opencv-边缘检测+获取轮廓

一、边缘检测

OpenCV提供很多边缘检测的滤波函数,比如 Laplacian,Sobel,Scharr,Canny等。这些函数会将非边缘区域转化为黑色,将边缘区域转为白色或其他颜色**。但是,这些函数容易将噪声错误的识别为边缘,所以在进行边缘检测之前应该先对图像进行模糊处理。**

import cv2
 
img = cv2.imread('car.jpg', flags=cv2.IMREAD_GRAYSCALE)
GBlur = cv2.GaussianBlur(img, (3, 3), 0)
canny = cv2.Canny(GBlur, 50, 150)
cv2.imshow('img', img)
cv2.imshow('canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

二、边界框、最小矩形区域、最小闭圆的轮廓

用cv2.findContours()方法来寻找轮廓值

0.函数原型

cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None)

1.函数参数

image

表示输入的图片,注意必须为二值图片。若输入图片为彩色,必须先进行灰度化和二值化。

mode

表示轮廓的检索模式:

参数 作用
cv2.RETR_EXTERNAL 只检测外轮廓
cv2.RETR_LIST 检测的轮廓不建立等级关系
cv2.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息
cv2.RETR_TREE 建立一个等级树结构的轮廓
method

表示轮廓的近似办法:

参数 作用
cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2), abs(y2-y1))<=1
cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个 矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1 使用teh-Chinl chain 近似算法
cv2.CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法

2.函数返回值

cv2.findContours()函数返回两个值,一个是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy。

contours:

cv2.findContours()函数首先返回一个list,list中每个元素(本例为2个)都是图像中的一个轮廓信息,list中每个元素(轮廓信息)类型为ndarray。len(contours[1]) 表示第一个轮廓储存的元素个数,即该轮廓中储存的点的个数。本例第一个轮廓为矩形,轮廓中有4个点,这是因为当参数mode 设置成: cv2.CHAIN_APPROX_SIMPLE ,轮廓中并不是存储轮廓上所有的点,而是只存储可以用直线描述轮廓的点的个数,比如一个“正立”的矩形,只需4个顶点就能描述轮廓了。

print(type(contours))                         # 输出为:
print(type(contours[0]))                      # 输出为:
print(len(contours))                          # 图像中轮廓的数量,输出为:2
print(len(contours[1]))                       # 轮廓1(矩形)中的元素(点)的数量, 输出为:4

由于我们知道返回的轮廓有两个,因此可通过

cv2.drawContours(img,contours,0,(0,0,255),3)

cv2.drawContours(img,contours,1,(0,255,0),3)
分别绘制两个轮廓,关于该参数可参见:cv2.drawContours() 轮廓绘制

hierarchy:

3.函数实例

import cv2
import numpy as np
img=cv2.imread('test.jpg')
imgray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(imgray,127,255,0)
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(np.size(contours))  #   得到该图中总的轮廓数量
print(contours[0])   #  打印出第一个轮廓的所有点的坐标, 更改此处的0,为0--(总轮廓数-1),可打印出相应轮廓所有点的坐标
print(hierarchy) #打印出相应轮廓之间的关系
img=cv2.drawContours(img,[contours[0]],-1,(0,255,0),10)  #标记处编号为0的轮廓,此处img为三通道才能显示轮廓
cv2.imshow('drawimg',img)
cv2.waitKey()
cv2.destroyAllWindows()

opencv-边缘检测+获取轮廓_第1张图片

2.常见错误

使用中可能会出现错误信息:
ValueError: not enough values to unpack (expected 3, got 2)

原因是:
OpenCV2和OpenCV4中:
findContours()返回2个值,分别为
—轮廓的点集(contours)
—各层轮廓的索引(hierarchy)
OpenCV3中:
findContours()返回3个值,分别为
—处理的图像(image)
—轮廓的点集(contours)
—各层轮廓的索引(hierarchy)

参考

1.https://www.cnblogs.com/guobin-/p/10842486.html
2.https://blog.csdn.net/rookie_wei/article/details/83027808
3.https://blog.csdn.net/Easen_Yu/article/details/89365497

你可能感兴趣的:(图像处理)