目的:
1. 識別并框選出圖片中紅色的幾何圖形,分辨出各是什么圖形(不允許用滑鼠 操作),
2. 將紅色圖形中心連線,計算連線圍成圖形的面積,

代碼如下:
import cv2
import sys
import cmath
import numpy
#讀取影像
areas = list()
x= list()
y = list()
img1 = cv2.imread("E:/a/qw.jpg")
(B,G,R) = cv2.split(img1)
retal , img2 = cv2.threshold(R,0,255,cv2.THRESH_OTSU)
contours, hierarachy = cv2.findContours(img2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
#cv2.drawContours(img1,contours,i,(0,0,255),10)
area = cv2.contourArea(contours[i],False)
areas.append(area)
areas.sort(reverse=True)
for i in range(len(contours)):
area = cv2.contourArea(contours[i],False)
if area > areas[5]:
if area < areas[1]:
print(i)
epsilon = 0.02 * cv2.arcLength(contours[i], True)
approx = cv2.approxPolyDP(contours[i],epsilon,True)
cv2.polylines(img1,[approx],True,(0,0,255),10)
M = cv2.moments(contours[i])
cx = int(M["m10"]/M["m00"])
cy = int(M["m01"]/M["m00"])
x.append(cx)
y.append(cy)
if len(approx) > 4:
print("圓形")
text = "y"
elif len(approx) == 3:
print("三角形")
text = "s"
elif len(approx) == 4:
print("矩形")
text = "j"
cv2.putText(img1,text,(cx,cy),cv2.FONT_HERSHEY_PLAIN,10,(0, 255, 0),5)
S = (1/2)*(x[0]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]+x[2]*y[0]-x[1]*y[1])
print("s=%d"%S)
pts = numpy.array([[x[0],y[0]],[x[1],y[1]],[x[2],y[2]]])
pts = pts.reshape((-1,1,2))
cv2.polylines(img1,[pts],True,(255, 0, 0),10)
cv2.namedWindow("RED",cv2.WINDOW_NORMAL)
cv2.imshow("RED",img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
首先:
讀取檔案中的圖片,注意:檔案地址的斜杠要是/或\\,否則會報錯
img1 = cv2.imread("E:/a/qw.jpg")
我們用imshow函式來顯示圖片的時候會發現圖片過大螢屏顯示不完
cv2.imshow("RED",img1)

比如這樣,所以我們需要將影像變形以便更合適顯示在我們的螢屏,利用下面的函式就可以舒服的顯示我們的影像啦
cv2.namedWindow("RED",cv2.WINDOW_NORMAL)
| 標志引數 | 作用 |
| WINDOW_AUTOSIZE | 根據影像大小顯示視窗,不允許用戶調整大小 |
| WINDOW_FREERATIO | 視窗大小自適應比例 |
| WINDOW_KEEPRATIO | 保持影像的比例 |
| WINDOW_NORMAL | 顯示影像后,允許用戶隨意調整視窗大小 |
進行圖片的通道分離:利用split函式來分離出藍、綠、紅三種顏色的灰度圖
(B,G,R) = cv2.split(img1)
這個是紅色分離后的影像,可以看出紅色的地方已經變成白色或灰色

然后經過影像二值化函式threshold()得到黑白的影像(二值圖),從而把紅色更好的提出
retal , img2 = cv2.threshold(R,0,255,cv2.THRESH_OTSU)

尋找圖形輪廓,把剛剛得到的二值圖放進函式,在二值圖中尋找輪廓,回傳每個輪廓的點contours
contours, hierarachy = cv2.findContours(img2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
通過這個輪廓得到的點去畫出得到的輪廓利用drawContours來畫出:
cv2.drawContours(img1,contours,i,(0,0,255),10)

我們發現有很多的噪聲需要消掉,我們通過判斷面積來將不是紅色輪廓的其他輪廓消除,不難看出紅色的三個圖形輪廓的面積在全部輪廓中排名3,4,5.所以我們通過contourArea()函式求出每個輪廓的面積并把他們放在areas串列中,
area = cv2.contourArea(contours[i],False)
areas.append(area)
這是把其他輪廓去除之后的圖形

我們發現這三分個輪廓,每個輪廓都是由很多個輪廓點組成,但是確實像矩形可以只用四個輪廓點表示,三角形可以只用三個輪廓點表示就可以了,所以下一步為了方便我們檢測圖形是否是三角形、圓形還是矩形,我們需要對輪廓點進行優化,所以我們就用到了approxPolyDP函式
epsilon = 0.02 * cv2.arcLength(contours[i], True)
approx = cv2.approxPolyDP(contours[i],epsilon,True)
在這里epsilon作為一個引數,這個需要調一下,0.02就是調出來的,具體參考:
opencv 使用approxPolyDP輪廓近似_brooknew的專欄-CSDN博客
再利用polylines()函式來畫出輪廓點之間的連線
cv2.polylines(img1,[approx],True,(0,0,255),10)
效果如下:
然后根據輪廓點的個數就可以判斷是什么形狀啦,
下一步我們尋找紅色圖形的中心點,用moments()函式求出圖形的矩,并求出每個圖形的重心,詳細可以看
Python OpenCV findContours()函式與drawContours()函式用法_dz4543的博客-CSDN博客_drawcontours()引數說明
M = cv2.moments(contours[i])
cx = int(M["m10"]/M["m00"])
cy = int(M["m01"]/M["m00"])
然后根據三點求面積公式就可以求出三個重心圍成的面積
S=(1/2)*(x1y2*1+x2y3*1+x3y1*1-x1y3*1-x2y1*1-x3y2*1)
S = (1/2)*(x[0]*y[1]-x[0]*y[2]+x[1]*y[2]-x[1]*y[0]+x[2]*y[0]-x[1]*y[1])
然后利用polylines()函式連接三個重心
pts = numpy.array([[x[0],y[0]],[x[1],y[1]],[x[2],y[2]]])
pts = pts.reshape((-1,1,2))
cv2.polylines(img1,[pts],True,(255, 0, 0),10)
在這里reshape()是為了規范引數形式,讓pts自適應維度大小,
最終的圖形為


本文章是作者為了記錄學習程序而寫,如果有錯誤請大家指正,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/312238.html
標籤:其他
