在本教程中,您将学习如何使用 OpenCV 库在 Python 中处理图像。
OpenCV 是一个用于实时图像处理的免费开源库。它用于处理图像、视频甚至直播,但在本教程中,我们将仅将处理图像作为第一步。在开始之前,我们先安装 OpenCV。
安装 OpenCV
要在系统上安装 OpenCV,请运行以下 pip 命令:
pip install opencv-python
现在OpenCV已经安装成功,我们已经准备好了。让我们来欣赏一些图像吧!
旋转图像
首先,导入cv2模块。
import cv2
现在要读取图像,请使用 cv2 模块的 imread() 方法,在参数中指定图像的路径并将图像存储在变量中,如下所示:
img = cv2.imread("pyimg.jpg")
该图像现在被视为矩阵,行和列值存储在 img 中。
实际上,如果你检查 img 的类型,它会给出以下结果:
>>>print(type(img))
<class 'numpy.ndarray'>
It’s a NumPy 数组!这就是为什么使用 OpenCV 进行图像处理如此简单。您一直在使用 NumPy 数组。
要显示图像,可以使用cv2的imshow()方法。
cv2.imshow('Original Image', img)
cv2.waitKey(0)
waitkey 函数将时间作为参数(以毫秒为单位)作为窗口关闭的延迟。这里我们将时间设置为零以永远显示窗口,直到我们手动关闭它。
要旋转此图像,您需要图像的宽度和高度,因为您将在旋转过程中使用它们,稍后您将看到。
height, width = img.shape[0:2]
shape 属性返回图像矩阵的高度和宽度。如果您打印
img.shape[0:2]
,您将得到以下输出:
好的,现在我们有了图像矩阵,我们想要得到旋转矩阵。为了获得旋转矩阵,我们使用getRotationMatrix2D()CV2的方法。语法为getRotationMatrix2D() is:
cv2.getRotationMatrix2D(center, angle, scale)
这里的center是旋转中心点,angle是以度为单位的角度,scale是使图像适合屏幕的缩放属性。
为了获得图像的旋转矩阵,代码如下:
rotationMatrix = cv2.getRotationMatrix2D((width/2, height/2), 90, .5)
下一步是借助旋转矩阵旋转我们的图像。
为了旋转图像,我们有一个名为的 cv2 方法包裹仿射它以原始图像、图像的旋转矩阵以及图像的宽度和高度作为参数。
rotatedImage = cv2.warpAffine(img, rotationMatrix, (width, height))
旋转后的图像存储在rotatedImage 矩阵中。要显示图像,请使用 imshow() ,如下所示:
cv2.imshow('Rotated Image', rotatedImage)
cv2.waitKey(0)
运行以上几行代码后,您将得到以下输出:
裁剪图像
首先,我们需要导入cv2模块并读取图像并提取图像的宽度和高度:
import cv2
img = cv2.imread("pyimg.jpg")
height, width = img.shape[0:2]
现在获取行和列的开始和结束索引。这将定义新创建的图像的大小。例如,从第 10 行开始到第 15 行将给出图像的高度。
同样,从第 10 列开始直到第 15 列将给出图像的宽度。
您可以通过指定总高度和总宽度的百分比值来获取起点。同样,要获取裁剪图像的终点,请指定百分比值,如下所示:
startRow = int(height*.15)
startCol = int(width*.15)
endRow = int(height*.85)
endCol = int(width*.85)
现在将这些值映射到原始图像。请注意,您必须将起始值和结束值转换为整数,因为映射时索引始终是整数。
croppedImage = img[startRow:endRow, startCol:endCol]
这里我们指定了行和列从开始到结束的范围。
现在在输出中显示原始图像和裁剪后的图像:
cv2.imshow('Original Image', img)
cv2.imshow('Cropped Image', croppedImage)
cv2.waitKey(0)
结果如下:
调整图像大小
要调整图像大小,可以使用 openCV 的 resize() 方法。在 resize 方法中,您可以指定 x 轴和 y 轴的值,或者指定图像大小的行数和列数。
导入并读取图像:
import cv2
img = cv2.imread("pyimg.jpg")
现在使用带有轴值的调整大小方法:
newImg = cv2.resize(img, (0,0), fx=0.75, fy=0.75)
cv2.imshow('Resized Image', newImg)
cv2.waitKey(0)
结果如下:
现在使用行和列值来调整图像大小:
newImg = cv2.resize(img, (550, 350))
cv2.imshow('Resized Image', newImg)
cv2.waitKey(0)
我们说我们需要 550 列(宽度)和 350 行(高度)。
结果将是:
调整图像对比度
在Python OpenCV模块中,没有专门的函数来调整图像对比度,但是官方文档OpenCV 提出了一个可以同时执行图像亮度和图像对比度的方程。
new_img = a * original_img + b
这里 a 是 alpha,它定义图像的对比度。如果a大于1,对比度就会更高。
如果a的值在0和1之间(小于1但大于0),则对比度会较低。如果a为1,则图像不会有对比度效果。
b 代表贝塔。 b 的值在 -127 到 +127 之间变化。
要在 Python OpenCV 中实现此方程,您可以使用 addWeighted() 方法。我们使用 addWeighted() 方法,因为它为 24 位彩色图像生成 0 到 255 范围内的输出。
addWeighted()方法的语法如下:
cv2.addWeighted(source_img1, alpha1, source_img2, alpha2, beta)
此语法将混合两个图像,第一个源图像 (source_img1) 的权重为 alpha1,第二个源图像 (source_img2)。
如果您只想在一张图像中应用对比度,则可以使用 NumPy 添加第二个图像源作为零。
让我们来看一个简单的例子。导入以下模块:
import cv2
import numpy as np
阅读原图:
img = cv2.imread("pyimg.jpg")
现在应用对比度。由于没有其他图像,我们将使用 np.zeros 它将创建一个与原始图像具有相同形状和数据类型的数组,但该数组将用零填充。
contrast_img = cv2.addWeighted(img, 2.5, np.zeros(img.shape, img.dtype), 0, 0)
cv2.imshow('Original Image', img)
cv2.imshow('Contrast Image', contrast_img)
cv2.waitKey(0)
在上面的代码中,亮度设置为 0,因为我们只想应用对比度。
原图与对比图对比如下:
使图像模糊
高斯模糊
要使图像模糊,可以使用 OpenCV 的 GaussianBlur() 方法。
GaussianBlur() 使用高斯核。内核的高度和宽度应该是正奇数。
然后你必须分别指定X和Y方向,即sigmaX和sigmaY。如果仅指定其中之一,则两者被视为相同。
考虑以下示例:
import cv2
img = cv2.imread("pyimg.jpg")
blur_image = cv2.GaussianBlur(img, (7,7), 0)
cv2.imshow('Original Image', img)
cv2.imshow('Blur Image', blur_image)
cv2.waitKey(0)
在上面的代码片段中,实际图像连同内核的高度和宽度以及 X 和 Y 方向一起传递给 GaussianBlur()。
原始图像和模糊图像的对比如下:
中值模糊
在中值模糊中,在内核区域内计算图像所有像素的中值。然后将中心值替换为所得中值。当图像中存在椒盐噪声时,使用中值模糊。
要应用中值模糊,可以使用 OpenCV 的中值模糊()方法。
考虑以下示例,图像中存在椒盐噪声:
import cv2
img = cv2.imread("pynoise.png")
blur_image = cv2.medianBlur(img,5)
这将在图像中应用 50% 的噪声以及中值模糊。现在显示图像:
cv2.imshow('Original Image', img)
cv2.imshow('Blur Image', blur_image)
cv2.waitKey(0)
结果如下:
原图与模糊处理后的另一张对比图:
检测边缘
要检测图像中的边缘,可以使用 cv2 的 Canny() 方法,该方法实现了 Canny 边缘检测器。 Canny 边缘检测器也称为最优检测器.
Canny() 的语法如下:
cv2.Canny(image, minVal, maxVal)
这里 minVal 和 maxVal 分别是最小和最大强度梯度值。
考虑以下代码:
import cv2
img = cv2.imread("pyimg.jpg")
edge_img = cv2.Canny(img,100,200)
cv2.imshow("Detected Edges", edge_img)
cv2.waitKey(0)
输出如下:
这是上述代码在另一张图像上的结果:
将图像转换为灰度(黑白)
将图像转换为灰度的简单方法是像这样加载它:
img = cv2.imread("pyimg.jpg", 0)
还有另一种使用 BGR2GRAY 的方法。
要将彩色图像转换为灰度图像,请使用 cv2 模块的 BGR2GRAY 属性。下面的示例对此进行了演示:
导入 cv2 模块:
import cv2
阅读图像:
img = cv2.imread("pyimg.jpg")
使用 cv2 模块的 cvtColor() 方法,该方法将原始图像和 COLOR_BGR2GRAY 属性作为参数。将结果图像存储在变量中:
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
显示原始图像和灰度图像:
cv2.imshow("Original Image", img)
cv2.imshow("Gray Scale Image", gray_img)
cv2.waitKey(0)
输出如下:
质心(斑点中心)检测
要找到图像的中心,第一步是将原始图像转换为灰度图像。我们可以像之前一样使用 cv2 的 cvtColor() 方法。
下面的代码演示了这一点:
import cv2
img = cv2.imread("py.jpg")
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
我们读取图像并将其转换为灰度图像。新图像存储在gray_img中。
现在我们必须计算图像的矩。使用cv2的moments()方法。在 moment() 方法中,将传递灰度图像,如下所示:
moment = cv2.moments(gray_img)
然后我们需要使用上面得到的矩来计算图像中心的 x 和 y 坐标:
X = int(moment ["m10"] / moment["m00"])
Y = int(moment ["m01"] / moment["m00"])
最后,我们得到了图像的中心。为了突出显示这个中心位置,我们可以使用 Circle 方法,它将在给定半径的给定坐标中创建一个圆。
Circle() 方法采用 img、创建圆的 x 和 y 坐标、大小、我们想要圆的颜色和厚度。
cv2.circle(img, (X, Y), 15, (205, 114, 101), 1)
在图像上创建圆圈。
cv2.imshow("Center of the Image", img)
cv2.waitKey(0)
原始图像是:
检测到中心后,我们的图像将如下所示:
要从图像中提取文本,您可以使用 Google Tesseract-OCR。您可以从这里下载link
然后你应该安装 pytesseract 模块,它是 Tesseract-OCR 的 Python 包装器。
pip install pytesseract
我们将从中提取文本的图像如下:
现在,让我们将此图像中的文本转换为字符串,并在输出中将文本显示为字符串:
导入 pytesseract 模块:
import pytesseract
设置Tesseract-OCR可执行文件的路径:
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract'
现在使用图像到字符串将图像转换为字符串的方法:
print(pytesseract.image_to_string('pytext.png'))
输出如下:
效果就像魅力!
检测并纠正文本倾斜
在本节中,我们将纠正文本倾斜。
原图如下:
导入模块 cv2、NumPy 并读取图像:
import cv2
import numpy as np
img = cv2.imread("pytext1.png")
将图像转换为灰度图像:
gray_img=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
使用反转灰度图像按位非:
gray_img=cv2.bitwise_not(gray_img)
使用NumPy的column_stack方法选择大于零的像素的x和y坐标:
coordinates = np.column_stack(np.where(gray_img > 0))
现在我们必须计算倾斜角度。我们将使用最小区域矩形()cv2 的方法返回从 -90 到 0 度的角度范围(其中不包括 0)。
ang=cv2.minAreaRect(coordinates)[-1]
文本区域的旋转角度将存储在 ang 变量中。现在我们为角度添加一个条件;如果文本区域的角度小于 -45,我们将添加 90 度,否则我们将角度乘以负数以使角度为正。
if ang<-45:
ang=-(90+ang)
else:
ang=-ang
计算文本区域的中心:
height, width = img.shape[:2]
center_img = (width / 2, height / 2)
现在我们有了文本倾斜的角度,我们将应用 getRotationMatrix2D() 来获取旋转矩阵,然后我们将使用 wrapAffine() 方法来旋转角度(前面已解释)。
rotationMatrix = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated_img = cv2.warpAffine(img, rotationMatrix, (width, height), borderMode = cv2.BORDER_REFLECT)
显示旋转后的图像:
cv2.imshow("Rotated Image", rotated_img)
cv2.waitKey(0)
颜色检测
让我们检测图像中的绿色:
导入用于图像的模块 cv2 和用于图像数组的 NumPy:
import cv2
import numpy as np
读取图像并使用 cvtColor() 将其转换为 HSV:
img = cv2.imread("pydetect.png")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
显示图像:
cv2.imshow("HSV Image", hsv_img)
现在为较低的绿色值和较高的绿色值创建一个 NumPy 数组:
lower_green = np.array([34, 177, 76])
upper_green = np.array([255, 255, 255])
使用 cv2 的 inRange() 方法检查给定的图像数组元素是否位于上下边界的数组值之间:
masking = cv2.inRange(hsv_img, lower_green, upper_green)
这将检测绿色。
最后,显示原始图像和结果图像:
cv2.imshow("Original Image", img)
cv2.imshow("Green Color detection", masking)
cv2.waitKey(0)
减少噪音
为了减少图像中的噪声,OpenCV 提供了以下方法:
- fastNlMeansDenoising():从灰度图像中去除噪声
- fastNlMeansDenoisingColored():从彩色图像中去除噪声
- fastNlMeansDenoisingMulti():去除灰度图像帧(灰度视频)中的噪声
- fastNlMeansDenoisingColoredMulti():与 3 相同,但适用于彩色帧
让我们在示例中使用 fastNlMeansDenoisingColored() :
导入cv2模块并读取图像:
import cv2
img = cv2.imread("pyn1.png")
应用去噪函数,该函数分别采用原始图像 (src)、目的地(在存储结果时没有保留)、滤波器强度、去除有色噪声的图像值(通常等于滤波器强度或 10) ),用于计算权重的模板块大小(以像素为单位)应始终为奇数(建议大小等于 7),以及以像素为单位的窗口大小以计算给定像素的平均值。
result = cv2.fastNlMeansDenoisingColored(img,None,20,10,7,21)
显示原始图像和去噪图像:
cv2.imshow("Original Image", img)
cv2.imshow("Denoised Image", result)
cv2.waitKey(0)
输出将是:
获取图像轮廓
轮廓是图像中连接在一起的曲线。曲线连接图像中的连续点。轮廓的目的是用来检测物体。
我们获取轮廓的原始图像如下:
考虑以下代码,我们使用 findContours() 方法来查找图像中的轮廓:
导入cv2模块:
import cv2
读取图像并将其转换为灰度图像:
img = cv2.imread('py1.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
求阈值:
retval, thresh = cv2.threshold(gray_img, 127, 255, 0)
使用 findContours() 获取图像(我们在此处传递了阈值)和一些属性。看findContours() 官方.
img_contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
使用drawContours()方法在图像上绘制轮廓:
cv2.drawContours(img, img_contours, -1, (0, 255, 0))
显示图像:
cv2.imshow('Image Contours', img)
cv2.waitKey(0)
结果将是:
从图像中删除背景
要从图像中删除背景,我们将找到轮廓来检测主要对象的边缘,并为背景创建一个带有 np.zeros 的掩模,然后使用按位与操作员。
考虑下面的例子:
导入模块(NumPy 和 cv2):
import cv2
import numpy as np
读取图像并将图像转换为灰度图像:
img = cv2.imread("py.jpg")
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
求阈值:
_, thresh = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
在threshold()方法中,最后一个参数定义阈值的样式。请参阅官方文档OpenCV 阈值.
找到图像轮廓:
img_contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2]
对轮廓进行排序:
img_contours = sorted(img_contours, key=cv2.contourArea)
for i in img_contours:
if cv2.contourArea(i) > 100:
break
使用 np.zeros 生成掩码:
mask = np.zeros(img.shape[:2], np.uint8)
绘制轮廓:
cv2.drawContours(mask, [i],-1, 255, -1)
应用按位与运算符:
new_img = cv2.bitwise_and(img, img, mask=mask)
显示原始图像:
cv2.imshow("Original Image", img)
显示结果图像:
cv2.imshow("Image with background removed", new_img)
cv2.waitKey(0)
如您所见,使用 OpenCV 时图像处理很有趣。我希望您觉得本教程有用。继续回来。
谢谢。