计算机视觉技术- 图像轮廓

计算机视觉技术- 图像轮廓


轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点(沿边界)的曲线。轮廓是用于形状分析以及对象检测和识别的有用工具。为了获得更高的准确性,最好使用二进制图像。因此,在找到轮廓之前,请应用阈值或canny边缘检测。在 OpenCV 中,找到轮廓就像从黑色背景中找到白色物体。因此请记住,要找到的对象应该是白色,背景应该是黑色。

查找轮廓

findcontour()
函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法。输出等高线和层次结构。轮廓是图像中所有轮廓的 Python 列表。每个单独的轮廓是一个(x,y)坐标的 Numpy 数组的边界点的对象。

操作如下:以灰度的模式读取一个蓝色石头的图片,进行二值化阀值运算,找出所有轮廓,最后显示出原始、二值化以及闭运算后的图像。

参考代码

import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('../data/blueStone.jpg')
plt.figure(figsize=(10,5))
imgBGR = cv.cvtColor(img, cv.COLOR_RGB2BGR)
imgGRAY = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
ret, binary = cv.threshold(imgGRAY, 10, 255, cv.THRESH_BINARY) # gray to binary
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
print(len(contours))
plt.subplot(1,2,1),plt.imshow(imgBGR)
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,2,2),plt.imshow(binary,cmap = 'gray')
plt.title('Binary Image'), plt.xticks([]), plt.yticks([])
  • contours:是检测到的轮廓座标内容。
  • hierarchy:图像拓扑信息。与轮廓的数量一样多。对于第 i
    个轮廓,hierarchy[i][0]、hierarchy[i][1]、hierarchy[i][2] 和 hierarchy[i][3] 被设置为0。基于相同层次级别的下一个和前一个轮廓的轮廓中的索引,分别是第一个子轮廓和父轮廓。如果轮廓 i 没有下一个、上一个、父级或嵌套轮廓,则 hierarchy[i] 的相应元素将为负。

下图显示原图与经过二值化的图片,而在 findContours() 运算的结果却有 214 个轮廓,右上角有一个很明显的区域,但那个部分并非是石头部分,所以可以使用ROI技术,来改善这个算法。

在这里插入图片描述
图 1. 显示查找蓝色石头轮廓的个数

参考代码

plt.figure(figsize=(10,5))
imgROI = imgBGR[120:720, 140:670]
binROI = binary[120:720, 140:670] # ROI
contours, hierarchy = cv.findContours(binROI, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
print(len(contours))
plt.subplot(1,2,1),plt.imshow(imgROI)
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,2,2),plt.imshow(binROI, cmap = 'gray')
plt.title('Binary Image'), plt.xticks([]), plt.yticks([])
plt.show()

优化的结果,将轮廓从 214 降低到 43 个。

在这里插入图片描述
图 2. 使用 ROI 查找蓝色石头轮廓的个数

绘制轮廓

要绘制轮廓,请使用 drawContours() 函数。只要有边界点,它也可以用来绘制任何形状。它的第一个参数是源图像,第二个参数是应该作为 Python 列表传递的轮廓,第三个参数是轮廓的索引(在绘制单个轮廓时有用。要绘制所有轮廓,请传递 -1,其余参数是颜色,厚度等等。

操作如下:使用开运算消除噪音,找出所有轮廓,优化后只有 23 个,最后在原始图片绘制轮廓的图像。

参考代码

# 开运算
erode_hsv = cv.erode(binROI, None, iterations=1)
dilated_hsv = cv.dilate(erode_hsv, None, iterations=1)
displyImg=imgROI.copy()
#获取轮廓
_,binary=cv.threshold(dilated_hsv,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
image=cv.drawContours(displyImg,contours,-1,(0,255,0),1)#画出轮廓
print(len(contours))
plt.imshow(image)
plt.show()

优化的结果,将轮廓从 214 降低到 43 个。

在这里插入图片描述
图 3. 开运算优化并绘制轮廓

参考资料

  • OpenCV API, https://docs.opencv.org/
  • matplotlib.pyplot.subplot, https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplot.html#matplotlib.pyplot.subplot
  • matplotlib.pyplot.imshow, https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html

猜你喜欢

转载自blog.csdn.net/m0_50614038/article/details/129495364