订阅
纠错
加入自媒体

使用Python+OpenCV进行图像处理(二)

2019-04-26 08:49
磐创AI
关注

梯度(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  2  
声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

人工智能 猎头职位 更多
扫码关注公众号
OFweek人工智能网
获取更多精彩内容
文章纠错
x
*文字标题:
*纠错内容:
联系邮箱:
*验 证 码:

粤公网安备 44030502002758号