7. OpenCV - Image Contour

1. Through OpenCV's findContours, you can easily find the outline of the content in the picture.

2. In order to have a higher accuracy in extracting the contour, before extracting the contour, it is necessary to preprocess the image (binary value + threshold), and only keep the image of interest.

3. By calculating the contour area and the area of ​​the circumscribed rectangle or circumscribed circle, the contour features can be found, and the contours of interest can be further screened out.

Syntax: cv2.findContours(img,mode,method)
mode: contour retrieval mode
RETR_EXTERNAL: only check the outermost contours
RETR_LIST: retrieve all contours and save them in a linked list RETR_CCOMP: retrieve all contours and organize them into two
layers: the top layer is the outer boundary of each part, the second layer is the boundary of the hole RETR_TREE: retrieve all contours and reconstruct the entire hierarchy of nested contours (This is commonly used) method: Contour approximation method CHAIN_APPROX_NONE: Contour output in the form of Freeman chain code, all other methods output polygons (sequences
of
vertices )
.
CHAIN_APPROX_SIMPLE: Compresses horizontal, vertical and oblique parts, that is, the function keeps only their end parts.
For higher accuracy, use binary images

sample code 

import cv2
import math
import numpy as np

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

def cv_show(name, img):
    cv2.imshow(name, img)  # 显示图像
    cv2.waitKey(0)         # 等待时间,单位毫秒,0表示任意键终止
    cv2.destroyAllWindows()

#1.读取图像
image = cv2.imread("C:\\Users\\zhangqs\\Desktop\\cv.png")

#2.预处理
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)                 #灰度图
ret,threshold=cv2.threshold(gray,160,255,cv2.THRESH_BINARY) #阈值处理

#3.查找轮廓
contours,hierarchy=cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

print('共找到',len(contours),'个轮廓')
#4.绘制轮廓

#在原图上绘制轮廓
draw2=image.copy() #注意:需要copy一下,否则将会改动原图
drawed2=cv2.drawContours(draw2,contours,-1,(0,0,255),2)  #图像,轮廓,轮廓索引,颜色模式,线条厚度
cv_show('draw_contours',draw2)

#在灰度图上绘制轮廓(下面的np.hstack函数要求数组维度一致,才能比较显示)
draw=gray.copy() #注意:需要copy一下,否则将会改动原图
drawed=cv2.drawContours(draw,contours,-1,(0,0,255),2)  #图像,轮廓,轮廓索引,颜色模式,线条厚度

#5.轮廓近似

#外接矩形(绿色线)
cnt=contours[12]
# epsilon=0.1*cv2.arcLength(cnt,True)
# approx=cv2.approxPolyDP(cnt,epsilon,True)
x,y,w,h=cv2.boundingRect(cnt)
imgRectangle=cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
cv_show('Rectangle',imgRectangle)

area=cv2.contourArea(cnt) #轮廓面积
rectArea=w*h #外接矩形面积
rate=float(area)/rectArea
print('轮廓面积/外接矩形面积比:',rate)

#外接圆(蓝色线)
cnt2=contours[11] 
(x,y),radius=cv2.minEnclosingCircle(cnt2)
center=(int(x),int(y))
radius=int(radius)
imgCircle=cv2.circle(image,center,radius,(255,0,0),2)
cv_show('Circle',imgCircle)
areaCircle=cv2.contourArea(cnt) #轮廓面积
rectArea=math.pi*radius*radius #外接圆面积
rateCircle=float(areaCircle)/areaCircle
print('轮廓面积/外接圆面积比:',rateCircle)


# #合并显示
# res=np.hstack((gray,threshold,drawed)) #注意:两层括号
# cv2.imshow('all',res)
# cv2.waitKey(0)
# cv2.destroyAllWindows()


operation result

 original image 

Contour drawing 

Bounding rectangle (green line) 

 Circumscribed circle (blue line)

 By traversing the contour, by calculating the area ratio, we can find the contour features, and then filter out the contours we are interested in.

Guess you like

Origin blog.csdn.net/a497785609/article/details/131247819