使用Python+OpenCV进行图像处理(二)
梯度(Gradient)
在数学中,梯度用于几何地表示多变量函数图形的斜率。由于它是一个向量值函数,代表着方向和大小两种属性。在这里,我们也可以将同样的概念引入到图像的像素值中。图像梯度表示像素强度或颜色模式的方向变化,因此可以通过梯度来定位边缘。
# Apply gradient filtering
sobel_x = cv2.Sobel(img, cv2.CV_64F, dx = 1, dy = 0, ksize = 5)
sobel_y = cv2.Sobel(img, cv2.CV_64F, dx = 0, dy = 1, ksize = 5)
blended = cv2.addWeighted(src1=sobel_x, alpha=0.5, src2=sobel_y,
beta=0.5, gamma=0)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
Sobel运算同时使用高斯平滑和微分。我们通过cv2.Sobel()函数使用它,可以定义两个不同的方向:垂直方向(sobelx)和水平方向(sobely)。dx和dy表示导数。当dx = 1时,通过计算像素值沿水平方向的导数,从而进行图像滤波。
通过函数cv2.addWeighted()对sobelx和sobely的两种过滤器加权求和,可以实现两个方向上的梯度求解及图像滤波。上述代码中两种过滤器设定了相同的权重。
拉普拉斯运算使用的是x和y的二阶导数,数学表达式如下。
让我们通过下方代码更直观的看看这些处理后图像是什么样的。
# Plot the images
images = [sobel_x, sobel_y, blended, laplacian]
plt.figure(figsize = (20, 20))
for i in range(4):
plt.subplot(1, 4, i+1)
plt.imshow(images[i], cmap = 'gray')
plt.axis('off')
plt.show()
如上图所示,第一幅和第二幅图像均含有一个方向图样。在第一张图中,我们可以清楚地看到垂直方向上的边缘。在第二幅图中,我们可以看到水平线。第三幅和第四幅图像,两个方向的边缘都凸显出来了。
形态转换(Morpgological transformations)
通过滤波操作来转换图像的形态的技术称为形态变换(morphological transformation)。首先,让我们了解下腐蚀(erosion)和扩张(dilation)。
腐蚀(Erosion) 是一种缩小图形形态的技术,通常被应用在灰度图上。过滤器的形状可以是矩形、椭圆和交叉形状。通过过滤器删除给定区域下的全部0值。
代码实现如下:
img = cv2.imread('simpson.jpg')
# Create erosion kernels
kernel_0 = np.ones((9, 9), np.uint8)
kernel_1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
kernel_2 = cv2.getStructuringElement(cv2.MORPH_CROSS, (9, 9))
kernels = [kernel_0, kernel_1, kernel_2]
# Plot the images
plt.figure(figsize = (20, 20))
for i in range(3):
img_copy = img.copy()
img_copy = cv2.erode(img_copy, kernels[i], iterations = 3)
plt.subplot(1, 3, i+1)
plt.imshow(img_copy)
plt.axis('off')
plt.show()
上图形象的展示出不同滤波器下的不同缩放结果。我们可以看到三张分别使用基础(方形)滤波器、椭圆形滤波器和交叉滤波器处理过的结果图。可以看出其分别以“圆形”、“线性”和“对角线”的方式进行收缩。
扩张(Dilation)与侵蚀是相反的。它是一种对图形形态进行放大的操作。其作用也与侵蚀相反。实现代码如下。
# Apply dilation
kernel = np.ones((9, 9), np.uint8)
img_dilate = cv2.dilate(img, kernel, iterations = 3)
plt.figure(figsize = (20, 10))
plt.subplot(1, 2, 1); plt.imshow(img, cmap="gray")
plt.subplot(1, 2, 2); plt.imshow(img_dilate, cmap="gray")
plt.show()
开闭运算是侵蚀和扩张的混合形式。开运算是指先进行侵蚀,然后对侵蚀结果进行扩张操作。相对应的,闭运算是指先进行扩张,再进行侵蚀。
正如上图所示,闭运算一般用于检测图形的整体轮廓,开运算用于检测图形的子模式(subpatterns)。可以使用函数cv2.morphologyEx()来实现这些操作。参数op用于指定使用哪种运算类型(开/闭)。完整代码如下所示。
# Apply the operations
kernel = np.ones((9, 9), np.uint8)
img_open = cv2.morphologyEx(img, op= cv2.MORPH_OPEN, kernel)
img_close = cv2.morphologyEx(img, op= cv2.MORPH_CLOSE, kernel)
img_grad = cv2.morphologyEx(img, op= cv2.MORPH_GRADIENT, kernel)
img_tophat = cv2.morphologyEx(img, op= cv2.MORPH_TOPHAT, kernel)
img_blackhat = cv2.morphologyEx(img, op= cv2.MORPH_BLACKHAT, kernel)
# Plot the images
images = [img, img_open, img_close, img_grad,
img_tophat, img_blackhat]
fig, axs = plt.subplots(nrows = 2, ncols = 3, figsize = (15, 15))
for ind, p in enumerate(images):
ax = axs[ind//3, ind%3]
ax.imshow(p, cmap = 'gray')
ax.axis('off')
plt.show()
注意,原图中的手在分别使用开闭操作进行处理时会产生不同的结果。梯度滤波(MORPHCGRADIENT)运算是计算扩张结果图与腐蚀结果图之差。顶帽(Top-hat)运算(MORPHTOPHAT)是计算开运算结果图与原始图像之差,黑帽(Black Hot)运算(MORPH_BLACKHAT)是计算闭运算结果图与原始图像之差。形态学运算详细介绍参看(https://homepages.inf.ed.ac.uk/rbf/HIPR2/morops.htm)。
总结与展望
本篇介绍了OpenCV中几项比较常用的运算。下篇将介绍轮廓检测和人脸检测等检测技术。欢迎批评指正。
最新活动更多
-
即日-1.24立即参与>>> 【限时免费】安森美:Treo 平台带来出色的精密模拟
-
2月28日火热报名中>> 【免费试用】东集技术年终福利——免费试用活动
-
即日-3.21立即报名 >> 【深圳 IEAE】2025 消费新场景创新与实践论坛
-
4日10日立即报名>> OFweek 2025(第十四届)中国机器人产业大会
-
7.30-8.1火热报名中>> 全数会2025(第六届)机器人及智能工厂展
-
即日-2025.8.1立即下载>> 《2024智能制造产业高端化、智能化、绿色化发展蓝皮书》
推荐专题
发表评论
请输入评论内容...
请输入评论/评论长度6~500个字
暂无评论
暂无评论