Python-Opencv实现魔方边缘识别
前言
同學要做擰魔方機器人,但是他對視覺識別方面的知識不太明白,于是我幫他完成了識別魔方色塊邊緣的功能,過程中學習了不少可以用于圖像處理的函數。下面我會先詳解每一個函數,然后再給出整合后的代碼。
環境配置:我是在anaconda上配置的python3.8的環境,用Jupyter Notebook來編寫運行代碼。
函數詳解
魔方圖片:
先對目標圖像進行預處理:
imgobj = cv2.imread('CV_img/test2.jpg') gray = cv2.cvtColor(imgobj, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (3, 3), 0)canny = cv2.Canny(blurred, 20, 40)kernel = np.ones((3,3), np.uint8) dilated = cv2.dilate(canny, kernel, iterations=2) #閉運算,先膨脹再腐蝕,可以填充孔洞(√) dilated=morphology.dilation(dilated,morphology.square(8)) dilated=morphology.erosion(dilated,morphology.square(8))cv2.imread先讀取測試圖片;
cv2.cvtColor(p1,p2) 是顏色空間轉換函數,p1是需要轉換的圖片,p2是轉換成何種格式。cv2.COLOR_BGR2GRAY 是將BGR格式轉換成灰度圖片;
cv2.GaussianBlur是高斯濾波,是平滑濾波的一種方法,而Canny算子是邊緣檢測的一種算法,通過這兩個函數對圖像進行濾波運算。
dilate()函數可以對輸入圖像用特定結構元素進行膨脹操作,該結構元素確定膨脹操作過程中的鄰域的形狀。先創造一個3*3的數組(也就是kernel),用于膨脹操作的結構元素,使得處理后的圖片看起來更契合魔方的特征。iterations是被遞歸的次數。
dilation為膨脹,erosion為腐蝕,先膨脹再腐蝕是閉運算,可以填充孔洞,而先腐蝕再膨脹是開運算,可以消除小物體小斑塊,效果由參數morphology.square(p1)中的p1決定,數值越大效果越明顯。
然后是提取輪廓:
contours, hierarchy = cv2.findContours(dilated,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)findContours函數是本程序中最核心的函數,大家也可以自己去找其他的資料進行更全面的了解。該函數的作用是檢測圖片中物體的輪廓。
先從findContours函數原型看起:
findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point());各個參數解析:
image,目標圖像,一般來說灰度圖效果比較好。
contours是一個向量的集合,其中的每一個元素對應著一條輪廓,每個元素保存了一組由連續的Point點構成的點的集合,有多少輪廓,向量contours就有多少元素。你就把它當做一個數組,數組中每一個元素就是一條輪廓,且這個元素包含了這條輪廓的所有信息。
hierarchy,也是一個向量,向量內每個元素保存了一個包含4個int整型的數組。向量hiararchy內的元素和輪廓向量contours內的元素是一一對應的,向量的容量相同。hierarchy向量內每一個元素的4個int型變量——hierarchy[i][0] ~hierarchy[i][3],分別表示第i個輪廓的后一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號。
int型的mode,定義輪廓的檢索模式:
取值一:cv2.RETR_EXTERNAL只檢測最外圍輪廓,包含在外圍輪廓內的內圍輪廓被忽略。
取值二:cv2.RETR_LIST 檢測所有的輪廓,包括內圍、外圍輪廓,但是檢測到的輪廓不建立等級關系,彼此之間獨立,沒有等級關系,這就意味著這個檢索模式下不存在父輪廓或內嵌輪廓, 所以hierarchy向量內所有元素的第3、第4個分量都會被置為-1.
取值三:cv2.RETR_CCOMP 檢測所有的輪廓,但所有輪廓只建立兩個等級關系,外圍為頂層,若外圍內的內圍輪廓還包含了其他的輪廓信息,則內圍內的所有輪廓均歸屬于頂層。
取值四:cv2.RETR_TREE, 檢測所有輪廓,所有輪廓建立一個等級樹結構。外層輪廓包含內層輪廓,內層輪廓還可以繼續包含內嵌輪廓。
取值一:cv2.CHAIN_APPROX_NONE 保存物體邊界上所有連續的輪廓點到contours向量內。
取值二:cv2.CHAIN_APPROX_SIMPLE 僅保存輪廓的拐點信息,把所有輪廓拐點處的點保存入contours向量內,拐點與拐點之間直線段上的信息點不予保留。
取值三和四:cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法。
我們這里mode取值cv2.RETR_TREE,method取值cv2.CHAIN_APPROX_SIMPLE.
然后處理contours中的數據以得到我們想要的結果。
candidates = [] for i in range(0,len(contours)):area = cv2.contourArea(contours[i])#計算面積if 40000<area<50000: #魔方色塊的面積candidates.append(contours[i]) cv2.drawContours(imgobj, candidates, -1, (0, 0, 255), 3)cv2.namedWindow("enhanced",0);cv2.resizeWindow("enhanced", 640, 640);cv2.imshow("enhanced",imgobj)cv2.waitKey(0)我的方案是通過計算每條輪廓所圍圖形的面積來確定哪些輪廓是我們所需要的。
candidates用來存放符合條件的輪廓。
面積值,我是把所有的輪廓的面積都算出來了,然后找到了相近的九個面積值來確定的。只要保持拍攝魔方的時候攝像頭外設的鏡頭與魔方距離固定應該就可行。
append函數用于在列表末尾添加新的對象。
最終效果圖:
只要得到這些輪廓下面就好辦了,可以用過函數cv2.moments來查找到每條輪廓的中心點,在通過中心點的HSV值來確定顏色,具體流程我這里就不贅述了,大家自己寫一下。
完整代碼
我的代碼是使用攝像頭外設來實時實現識別魔方邊緣的。
注意改一個適當的面積范圍。
總結
以上是生活随笔為你收集整理的Python-Opencv实现魔方边缘识别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何做好基线配置
- 下一篇: java 获取图片像素_转:java提取