一、轮廓检测
注意:做轮廓检测前需要将图片读取为二值数据,即像素值只为0和255。
python
contours, hierarchy = cv2.findContours(image, mode, method)
参数介绍:
image:
输入图像,必须是二值化图像(非 0 即 255)
mode:决定要检测哪些轮廓
cv2.RETR_EXTERNAL:只检测最外层轮廓,忽略内部嵌套轮廓
cv2.RETR_LIST:检测所有轮廓,但不建立任何层级关系(轮廓间无父子区分)
cv2.RETR_CCOMP:检测所有轮廓,仅建立两层层级(外层为父,内层为子)
cv2.RETR_TREE:检测所有轮廓,建立完整的层级树结构
method:决定如何压缩轮廓的点集(减少冗余点,简化轮廓)
cv2.CHAIN_APPROX_NONE:保存轮廓上所有的点(无压缩)
cv2.CHAIN_APPROX_SIMPLE:压缩水平 / 垂直 / 对角线方向的点,只保留端点(如矩形只保留 4 个角点)
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))

二、轮廓绘制
python
cv2.drawContours(image,
contours,
contourIdx,
color,
thickness=None,
lineType=None,
hierarchy=None,
maxLevel=None,
offset=None)
参数介绍:
image:
要绘制轮廓的目标图像
必须是彩色图像(BGR 格式),如果是灰度图,绘制的彩色轮廓会显示为灰度(丢失颜色)
contours:
轮廓列表,通常由cv2.findContours()函数返回。
contourIdx:指定要绘制的轮廓索引(决定绘制哪些轮廓)
-1:绘制所有轮廓
1:只绘制第 1 个轮廓(contours[0])
n:只绘制第 n+1 个轮廓(需确保 n < len(contours),否则无效果)
color:
轮廓的绘制颜色,格式为 BGR 三元组
thickness:(默认 1)
轮廓线的宽度(像素值)轮廓线的宽度(像素值)
lineType
轮廓线的类型。默认值为cv2.LINE_8。
hierarchy
轮廓层次结构。通常由cv2.findContours()函数返回。
maxLevel
绘制的最大轮廓层级。默认值为None,表示绘制所有层级。
offset
轮廓点的偏移量。默认值为None。
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))
image_copy = amy.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0,255, 0),thickness=2)
cv2.imshow( 'Contours_show', image_copy)
cv2.waitKey(0)

三、检测目标轮廓
通过轮廓面积
python
cv2.contourArea(contour, oriented)
参数介绍:
contour:
单个轮廓的点集(不是轮廓列表),是 cv2.findContours() 返回的 contours 列表中的单个元素。
oriented:(默认 False)
是否返回「有向面积」(带正负号),而非绝对值面积。
True:返回有向面积(可正可负),符号由轮廓的点排列方向(顺时针 / 逆时针)决定,
False:返回绝对值面积(正数)
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))
image_copy = amy.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0,255, 0),thickness=2)
cv2.imshow( 'Contours_show', image_copy)
cv2.waitKey(0)
area_0 = cv2.contourArea(contours[0])#轮廓面积
print(area_0)
area_1 = cv2.contourArea(contours[1])
print(area_1)
通过轮廓周长
python
cv2.arcLength(curve, closed)
参数介绍:
curve:
单个轮廓的点集,是 cv2.findContours() 返回的 contours 列表中的单个元素。
closed:
指定轮廓是否为闭合轮廓
True:认为轮廓是闭合的(首尾点相连),计算完整的闭合周长
False:认为轮廓是开放的曲线(首尾点不相连),计算从第一个点到最后一个点的折线长度
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))
image_copy = amy.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0,255, 0),thickness=2)
cv2.imshow( 'Contours_show', image_copy)
cv2.waitKey(0)
length = cv2.arcLength(contours[0],closed=True)
print(length)
通过外接圆面积
python
cv2.circle(img,
center,
radius,
color,
thickness=None,
)
参数介绍:
img:
绘制圆形的目标图像(支持彩色图(BGR 格式)/ 灰度图)
center:
圆心坐标,格式为 (x, y)(元组类型,x = 横坐标,y = 纵坐标)
radius:
圆的半径,单位为像素,必须是正整数
color:
圆形的绘制颜色,格式为 BGR 三元组
thickness:(默认1)
圆形轮廓的线宽(像素值)
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))
image_copy = amy.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0,255, 0),thickness=2)
cv2.imshow( 'Contours_show', image_copy)
cv2.waitKey(0)
cnt = contours[6]
(x,y),r=cv2.minEnclosingCircle(cnt)#计算轮廓的外接圆
amy_circle = cv2.circle (amy, (int(x), int (y)), int(r), (0,255,0), 2)
cv2.imshow( 'phone_circle',amy_circle)
cv2.waitKey(0)
通过外接矩形面积
python
cv2.rectangle(img, pt1, pt2, color, thickness=None)
参数介绍:
img:
绘制矩形的目标图像
支持彩色图(BGR 格式)/ 灰度图
pt1:
矩形的左上角坐标 ,格式为 (x1, y1)(元组类型)
pt2:
矩形的右下角坐标 ,格式为 (x2, y2)(元组类型)
color:
矩形的绘制颜色,格式为 BGR 三元组
thickness:(默认为1)
矩形边框的线宽(像素值)
python
import cv2
import pandas as pd
amy = cv2.imread('../data/phone.png')
amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY)
cv2.imshow('amy_gray', amy_gray)
cv2.waitKey(0)
#amy_gray = cv2.cvtColor(amy,cv2.COLOR_BGR2GRAY) 读取灰度图
ret,amy_binary = cv2.threshold(amy_gray, 120,255,cv2.THRESH_BINARY)#阈值处理为二值
cv2.imshow( 'amy_binary',amy_binary)
cv2.waitKey(0)
_, contours, hierarchy = cv2.findContours (amy_binary, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#contours = cv2.findContours (amy_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[ -2]#通用
# print(hierarchy)
print(len(contours))
image_copy = amy.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0,255, 0),thickness=2)
cv2.imshow( 'Contours_show', image_copy)
cv2.waitKey(0)
x,y,w,h=cv2.boundingRect(cnt)#计算轮廓的最小外接矩形
phone_rectangle = cv2.rectangle(amy, (x,y), (x+w,y+h), (0,255, 0), 2)#在图像上绘制矩形
cv2.imshow( 'phone_rectangle',phone_rectangle)
cv2.waitKey(0)

四、轮廓近似
python
cv2.approxPolyDP(curve, epsilon, closed)
参数介绍:
curve:
需要简化的原始轮廓点集(单个轮廓,非轮廓列表)
epsilon:
逼近精度(核心参数),表示「原始轮廓」与「近似多边形」之间的最大允许距离(单位:像素)
通常取「原始轮廓周长」的百分比
closed:
指定近似后的多边形是否为闭合轮廓
True:多边形闭合(首尾点相连)
False:多边形开放(首尾点不相连)
python
phone = cv2.imread('phone.png')
phone_gray=cv2.cvtColor(phone,cv2.COLOR_BGR2GRAY) #转换为灰度图
ret, phone_thresh = cv2. threshold(phone_gray, 120, 255, cv2. THRESH_BINARY) #二值化
#image, Contours, hierarchy = cV2.findContours (phone_thresh, cV2.RETR_ TREE, CV2.CHAIN APPROX NONE)#获轮廓
contours=cv2.findContours(phone_thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2]
epsilon = 0.01 * cv2.arcLength(contours[0], True)#设置近似精度Ih要<E;E越小,点越多,越精确】
approx = cv2.approxPolyDP(contours[0], epsilon,True)#对轮廓进行近似
print(contours[0].shape)
print(approx.shape)
phone_new = phone.copy()
image_contours = cv2.drawContours(phone_new,[approx], contourIdx=-1, color=(0,255, 0), thickness=3)#cv2.imshow( winname: 'phone',phone)
cv2.waitKey(0)
cv2.imshow( 'image_contours',image_contours)
cv2.waitKey(0)


