在计算机视觉中,轮廓检测是另一个比较重要的任务。它包含的操作有计算矩形边界、圆形边界、多边形边界等等。
我们以下面的黑猫图为例来讲解如何利用OpenCV进行轮廓检测。
原图有点大,可以预先压缩一下方便屏幕显示:
import cv2
import numpy as np
img0 = cv2.imread("cat.jpg")
#img = cv2.pyrUp(img)#面积放大4倍
img0 = cv2.pyrDown(img0)#原图有点大,面积缩小到1/4
要做轮廓检测,背景须是黑色的灰度图,我们先来个黑白颠倒:
img =255- img0 #黑白颠倒,视情况(白色(亮)背景则需要颠倒,使背景变黑色
紧接着转灰度图:
gray = cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) #转灰度图。防止后续更改了原图,函数参数使用原图的拷贝
然后转二值图:
#threshold(src, thresh, maxval, type[, dst]) -> retval, dst
ret, thresh = cv2.threshold( gray, 100, 255,cv2.THRESH_BINARY) #转二值图,亮度小于100的变为0,打于的变为255
cv2.imshow("binary", thresh)
我们可以看到,原图底部灰色的文字在转二值图的时候被过滤掉了,不参与轮廓检测。
此时,我们可以检测轮廓点集(图中绿色的外边界点)
#2个返回值,分别是轮廓的点集(contours)和各层轮廓的索引(hierarchy) # openCV 4 , 否则注意版本差异!
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
之后,我们可以循环求得图形各部分的矩形轮廓线:
for c in contours: #对于每一个轮廓
#无倾斜的 边界矩形框
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(img0, (x,y), (x+w, y+h), (255,0,0), 2) # 颜色均为(B,G,R)模式
cv2.imshow("contours", img0)
图中有些过小的轮廓也显示出来了,我们可以加点尺寸限制,将它们过滤掉:
W,H = img0.shape[0], img0.shape[1]
for c in contours: #对于每一个轮廓
#无倾斜的 边界矩形框
x, y, w, h = cv2.boundingRect(c)
if w>0.1 *W and h >0.1*H:
cv2.rectangle(img0, (x,y), (x+w, y+h), (255,0,0), 2) # 颜色均为(B,G,R)模式
我们可以循环求得图形各部分的最小矩形轮廓线:
W,H = img0.shape[0], img0.shape[1]
for c in contours: #对于每一个轮廓 # 可倾斜的最小边界矩形框
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)#计算出来的顶点,浮点型
box = np.int0(box) #4个顶点坐标转化为整数
#过滤太小的
d = np.linalg.norm(box[0]-box[2]) #对角线长度
if d> 0.075* np.sqrt(W**2+H**2):
cv2.drawContours(img0, [box], 0, (0,0,255),2)
cv2.imshow("contours", img0)
我们可以循环求得图形各部分的最小闭圆轮廓线:
W,H = img0.shape[0], img0.shape[1]
for c in contours: #对于每一个轮廓 #最小边界圆
(x,y) , radius = cv2.minEnclosingCircle(c)
center, radius = (int(x), int(y)) , int(radius)
if radius > 0.05* np.sqrt(W**2+H**2):
cv2.circle(img0, center, radius, (255,255,0),3)
cv2.imshow("contours", img0)
我们可以循环求得图形各部分的多边形轮廓线:
for c in contours: #对于每一个轮廓
epsilon = 0.001*cv2.arcLength(c, True) #epsilon为近似轮廓多边形周长与原轮廓周长的最大差值
approxPloy = cv2.approxPolyDP(c, epsilon, True) #True表示 多边形封闭
cv2.polylines(img0, [approxPloy], True, (255, 0, 255), 2) #
cv2.imshow("contours", img0)
通常我们会计算凸多边线轮廓:
#凸轮廓需要先加上下面这句
hull = cv2.convexHull(c) # 计算凸轮廓多变形时需要先处理轮廓
本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!