作者:Muhammad Junaid Khalid
翻译:老齐
与本文相关的图书推荐:《数据准备和特征工程》
概要
在本文中,将学习如何使用Python语言进行图像处理,我们不会局限于一个单独的库或框架,然而,有一个库的使用率将会是最高的,那就是OpenCV。我们一开始会讨论一些图像处理,然后继续探讨不同的应用/场景,也就是图像处理的用武之地。开始吧!
什么是图像处理?
在深入研究图像处理的方法之前,重要的是要了解什么是图像处理,特别是这项技术在处理大量图片方面的角色。图像处理完整的说法是“数字图像处理”,经常使用图像处理的领域是“计算机视觉”。对这两个术语不要混淆,图像处理算法和计算机视觉(CV)算法都以图像为输入,然而,在图像处理中,输出也是图像,而在计算机视觉中,输出可以是关于图像的一些特征或信息。
为什么需要图像处理?
我们收集或生成的数据大部分是原始数据,也就是说,由于一些可能的原因,这些数据不适合直接用于应用程序。因此,我们需要首先分析它,执行必要的预处理,然后使用它——特别推荐《数据准备和特征工程》,此书即为这方面最佳读物。
例如,我们正在尝试构建一个关于猫的分类器。我们的程序会把一个图像作为输入,然后告诉我们这个图像是否包含一只猫。构建这个分类器的第一步是收集数百张含有猫的图片。一个常见的问题是,收集的所有图片的大小都不相同,因此在将它们提供给模型进行训练之前,需要调整它们的大小或者把它们进行预处理,使尺寸符合标准。
为什么图像处理对于任何计算机视觉应用序都是必不可少的?以上提到的只是众多原因之一。
预备知识
为了轻松地学习本文内容,你需要已经具备如下知识。
首先,应该具备一定的编程语言技能,本文使用的是Python语言,如果尚未掌握此语言,推荐阅读《跟老齐学Python:轻松入门》或《Python大学实用教程》。
其次,你应该了解什么是机器学习以及它的基本工作原理。因为在本文中我们将使用一些机器学习算法来进行图像处理。
另外,如果你之前接触过或掌握了OpenCV的基本知识,也会有所帮助。但这不是必需的。
还有,你一定要了解图像在内存中究竟是如何表示的。每幅图像都由一组像素表示,即像素值矩阵。对于灰度图像,像素值的范围是0到255,它们表示该像素的强度。例如,如果你有一个20×20维的图像,它将由一个20x20的矩阵表示(像素值总共是400)。
如果你正在处理彩色图像,你应该知道它有三个通道——红、绿、蓝(RGB)。因此,一个彩色图像有三个这样的矩阵。
安装
注意: 由于我们将通过Python使用OpenCV,所以你必须会实用它,前面推荐了关于Python的书籍。下面依次说明在不同操作系统中OpenCV的安装方法:
- Windows
$ pip install opencv-python
复制代码
- MacOS
$ brew install opencv3 --with-contrib --with-python3
复制代码
- Linux
$ sudo apt-get install libopencv-dev python-opencv
复制代码
要检查是否安装成功,请在Python交互模式中运行以下命令:
import cv2
复制代码
必备的基础知识
在进行图像处理之前,要先做一些准备。
在本文中,我们将使用以下图像:
注意: 为了在本文中显示该图像,对其进行了缩放,但是我们使用的图像原始大小约为1180x786。
你可能注意到图像现在是彩色的,这意味着它由三个颜色通道表示,即红色、绿色和蓝色。我们将把图像转换成灰度,并使用下面的代码将图像分割成单独的通道。
找到图像细节
使用
imread()
函数加载图像后,我们可以得到关于它的一些简单属性,比如像素的数量和尺寸:
import cv2
img = cv2.imread('rose.jpg')
print("Image Properties")
print("- Number of Pixels: " + str(img.size))
print("- Shape/Dimensions: " + str(img.shape))
复制代码
Output:
Image Properties
- Number of Pixels: 2782440
- Shape/Dimensions: (1180, 786, 3)
复制代码
将图像分割成单独的通道
现在,我们将使用OpenCV将图像分割成红色、绿色和蓝色的部分,并显示它们:
from google.colab.patches import cv2_imshow
blue, green, red = cv2.split(img) # Split the image into its channels
img_gs = cv2.imread('rose.jpg', cv2.IMREAD_GRAYSCALE) # Convert image to grayscale
cv2_imshow(red) # Display the red channel in the image
cv2_imshow(blue) # Display the red channel in the image
cv2_imshow(green) # Display the red channel in the image
cv2_imshow(img_gs) # Display the grayscale version of image
复制代码
为了简单起见,我们只显示灰度图像。
图像阈值
阈值的概念非常简单。正如上面在图像表示中所讨论的,像素值可以是0到255之间的任何值。假设我们想要将一幅图像转二值化,即指定一个像素值为0或1。为此,我们可以设置阈值。例如,如果阈值(T)为125,那么所有大于125的像素将被赋值为1,所有小于或等于该值的像素将被赋值为0。下面,我们通过代码来更好地理解它。
将下面的图像用上述方法进行转换:
import cv2
# Read image
img = cv2.imread('image.png', 0)
# Perform binary thresholding on the image with T = 125
r, threshold = cv2.threshold(img, 125, 255, cv2.THRESH_BINARY)
cv2_imshow(threshold)
复制代码
输出:
正如你所看到的, 二值化之后,出现了两个区域,即黑色区域(像素值0)和白色区域(像素值1)。原来, 我们设置的阈值正好在图像的中间,这就是为什么黑白值在那里被分割。
应用
1:去除图像中的噪声
现在你已经对图像处理的概念和用途有了基本的了解,接下来让我们来了解一下它的一些具体应用。
在大多数情况下,我们收集的原始数据有噪声,也就是说,不需要的特征使图像很难被感知。虽然这些图像可以直接用于特征抽取,但是算法的准确性会受到很大的影响。这就是为什么在将图像传递给算法以获得更好的精度之前,要对图像进行处理的原因。
有许多不同类型的噪声,如高斯噪声,椒盐噪声等。我们可以通过应用滤波器来去除图像中的噪声,或者至少将其影响降到最低。在滤波器方面也有很多选择,每一个滤波器都有不同的优点。因此,对于特定类型的噪声来说,总有一个是最好的。
为了更好地理解这一点,我们将在上面的玫瑰色图像的灰度版本中添加“盐和胡椒粉”噪声,然后尝试使用不同的滤波器去除图像中的噪声,看看哪一个最适合这种类型。