目錄
一.輪廓操作
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))
或者通過修改運行配置