尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OpenCV入门学习(三):轮廓检测与模板匹配

OpenCV入门学习(三):轮廓检测与模板匹配 OpenCV入门学习三轮廓检测与模板匹配前言本文是OpenCV系列教程的第三篇。在掌握了图像预处理之后我们将进入轮廓检测与模板匹配的学习。轮廓检测用于在图像中查找物体的边界模板匹配用于在图像中寻找与模板相似的区域物体追踪则用于在视频序列中持续跟踪目标对象。本章涵盖五个核心知识点轮廓检测与绘制、轮廓特征、轮廓近似、模板匹配、物体追踪。目录一、轮廓检测与绘制二、轮廓特征三、轮廓近似四、模板匹配五、物体追踪六、总结一、轮廓检测与绘制轮廓检测用于在图像中查找物体的边界轮廓。1.1 轮廓检测核心函数contours, hierarchy cv2.findContours(img, mode, method)[-2]参数说明img输入图像需为二值图像mode轮廓检索模式method轮廓近似方法mode检索模式模式说明cv2.RETR_EXTERNAL只检测外轮廓cv2.RETR_LIST所有轮廓同一等级不建立层级关系cv2.RETR_CCOMP两级层级外轮廓为第1级内部空洞为第2级cv2.RETR_TREE完整层级结构method近似方法方法说明cv2.CHAIN_APPROX_NONE存储所有轮廓点cv2.CHAIN_APPROX_SIMPLE压缩存储只保留端点矩形只需4个点注意做轮廓检测前需要将图片转为二值图像。importcv2 imgcv2.imread(sl.png)img_graycv2.cvtColor(img,cv2.COLOR_BGR2GRAY)cv2.imshow(img_gray,img_gray)# 二值化THRESH_BINARY_INV大于190变黑小于等于190变白ret,img_binarycv2.threshold(img_gray,190,255,cv2.THRESH_BINARY_INV)cv2.imshow(img_binary,img_binary)# RETR_EXTERNAL只检测外轮廓忽略内部轮廓contours_externalcv2.findContours(img_binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[-2]# RETR_TREE检测所有轮廓建立完整层级结构contours_treecv2.findContours(img_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)[-2]print(fRETR_EXTERNAL 轮廓数量:{len(contours_external)})print(fRETR_TREE 轮廓数量:{len(contours_tree)})cv2.waitKey(0)cv2.destroyAllWindows()输出示例 RETR_EXTERNAL 轮廓数量: 32 RETR_TREE 轮廓数量: 7311.2 轮廓绘制核心函数cv2.drawContours(image, contours, contourIdx, color, thickness)参数说明image要绘制轮廓的图像contours轮廓列表contourIdx轮廓索引-1表示绘制所有color颜色BGR格式thickness线条粗细# 绘制轮廓img_externalimg.copy()img_treeimg.copy()cv2.drawContours(img_external,contours_external,-1,(255,0,0),2)cv2.drawContours(img_tree,contours_tree,-1,(255,0,0),2)cv2.imshow(RETR_EXTERNAL,img_external)cv2.imshow(RETR_TREE,img_tree)cv2.waitKey(0)cv2.destroyAllWindows()二、轮廓特征2.1 面积与周长面积cv2.contourArea(contour)|周长cv2.arcLength(curve, closed)# 计算面积areacv2.contourArea(contours_external[-1])print(area)# 计算周长closedTrue表示封闭lengthcv2.arcLength(contours_external[-1],True)print(length)输出示例 193874.0 3992.0410888195042.2 根据面积筛选# 筛选面积大于10000的轮廓big_contours_tree[iforiincontours_treeifcv2.contourArea(i)10000]img_bigimg.copy()cv2.drawContours(img_big,big_contours_tree,-1,(0,0,255),3)cv2.imshow(img_big,img_big)cv2.waitKey(0)cv2.destroyAllWindows()2.3 轮廓排序# 按面积从大到小排序取最大轮廓max_contoursorted(contours_tree,keycv2.contourArea,reverseTrue)[0]img_bigestimg.copy()cv2.drawContours(img_bigest,max_contour,-1,(0,0,255),3)cv2.imshow(img_bigest,img_bigest)cv2.waitKey(0)cv2.destroyAllWindows()2.4 外接圆核心函数cv2.minEnclosingCircle(points)→(x, y), r绘制函数cv2.circle(img, center, radius, color, thickness)# 外接圆img_circleimg.copy()(x,y),rcv2.minEnclosingCircle(max_contour)cv2.circle(img_circle,(int(x),int(y)),int(r),(0,0,255),3)cv2.imshow(min_enclosing_circle,img_circle)cv2.waitKey(0)cv2.destroyAllWindows()2.5 外接矩形核心函数cv2.boundingRect(points)→(x, y, w, h)绘制函数cv2.rectangle(img, pt1, pt2, color, thickness)# 外接矩形img_rectimg.copy()x,y,w,hcv2.boundingRect(max_contour)cv2.rectangle(img_rect,(x,y),(xw,yh),(0,0,255),3)cv2.imshow(bounding_rect,img_rect)cv2.waitKey(0)cv2.destroyAllWindows()三、轮廓近似轮廓近似用于减少轮廓点数简化轮廓形状。核心函数cv2.approxPolyDP(curve, epsilon, closed)参数说明curve输入轮廓epsilon近似精度越小越精确越大越粗略closed是否封闭# epsilon 精度系数 × 轮廓周长epsilon0.005*cv2.arcLength(big_contours_tree[0],True)approxcv2.approxPolyDP(big_contours_tree[0],epsilon,True)print(f原始点数:{big_contours_tree[0].shape[0]})print(f近似后点数:{approx.shape[0]})# 绘制近似后的轮廓img_approximg.copy()cv2.drawContours(img_approx,[approx],-1,(0,255,0),3)cv2.imshow(approx_contour,img_approx)cv2.waitKey(0)cv2.destroyAllWindows()输出示例 原始点数: 3408 近似后点数: 40四、模板匹配模板匹配用于在图像中寻找与模板图像匹配的区域。核心函数cv2.matchTemplate(image, templ, method)→ 返回匹配结果矩阵参数说明image待搜索图像templ模板图像method匹配方法匹配方法方法匹配越好TM_SQDIFF/TM_SQDIFF_NORMED值越小TM_CCORR/TM_CCOEFF/ 及其归一化版本值越大获取最佳匹配位置cv2.minMaxLoc(res)→min_val, max_val, min_loc, max_locimportcv2 imgcv2.imread(sl.png)templatecv2.imread(sl_yu.png)cv2.imshow(img,img)cv2.imshow(template,template)cv2.waitKey(0)h,wtemplate.shape[:2]# 模板匹配归一化相关系数匹配法值越大表示匹配越好rescv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)# 获取匹配结果的最大值及其位置即最佳匹配区域的左上角坐标_,_,_,max_loccv2.minMaxLoc(res)# 绘制矩形框标注最佳匹配区域top_leftmax_loc bottom_right(top_left[0]w,top_left[1]h)img_tempcv2.rectangle(img,top_left,bottom_right,(255,0,0),2)cv2.imshow(img_temp,img_temp)cv2.waitKey(0)cv2.destroyAllWindows()五、物体追踪物体追踪用于在视频序列中持续跟踪目标对象。创建跟踪器cv2.TrackerCSRT_create()选择ROIcv2.selectROI(windowName, img, showCrosshair)初始化tracker.init(frame, roi)更新success, box tracker.update(frame)→ 返回(x, y, w, h)importcv2# 创建CSRT跟踪器trackercv2.TrackerCSRT_create()capcv2.VideoCapture(0)trackingFalse# 是否正在跟踪whileTrue:ret,framecap.read()framecv2.flip(frame,1)# 镜像翻转更符合习惯ifnotret:breakkeycv2.waitKey(1)# ESC退出ifkey27:break# 按y键重新框选目标ifkeyord(y):cv2.destroyWindow(tracking)cv2.imshow(Select Object,frame)# 鼠标框选目标区域按空格或回车确认按c取消roicv2.selectROI(Select Object,frame,showCrosshairFalse)ifroi[2]!0androi[3]!0:tracker.init(frame,roi)trackingTrueelse:trackingFalsecv2.destroyWindow(Select Object)cv2.imshow(tracking,frame)# 更新跟踪iftracking:success,boxtracker.update(frame)ifsuccess:x,y,w,h[int(v)forvinbox]cv2.rectangle(frame,(x,y),(xw,yh),(0,255,0),2)cv2.imshow(tracking,frame)cap.release()cv2.destroyAllWindows()操作说明步骤操作说明1运行程序摄像头自动打开显示实时画面2按y键进入目标框选模式3鼠标框选按住左键拖拽框出要跟踪的目标区域4按空格或回车确认选择开始跟踪5按c键取消本次框选回到预览状态6跟踪失败目标移出画面或丢失后按y键重新框选7按ESC键退出程序注意在英文输入法状态下操作六、总结核心函数速查类别函数用途轮廓检测findContours()查找轮廓轮廓绘制drawContours()绘制轮廓轮廓面积contourArea()计算面积轮廓周长arcLength()计算周长外接圆minEnclosingCircle()最小外接圆外接矩形boundingRect()最小外接矩形轮廓近似approxPolyDP()简化轮廓模板匹配matchTemplate()匹配模板获取极值minMaxLoc()获取最大/最小值位置创建跟踪器TrackerCSRT_create()CSRT跟踪器选择ROIselectROI()手动框选区域常见陷阱陷阱正确做法原图直接传入findContours先灰度化再二值化忘记[-2]索引findContours返回值用[-2]取contours直接修改原图绘制轮廓先copy()再绘制模板匹配后没取最大位置用minMaxLoc()获取跟踪器未初始化就update先init()再update系列直达上篇OpenCV入门学习二图像预处理本篇OpenCV入门学习三轮廓检测与模板匹配本文
返回列表