【笔记】OpenCV3 图形处理-轮廓检测(四)

本文介绍了在计算机视觉中如何使用OpenCV3进行轮廓检测,包括图像二值化、固定阈值和自适应阈值二值化方法,并展示了如何找到并绘制轮廓。通过对不同图像的应用,探讨了轮廓检测的效果和局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在计算机视觉中,轮廓检测是一个比较重要的任务

还有一些相关的操作:计算多边形边界、形态逼近和计算感兴趣区域,后面再慢慢研究。。。

先来初步尝试下轮廓检测


检测前,先对图像进行处理

  • 图像二值化

图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

  • threshold  固定阈值二值化

def threshold(src, thresh, maxval, type, dst=None)

其中:

src:  输入图,只能输入单通道图像,通常来说为灰度图

thresh:设定的阈值

maxval: 当灰度值大于或小于阈值时,将灰度值赋成的值

type:       二值化的方式


可以有的方式有:

cv2.THRESH_BINARY = 0  大于阈值的部分被置为255,小于部分被置为0
cv2.THRESH_BINARY_INV = 1 大于阈值部分被置为0,小于部分被置为255
cv2.THRESH_MASK = 7
cv2.THRESH_OTSU = 8
cv2.THRESH_TOZERO = 3 小于阈值部分被置为0,大于部分保持不变
cv2.THRESH_TOZERO_INV = 4 大于阈值部分被置为0,小于部分保持不变
cv2.THRESH_TRIANGLE = 16
cv2.THRESH_TRUNC = 2  大于阈值部分被置为thresh,小于部分保持原样


看看有些啥效果。。。

import cv2
import matplotlib.pyplot as plt

#灰度读取
img = cv2.imread('img/Lena.jpg', cv2.IMREAD_GRAYSCALE)

ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_MASK)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_OTSU)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh6 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
ret, thresh7 = cv2.threshold(img, 127, 255, cv2.THRESH_TRIANGLE)
ret, thresh8 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)


titles = ['img', 'BINARY','BINARY_INV','MASK','OTSU','TOZERO','TOZERO_INV','TRIANGLE','TRUNC']
imgs = [img,thresh1,thresh2,thresh3,thresh4,thresh5,thresh6,thresh7,thresh8]

for i in range(9):
    plt.subplot(3,3,i+1),plt.imshow(imgs[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

补充一直二值化的图,THRESH_OTSU

 


  • adaptiveThreshold  自适应阈值二值化

自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点的阈值

def adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)

其中:

src:  输入图,只能输入单通道图像,通常来说为灰度图

maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值

adaptiveMethod:       自适应计算方法: cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值

                                                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和

thresholdType:       二值化的方式  cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV

blockSize:       规定区域大小

C: 常数C,阈值等于均值或者加权值减去这个常数

返回值只有一个

thresh1 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
thresh2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,11,2)
thresh3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
thresh4 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,11,2)

titles = ['img', 'MEAN_C','MEAN_C_INV','GAUSSIAN_C','GAUSSIAN_C_INV']
imgs = [img,thresh1,thresh2,thresh3,thresh4]

for i in range(5):
    plt.subplot(3,3,i+1),plt.imshow(imgs[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

 


  • cv2.findContours() 寻找图像的轮廓 

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

其中:

image:输入图像(会被修改),要求是二值图像

mode:轮廓的检索模式:

cv2.RETR_EXTERNAL只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层
cv2.RETR_TREE建立一个等级树结构的轮廓

 

 

 

 

 

method:轮廓近似办法

cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标
cv2.CHAIN_APPROX_TC89_L1使用teh-Chini近似算法
CV_CHAIN_APPROX_TC89_KCOS使用teh-Chini近似算法

 

 

 

 

 

返回值:轮廓数据,轮廓对应的属性

 


  • cv2.drawContours()  绘制轮廓

def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

其中:

image:输入/输出图像,指明在哪个图像上绘制轮廓。并且该函数会修改源图像image。

contours:使用findContours检测到的轮廓数据

contourIdx:绘制轮廓的索引变量(表示绘制第几个轮廓),如果为负值则绘制所有输入轮廓。

color:轮廓颜色。

thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制。

lineTpye:线条类型,有默认值LINE_8

hierarchy:可选层次结构信息

maxLevel:用于绘制轮廓的最大等级。

offset:轮廓偏移参数,用制定偏移量offset=(dx, dy)给出绘制轮廓的偏移量。


做个例子将上面的方法连贯起来

生成图片——二值化——查找轮廓——绘制轮廓

img = np.zeros((400,400), dtype=np.uint8)

img[50:300,50:100] = 255
img[150:200,50:200] = 255
img[50:300, 150:200] = 255

img[150:200,250:300] = 255

绘制几个方框,设置为白色

ret, thresh = cv2.threshold(img, 127, 255, 0)
# cv2.THRESH_BINARY = 0

image, contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

img = cv2.drawContours(color, image, -1, (0,255,0), 2)
cv2.imshow('color', color)

成功标记处轮廓。。。。

 


  • 换个图片试试

img = cv2.imread('img/mei.jpg',cv2.IMREAD_COLOR)
cv2.imshow('img', img)

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (11,11), 0)

ret, thresh = cv2.threshold(gray, 127, 255, 0)
image, contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
img = cv2.drawContours(img, image, -1, (0,255,0), 2)

cv2.imshow('color', img)

百度图片里面找了张妹子图。。。  测试下。。。  感觉还是有点菜啊。。。。  有待继续研究。。。。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值