前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV 轮廓检测

OpenCV 轮廓检测

作者头像
用户6021899
发布2019-09-02 17:56:46
1.8K0
发布2019-09-02 17:56:46
举报

在计算机视觉中,轮廓检测是另一个比较重要的任务。它包含的操作有计算矩形边界、圆形边界、多边形边界等等。

我们以下面的黑猫图为例来讲解如何利用OpenCV进行轮廓检测。

原图有点大,可以预先压缩一下方便屏幕显示:

代码语言:javascript
复制
import cv2
import numpy as np
img0 = cv2.imread("cat.jpg")
#img = cv2.pyrUp(img)#面积放大4倍
img0 = cv2.pyrDown(img0)#原图有点大,面积缩小到1/4

要做轮廓检测,背景须是黑色的灰度图,我们先来个黑白颠倒:

代码语言:javascript
复制
img =255- img0  #黑白颠倒,视情况(白色(亮)背景则需要颠倒,使背景变黑色

紧接着转灰度图:

代码语言:javascript
复制
gray = cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) #转灰度图。防止后续更改了原图,函数参数使用原图的拷贝

然后转二值图:

代码语言:javascript
复制
#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)

我们可以看到,原图底部灰色的文字在转二值图的时候被过滤掉了,不参与轮廓检测。

此时,我们可以检测轮廓点集(图中绿色的外边界点)

代码语言:javascript
复制
#2个返回值,分别是轮廓的点集(contours)和各层轮廓的索引(hierarchy) # openCV 4 , 否则注意版本差异!
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

之后,我们可以循环求得图形各部分的矩形轮廓线

代码语言:javascript
复制
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)

图中有些过小的轮廓也显示出来了,我们可以加点尺寸限制,将它们过滤掉:

代码语言:javascript
复制
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)模式

我们可以循环求得图形各部分的最小矩形轮廓线

代码语言:javascript
复制
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)

我们可以循环求得图形各部分的最小闭圆轮廓线

代码语言:javascript
复制
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)

我们可以循环求得图形各部分的多边形轮廓线

代码语言:javascript
复制
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)

通常我们会计算凸多边线轮廓

代码语言:javascript
复制
    #凸轮廓需要先加上下面这句
    hull = cv2.convexHull(c) # 计算凸轮廓多变形时需要先处理轮廓
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档