轮廓检测

Posted missdx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了轮廓检测相关的知识,希望对你有一定的参考价值。

图像轮廓

 cv2.findContours(img,mode,method) 

  • mode :轮廓检测的模式
    • RETR_EXTERNAL :只检索最外面的轮廓;
    • RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
    • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
    • RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;
  • method:轮廓逼近方法
    • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
    • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

技术图片


  •  绘制轮廓

import cv2 as cv
import numpy as np


img = cv.imread(contours.png)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) # 为了更高的准确率,使用二值图像。当值大于127时,值赋予255,否则为0.
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
draw_img = img.copy()# 之所以copy原图,是因为绘制轮廓时,原图会被改变。
finally_img = cv.drawContours(draw_img, contours, -1, (0, 0, 255), 2) # 绘制轮廓。传入绘制图像,轮廓,轮廓索引,颜色模式((0, 0, 255)按照BGR来说就是红色),线条厚度

res = np.hstack((img, finally_img))
cv.imshow(img, res)
cv.waitKey(0)
cv.destroyAllWindows()

技术图片

 

  •  轮廓特征

    •   面积

 cv2.contourArea(参数) 

    •   周长

 cv2.arcLength(参数,True) # True表示闭合的 

import cv2 as cv
import numpy as np


img = cv.imread(contours.png)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) # 为了更高的准确率,使用二值图像。当值大于127时,值赋予255,否则为0.
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[0]
Area = cv.contourArea(cnt)
Length = cv.arcLength(cnt, True)
print(面积是:{},周长是:{}.format(Area, Length))

技术图片

 

  •  轮廓近似

技术图片

 

假设曲线AB是一段轮廓。现在我们要对它做轮廓近似。

首先我们设置一个阈值T。

第一步,先找到垂线DC,DC是垂直于AB的最长垂线,只有一条。判断DC是否大于T,若小于T,则AB就是近似轮廓,否则继续下一步。

第二步,连接AD和DB,同理找到最长垂线EG和FH。判断他们是否大于阈值T,若小于阈值,则AD或者DB就是近似轮廓,否则继续找。

 cv2.approxPolyDP(传入图, 阈值, True) :轮廓近似函数

import cv2 as cv
import numpy as np


img = cv.imread(contours2.png)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转换为灰度图
ret, thresh = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY) #二值图
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) # 找到轮廓图
cnt = contours[0] # 获取第一个轮廓,这是一个外轮廓,还有一个内轮廓。
draw_img1 = img.copy()
res1 = cv.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2) # 绘制第一个轮廓
epsilon = 0.1*cv.arcLength(cnt, True) # 设置一个阈值,阈值取的是轮廓周长的0.1,0.1可改变成其他值。
approx = cv.approxPolyDP(cnt, epsilon, True)
draw_img2 = img.copy()
res2 = cv.drawContours(draw_img2, [approx], -1, (0, 0, 255), 2)
res = np.hstack((res1, res2))
cv.imshow(res, res)
cv.waitKey(0)
cv.destroyAllWindows()

技术图片

 

  •  边界矩形

 x, y, w, h = boundingRect(输入图像) 

  • 计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的。
  • 返回四个值,分别是x,y,w,h;x,y是矩阵左上点的坐标,w,h是矩阵的宽和高

 rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) 

  • 绘制矩形
import cv2 as cv
import numpy as np


img = cv.imread(contours2.png)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[0]

x, y, w, h = cv.boundingRect(cnt)
rect_img = cv.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv.imshow(img, rect_img)
cv.waitKey(0)
cv.destroyAllWindows()

技术图片

 

  •  外接圆

 (x, y), radius = cv.minEnclosingCircle(cnt) # 得到中心点和半径 

 circle_img = cv.circle(img, center, radius, (0, 0, 255), 2) # 绘制边界圆 

import cv2 as cv
import numpy as np


img = cv.imread(contours.png)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
binary, contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
cnt = contours[0]

x, y, w, h = cv.boundingRect(cnt)
(x, y), radius = cv.minEnclosingCircle(cnt) # 得到中心点和半径
center = (int(x), int(y))
radius = int(radius)
circle_img = cv.circle(img, center, radius, (0, 0, 255), 2) # 绘制边界圆
cv.imshow(img, circle_img)
cv.waitKey(0)
cv.destroyAllWindows()

技术图片

 

以上是关于轮廓检测的主要内容,如果未能解决你的问题,请参考以下文章

youcans 的 OpenCV 例程200篇194.寻找图像轮廓(cv.findContours)

youcans 的 OpenCV 例程200篇195.绘制图像轮廓(cv.drawContours)

OpenCV实战(15)——轮廓检测详解

OpenCV学习代码记录——轮廓(contour)检测

OpenCV入门指南第六篇 轮廓检测 下

图像轮廓检测错误:OpenCV、C++