OpenCV之图像轮廓

什么是图像轮廓?
具有相同 颜色(在彩色图片中)或 强度(灰度图像要转变为二值化图像)的 连续点的曲线

图像轮廓的作用:
1.可以用于图形分析
2.物体的识别与检测
以下这张图中被红色线描出部分都可以称之为轮廓

OpenCV之图像轮廓
注意点:
1.为了检测的准确性,需要先对图像进行二值化或Canny操作
2.画轮廓是会修改输入图像,所以为了不避免破坏原来图像可以先进行深拷贝
轮廓查找api :
findContours (img, mode, ApproximationMode…),两个返回值 :contours(查找到所有轮廓的列表,不会绘制出来,只是以列表的形式存储所有轮廓的点)和 hierarchy(层级。表示查找到的所有轮廓有无层级或前后关系)。

mode : 对查找到的轮廓进行如何的组织.可以分级,也可以把所有的轮廓放在一个列表里,或者将轮廓按照树形结构进行存储。
RETR_EXTERNAL = 0, 表示只检测外轮廓(只检测最大的外圈轮廓,一般用于只想检测大物体)
RETR_LIST = 1,检测的轮廓不建立等级关系,所有轮廓放在一个列表中。
RETR_CCOMP = 2,有层级,每层最多两级
RETR_TREE = 3, 按照树形存储轮廓,从右到左一层一层检测(常用)

ApproximationMode:近似查找轮廓。
CHAIN_APPROX_NONE,保存所有轮廓上的点
CHAIN_APPROX_SIMPLE,只保存角点(常用)

绘制轮廓api :
drawContours(img, contours, contoursIdx, color, thickness,…)
img:在哪张图片上进行展示
contours :轮廓坐标点,也就是findContours第一个返回值。
contoursIdx:轮廓顺序号,拿到的所有轮廓坐标点会按照储存方式有个顺序,从0开始【-1表示绘制所有轮廓】
color :轮廓的颜色,书写为(0,0,255)
thickness :显卡,1为细线,2为粗线,-1表示对整个轮廓进行填充
以下是实例代码

import cv2
import numpy as np
#读文件
img = cv2.imread('d:\\STUDY_OPENCV\\img\\rct.png')
#转变成单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#二值化,第一个返回值是执行的结果和状态是否成功,第二个返回值才是真正的图片结果
ret,binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
#轮廓查找,第一个返回值是轮廓,第二个是层级
contours, hierarchy =  cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#绘制轮廓
cv2.drawContours(img, contours, -1, (0,0,255), 1)#改变的是img这张图
print(contours)

cv2.imshow('img',img)
cv2.imshow('binary',binary)
cv2.waitKey(0)

OpenCV之图像轮廓

获取轮廓的面积和周长

根据轮廓的面积,太碎小就去除
轮廓面积api:
countourArea(contour),contour指列表中具体的某一个轮廓,而且算出的面积是图像中的面积,不是实际的。

轮廓的周长api :
arcLength( curve , closed )
curve :计算的轮廓
closed :轮廓是否闭合,若闭合设为True,否则设为False

#计算面积
area = cv2.contourArea(contours[0])
#计算周长
len = cv2.arcLength(contours[0],True)
print("len = ",len)
print("area=%d"%(area))

多边形逼近与凸包

多边形逼近:如下图左边把手的一些特征点标出来使其画出手的大致形状,而不是沿着手边缘把所有像素点保存下来。这就叫多边形逼近,此类方法可以减少保存大量数据,并且根具实际情况调整精度(即特征点的个数)。

凸包 :如下图右边所示描绘物体的一个整个突出的轮廓。

OpenCV之图像轮廓
多边形逼近api:
apporxPolyDP(curve, epsilon, closed)
curve : 轮廓查找中具体一个轮廓
epsilon :精度,数字越小代表精度越低,表示和图形轮廓越吻合
closed :是否是闭合的轮廓

凸包 api :
convexHull(points, clockwise, …)
points : 点,某一个具体的轮廓
clockwise :True为顺时针绘制,False为逆时针绘制
【以上两个api返回值都是数组,所以需要自己写一个函数把返回的点描绘出来】

import cv2
import numpy as np

def drawShape(src, points):
    i = 0
    while i < len(points):
        if(i == len(points)-1):
            x,y = points[i][0]
            x1,y1 = points[0][0]
            cv2.line(src, (x,y), (x1,y1), (0,255,0), 3)
        else:
            x,y = points[i][0]
            x1,y1 = points[i+1][0]
            cv2.line(src, (x,y), (x1,y1), (0,255,0), 3)
        i = i+1

#&#x8BFB;&#x6587;&#x4EF6;
img = cv2.imread('d:\\STUDY_OPENCV\\img\\hand.png')
#&#x8F6C;&#x53D8;&#x6210;&#x5355;&#x901A;&#x9053;
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#&#x4E8C;&#x503C;&#x5316;,&#x7B2C;&#x4E00;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x662F;&#x6267;&#x884C;&#x7684;&#x7ED3;&#x679C;&#x548C;&#x72B6;&#x6001;&#x662F;&#x5426;&#x6210;&#x529F;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x624D;&#x662F;&#x771F;&#x6B63;&#x7684;&#x56FE;&#x7247;&#x7ED3;&#x679C;
ret,binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
#&#x8F6E;&#x5ED3;&#x67E5;&#x627E;,&#x7B2C;&#x4E00;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x662F;&#x8F6E;&#x5ED3;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x5C42;&#x7EA7;
contours, hierarchy =  cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#&#x7ED8;&#x5236;&#x8F6E;&#x5ED3;
cv2.drawContours(img, contours, 0, (0,0,255), 1)#&#x6539;&#x53D8;&#x7684;&#x662F;img&#x8FD9;&#x5F20;&#x56FE;

#&#x591A;&#x8FB9;&#x5F62;&#x903C;&#x8FD1;,20&#x4EE3;&#x8868;&#x7CBE;&#x5EA6;&#xFF0C;&#x6570;&#x5B57;&#x8D8A;&#x5927;&#x4EE3;&#x8868;&#x7CBE;&#x5EA6;&#x8D8A;&#x4F4E;&#xFF0C;approx&#x8FD4;&#x56DE;&#x7684;&#x662F;&#x70B9;&#x7684;&#x6570;&#x7EC4;
approx = cv2.approxPolyDP(contours[0], 5, True)
drawShape(img, approx)
print(approx)
print(len(approx))
#&#x51F8;&#x5305;
hull = cv2.convexHull(contours[0])
drawShape(img, hull)

cv2.imshow('img',img)
cv2.imshow('binary',binary)
cv2.waitKey(0)

OpenCV之图像轮廓

外接矩形

最小外接矩形:按照物体的角度以最小的面积进行衔接,可以知道物体有没有旋转(红色框)
最大外接矩形:把物体扩在里面但是面积最大(绿色框)。

OpenCV之图像轮廓
最小外接矩形api:
minAreaRect( points )
points : 物体的轮廓
返回值RotatedRect:x,y,width,height,angle。(起始点,宽,高,角度)

最大外接矩形api:
boundingRect(array)
array:轮廓
返回值Rect :x,y,width,height(起始点,宽,高)
以下是实例

import cv2
import numpy as np
#&#x8BFB;&#x6587;&#x4EF6;
img = cv2.imread('d:\\STUDY_OPENCV\\img\\hello.png')
#&#x8F6C;&#x53D8;&#x6210;&#x5355;&#x901A;&#x9053;
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#&#x4E8C;&#x503C;&#x5316;,&#x7B2C;&#x4E00;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x662F;&#x6267;&#x884C;&#x7684;&#x7ED3;&#x679C;&#x548C;&#x72B6;&#x6001;&#x662F;&#x5426;&#x6210;&#x529F;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x624D;&#x662F;&#x771F;&#x6B63;&#x7684;&#x56FE;&#x7247;&#x7ED3;&#x679C;
ret,binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
#&#x8F6E;&#x5ED3;&#x67E5;&#x627E;,&#x7B2C;&#x4E00;&#x4E2A;&#x8FD4;&#x56DE;&#x503C;&#x662F;&#x8F6E;&#x5ED3;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x5C42;&#x7EA7;
contours, hierarchy =  cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

#&#x6700;&#x5C0F;&#x5916;&#x63A5;&#x77E9;&#x5F62;&#xFF0C;&#x6839;&#x636E;&#x7ED8;&#x5236;&#x8F6E;&#x5ED3;api&#x6D4B;&#x8BD5;&#x53EF;&#x4EE5;&#x77E5;&#x9053;&#x5305;&#x8D77;&#x5B57;&#x6BCD;&#x7684;&#x6B63;&#x65B9;&#x5F62;&#x8F6E;&#x5ED3;&#x662F;contours[1]
r = cv2.minAreaRect(contours[1])
#&#x7531;&#x4E8E;&#x8FD4;&#x56DE;&#x7684;r&#x8FD8;&#x5E26;&#x89D2;&#x5EA6;&#xFF0C;&#x6240;&#x4EE5;&#x5229;&#x7528;boxPoints&#x628A;&#x6700;&#x5C0F;&#x5916;&#x63A5;&#x77E9;&#x5F62;&#x7684;&#x56DB;&#x4E2A;&#x9876;&#x70B9;&#x5750;&#x6807;&#x63D0;&#x53D6;&#x51FA;&#x6765;
box = cv2.boxPoints(r) #&#x7531;&#x4E8E;&#x8FD4;&#x56DE;&#x7684;box&#x662F;&#x6D6E;&#x70B9;&#x578B;&#xFF0C;&#x6240;&#x4EE5;&#x9700;&#x8981;&#x5BF9;box&#x8FDB;&#x884C;&#x4E00;&#x6B21;&#x5F3A;&#x5236;&#x8F6C;&#x6362;
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0,0,255), 2)#box&#x662F;&#x4E00;&#x4E2A;&#x4E8C;&#x7EF4;&#x5217;&#x8868;&#xFF0C;&#x9700;&#x8981;&#x8F6C;&#x6362;&#x4E3A;&#x4E09;&#x7EF4;&#x5217;&#x8868;

#&#x6700;&#x5927;&#x5916;&#x63A5;&#x77E9;&#x5F62;
x,y,w,h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x,y),(x+w, y+h),(255,0,0),2)
print(x+w,y+h)
cv2.imshow('img',img)
cv2.imshow('binary',binary)
cv2.waitKey(0)

OpenCV之图像轮廓

Original: https://blog.csdn.net/go___on/article/details/123246912
Author: 秃头蜘蛛
Title: OpenCV之图像轮廓

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/533395/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球