轮廓周长,面积,外界圆,外界矩形近似轮廓和模板匹配和argparse模块实现代码参数的动态配置
目录
一.轮廓操作
1.轮廓特征的引入与筛选
2.轮廓排序和精准定位
3.外接圆与外接矩形的计算与绘制
二.轮廓近似
1.轮廓近似的基本概念
2.轮廓近似的实现方法和核心步骤
3. 近似精度参数的设定逻辑
4.轮廓定位方法
三.模板匹配
1.模板匹配技术原理与实现流程
2.技术要点与注意事项
四.使用argparse模块实现代码参数的动态配置,避免手动修改代码
一.轮廓操作
1.轮廓特征的引入与筛选
- 基于轮廓的面积和周长特征,可对多个检测到的轮廓进行简单筛选
- 面积(area)和周长(perimeter)是两个最基础、易实现的轮廓特征
import cv2
phone=cv2.imread('phone.png')
phone_gray=cv2.imread('phone.png', 0)
ret,phone_binary=cv2.threshold(phone_gray,120,255,cv2.THRESH_BINARY)
contours=cv2.findContours(phone_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[-2]
#指定轮廓面积
area_0=cv2.contourArea(contours[0])
area_1=cv2.contourArea(contours[1])
print(area_0,area_1)
#指定轮廓周长,closed指示曲线是否封闭
length=cv2.arcLength(contours[0],closed=True)
print(length)
2.轮廓排序和精准定位
- 轮廓定位前需完成预处理,包括灰度化、二值化等步骤
- 所有轮廓特征提取均基于
findContours()
获取的轮廓列表进行
-
根据特定面积显示特定轮廓,通过设置面积阈值(如大于一万),可筛选出满足条件的目标轮廓
#根据特定面积显示特定轮廓
a_list=[]
for i in contours:if cv2.contourArea(i)>10000:a_list.append(i)
image_copy=phone.copy()
image_copy=cv2.drawContours(image=image_copy,contours=a_list,contourIdx=-1,color=(0,255,0),thickness=3)
cv2.imshow('Contours_show_10000',image_copy)
cv2.waitKey(0)
- 可对轮廓列表按面积或周长进行排序(升序或降序),便于快速定位目标
- 降序排列后索引为0的轮廓即为面积最大的轮廓,可直接提取并绘制
- 排序后可方便地获取第二、第三等大轮廓,实现多目标定位
sort_cnt=sorted(contours,key=cv2.contourArea,reverse=True)[0]#选取最大面积的轮廓
image_contours=cv2.drawContours(image_copy,[sort_cnt],contourIdx=-1,color=(0,0,255),thickness=3)
cv2.imshow('image_contours',image_copy)
cv2.waitKey(0)
3.外接圆与外接矩形的计算与绘制
- 外接圆:通过
minEnclosingCircle()
计算轮廓的最小外接圆,返回圆心坐标(x,y)和半径 - 注意OpenCV坐标系中X轴向右,Y轴向下,与常规坐标系不同
- 绘制时需将float类型的坐标转为int类型,避免类型错误
- 外接矩形:通过
minAreaRect()
计算轮廓的最小外接矩形,返回左上角坐标(x,y)、宽度(w)、高度(h) - 绘制时需根据左上角坐标和宽高计算右下角坐标(x+w, y+h)以完成矩形绘制
#外接圆,外界矩形
cnt=contours[7]
(x,y),r=cv2.minEnclosingCircle(cnt)
phone_circle=cv2.circle(phone,(int(x),int(y)),int(r),(0,255,0),2)
cv2.imshow('phone_circle',phone_circle)
cv2.waitKey(0)x,y,w,h=cv2.boundingRect(cnt)#计算该轮廓最小外接矩形
phone=cv2.imread('phone.png')
phone_rect=cv2.rectangle(phone,(x,y),(x+w,y+h),(0,255,0),thickness=3)
cv2.imshow('phone_rect',phone_rect)
cv2.waitKey(0)
cv2.destroyAllWindows()
二.轮廓近似
1.轮廓近似的基本概念
- 轮廓近似是对原始轮廓进行逼近或拟合,以减少点的数量,从而简化形状描述。
- 原始轮廓由成百上千个点构成(如手机外壳759个点),近似后可简化为十几个甚至几个点(如18个或8个点)。
2.轮廓近似的实现方法和核心步骤
- 使用OpenCV中的
cv2.approxPolyDP()
函数实现轮廓近似。 - 关键参数包括:
- 输入轮廓(如
counters[0]
) - 近似精度(
epsilon
),表示轮廓近似的程度,通常设置为轮廓周长的百分比(如1%或5%) - 是否封闭(
closed
),默认为True,因为多数轮廓为封闭图形
- 输入轮廓(如
epsilon=0.01*cv2.arcLength(contours[0],True)
approx=cv2.approxPolyDP(contours[0],epsilon,True)
print(contours[0].shape)
print(approx.shape)(229, 1, 2)#完整轮廓shape
(8, 1, 2)#近似轮廓shapephone=cv2.imread('phone.png')
phone_new=phone.copy()
image_contours=cv2.drawContours(phone_new,[approx],contourIdx=-1,color=(0,255,0),thickness=3)
cv2.imshow('phone',phone)
cv2.waitKey(0)
cv2.imshow('image_contours',image_contours)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 近似精度参数的设定逻辑
- 精度参数与近似点数量呈反比:精度越小,近似越精确,点越多;精度越大,近似越粗略,点越少。
- 实现原理中通过计算“中垂线距离”(H值)与设定精度(epsilon)比较,若H小于epsilon,则直接用两点连接;否则反复取中垂线,逐步逼近,最终决定采用几段线段。
4.轮廓定位方法
- 通过多种方式定位最外层轮廓:
- 基于轮廓索引遍历(如取第0个轮廓)
- 根据轮廓面积或周长进行排序,提取面积最大的轮廓
- 预估外部轮廓的特征(如周长大、面积大)并设定阈值筛选
三.模板匹配
import cv2
kele=cv2.imread('img.png')
template=cv2.imread('img_template.png')
cv2.imshow('kele',kele)
cv2.imshow('template',template)
cv2.waitKey(0)
1.模板匹配技术原理与实现流程
- 模板匹配用于在大图中定位与小图(模板)完全一致的区域,其核心是遍历大图,将模板与每个位置进行比对,计算匹配得分。
- 匹配过程采用归一化相关系数(NORMED)方法,得分越大表示匹配越佳,范围在 0 到 1 之间。
- 遍历整张大图后,提取得分最大值的位置(通过minMaxLoc() 获取坐标),该坐标即为模板匹配的最优位置。
- 根据最高得分坐标的左上角坐标(top-left)与模板图片的宽高,计算右下角坐标(x+w, y+h)
- 通过
cv2.rectangle()
在原图上绘制矩形框,标注匹配区域。
h,w=template.shape[:2]
res=cv2.matchTemplate(kele,template,cv2.TM_CCORR_NORMED)
min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(res)
top_left=max_loc#所要绘制矩形左上角的坐标(x,y)
bottom_right=(top_left[0]+w,top_left[1]+h)
kele_template=cv2.rectangle(kele,top_left,bottom_right,(0,255,0),2)
cv2.imshow('kele_template',kele_template)
cv2.waitKey(0)
2.技术要点与注意事项
- 模板与目标区域的尺寸必须完全一致,否则无法准确匹配。
- 匹配结果中需分析得分矩阵,识别最大值位置,避免误选低分区域。
- 该技术为后续银行卡号识别等场景提供了基础方法论。
四.使用argparse
模块实现代码参数的动态配置,避免手动修改代码
- 创建参数时使用
add_argument
指定参数名、类型(string/int/float)、默认值和帮助说明 - 参数可通过右键“运行配置”或终端命令行直接设置,支持别名(alias)优化可读性
- 支持通过
python main.py param1 value1 param2 value2
方式运行或通过python main.py -h
查看所有参数列表
import argparse
parser=argparse.ArgumentParser()
parser.add_argument('--name',type=str,default='john',help='姓名')
parser.add_argument('--age',type=int,default=18,help='年龄')
parser.add_argument('--weight',type=float,default=120.0,help='体重')
opt=parser.parse_args()
print('我叫{}我今年{}岁体重{}kg'.format(opt.name,opt.age,opt.weight))
或者通过修改运行配置