import cv2 import numpy as np thresh_gaizi=117 thresh_gaizi_range=3 thresh_yemian=257 thresh_yemian_range=3 thresh_baozhuang=436 thresh_baozhuang_range=3 value_gaizi=0 value_yemian=0 value_baozhuang=0 #對比1 #mask_img=mask_hsv #使用預先標定的顏色摳圖 #對比2 #mask_img=dst #使用Sobel融合後的檢測摳圖 #對比3 #mask_img=edge_output #使用Canny邊緣檢測演算法的檢測摳圖 mask_use=1 # 1-hsv 2-canny 3-canny #(c1)是否視窗列印訊息-除錯使用但是會降低檢測速度 debug_print=0 #除錯階段1 正式使用追求速度0 #選擇檢測形狀 detect_what=0#1圓 0矩形 #(c2)選擇是否出現標定顏色介面 detect_biaoding=1# 每次換一個光照環境 給1 滑鼠點選顏色區域矯正顏色數值,獲取範圍填寫在color_dist的最大最小中 #(c3)選擇檢測多少顏色 #檢測一種顏色 Lower顏色下限數值 Upper顏色上限數值 #color_dist = {'red': {'Lower': np.array([0, 230, 150]), 'Upper': np.array([10, 255, 190])},} #檢測多種顏色-有更多自己往後新增 color_dist = {'red': {'Lower': np.array([160, 80, 150]), 'Upper': np.array([190, 210, 220])}, 'yello': {'Lower': np.array([0, 0, 0]), 'Upper': np.array([170, 160, 80])} } hsvshow=0 #滑鼠點選函式 def getposHsv(event,x,y,flags,param): if event==cv2.EVENT_LBUTTONDOWN: print("HSV is",hsvshow[y,x]) def getColorBox(shareData,shareLock): cap = cv2.VideoCapture(0) #cv2.namedWindow('imageHSV', 1) if mask_use==1 and detect_biaoding==1: cv2.namedWindow('HSV', 1) cv2.setMouseCallback("HSV",getposHsv)#滑鼠函式 while cap.isOpened(): ret, frame = cap.read() if frame is not None: gs_frame = cv2.GaussianBlur(frame, (5, 5), 0) # 高斯模糊 hsv = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2HSV) # 轉化成HSV影像 global hsvshow hsvshow=hsv erode_hsv = cv2.erode(hsv, None, iterations=2) # 腐蝕 粗的變細 global color_dist if mask_use==1: #color_dist=color_dist pass else: color_dist = {'red': {'Lower': np.array([0, 190, 140]), 'Upper': np.array([10, 255, 255])} } for nowcoloe in color_dist: #使用純顏色摳圖 global mask_hsv if mask_use==1: mask_hsv = cv2.inRange(erode_hsv, color_dist[nowcoloe]['Lower'], color_dist[nowcoloe]['Upper']) # 灰度影像 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 高斯模糊,降低噪聲 blurred = cv2.GaussianBlur(gray, (3, 3), 0) # 影像梯度 #對比1 橫向檢測 xgrad = cv2.Sobel(blurred, cv2.CV_16SC1, 1, 0) absX = cv2.convertScaleAbs(xgrad) # 轉回uint8 #對比2 縱向檢測 ygrad = cv2.Sobel(blurred, cv2.CV_16SC1, 0, 1) absY = cv2.convertScaleAbs(ygrad) #對比3 橫+縱檢測 dst = cv2.addWeighted(absX,0.5,absY,0.5,0) #cv2.imshow("absX", absX) #cv2.imshow("absY", absY) #cv2.imshow("absX_absY", dst) edge_output = cv2.Canny(xgrad, ygrad, 50, 150) cv2.imshow("absX_absY_canny", edge_output) #img = cv2.GaussianBlur(mask_hsv,(3,3),0) #canny = cv2.Canny(img, 50, 150) #下面檢測用那個放開那個 預設是1 mask_img=frame if mask_use==1: #對比1 mask_img=mask_hsv #使用預先標定的顏色摳圖erode_hsv elif mask_use==2: #對比2 mask_img=dst #使用Sobel融合後的檢測摳圖 elif mask_use==3: #對比3 mask_img=edge_output #使用Canny邊緣檢測演算法的檢測摳圖 #print(colorshow) cnts = cv2.findContours(mask_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] draw_color=(255,255,255) if nowcoloe=="red": draw_color=(0,0,255) elif nowcoloe=="yello": draw_color=(0,255,255) elif nowcoloe=="green": draw_color=(0,255,0) image=frame if cnts: cnt = max(cnts, key=cv2.contourArea) c=cnt #函式可以計算面積,也可以使用矩 M[‘m00’] area=cv2.contourArea(c) #if area<1000:#踢出小邊界 #continue perimeter = cv2.arcLength(c,True) #計算周長 #hull = cv2.convexHull(cnt) #凸包 #最大邊界矩形(包圍盒) draw_rec=0 if draw_rec: x,y,w,h = cv2.boundingRect(c) image = cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,255),2) #旋轉矩形 draw_rec_ro=0 if draw_rec_ro : rect = cv2.minAreaRect(c) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(image,[box],0,(255,0,255),2) #最小外接圓 draw_yuan=0 if draw_yuan: (x,y),radius = cv2.minEnclosingCircle(c) center = (int(x),int(y)) radius = int(radius) img = cv2.circle(image,center,radius,(0,255,0),2) # 計算每一個輪廓的中心點 M = cv2.moments(c)#計算影像的矩,並返回一個字典 根據這些矩的值可以得到重心 M["m00"]=M["m00"]+0.001 #避免除以0 cX = int((M["m10"] / M["m00"])) cY = int((M["m01"] / M["m00"])) #print("面積",area,"周長",perimeter,'最小外接圓',radius,'輪廓的中心點',(cX,cY)) #檢測圓形 if detect_what==1: #用圓擬合目標 (x, y), radius = cv2.minEnclosingCircle(cnt) with shareLock: shareData[1]=int(x) shareData[2]=int(y) shareData[3]=int(radius) if debug_print==1: print("r",radius) #畫圓函式 radius 半徑 int(x), int(y) 位置 cv2.circle(image, (int(x), int(y)), int(radius), draw_color, 2) pass #檢測矩形 else: # # 獲取最小外接矩陣,中心點座標,寬高,旋轉角度 rect = cv2.minAreaRect(cnt) ## 獲取矩形四個頂點,浮點型 box = cv2.boxPoints(rect) # 取整 box = np.int0(box) # 獲取四個頂點座標 left_point_x = np.min(box[:, 0]) right_point_x = np.max(box[:, 0]) top_point_y = np.min(box[:, 1]) bottom_point_y = np.max(box[:, 1]) left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0] right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0] top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0] bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0] if nowcoloe=="red": #print("red",box[2][0],box[2][1]) value_gaizi=bottom_point_y #value_yemian=0 #value_baozhuang=0 if value_gaizi>= (thresh_gaizi-thresh_gaizi_range) and value_gaizi<= (thresh_gaizi+thresh_gaizi_range): cv2.putText(image, str("cap level:ok"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) else: cv2.putText(image, str("cap level:error"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.putText(image, str(top_point_y), (50,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.putText(image, str(bottom_point_y), (50,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) pt1=(0,top_point_y) pt2=(left_point_x,top_point_y) cv2.line(image, pt1, pt2, color=(0,255,0), thickness=2) pt1=(0,bottom_point_y) pt2=(left_point_x,bottom_point_y) cv2.line(image, pt1, pt2, color=(0,255,0), thickness=2) elif nowcoloe=="yello": #value_gaizi=bottom_point_y value_yemian=top_point_y value_baozhuang=bottom_point_y if value_yemian>= (thresh_yemian-thresh_yemian_range) and value_yemian<= (thresh_yemian+thresh_yemian_range): cv2.putText(image, str("liquid level:ok"), (120,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) else: cv2.putText(image, str("liquid level:error"), (120,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) if value_baozhuang>= (thresh_baozhuang-thresh_baozhuang_range) and value_baozhuang<= (thresh_baozhuang+thresh_baozhuang_range): cv2.putText(image, str("package level:ok"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) else: cv2.putText(image, str("package level:error"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) #print("yello",box[0][0],box[0][1]) cv2.putText(image, str(top_point_y), (50,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2) cv2.putText(image, str(bottom_point_y), (50,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2) pt1=(0,top_point_y) pt2=(left_point_x,top_point_y) cv2.line(image, pt1, pt2, color=(255,255,0), thickness=2) pt1=(0,bottom_point_y) pt2=(left_point_x,bottom_point_y) cv2.line(image, pt1, pt2, color=(255,255,0), thickness=2) #print(box) with shareLock: shareData[1]=box[0][0]#右上角h shareData[2]=box[0][1]#右上角w shareData[3]=box[2][0]#左下角h shareData[4]=box[2][1]#左下角w #print(rect) if debug_print==1: #print("h",box[0][0]-box[2][0],"w",box[0][1]-box[2][1]) h=abs(box[2][0]-box[0][0]) w=abs(box[2][1]-box[0][1]) #周長 zhouchang=(h+w)*2 txt = "Length:"+str(zhouchang)+" w:"+str(w)+" h:"+str(h) cv2.putText(image, txt, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) #顏色 colorshow=(color_dist[nowcoloe]['Lower']+color_dist[nowcoloe]['Upper'])/2 txt = "Color-R G B:"+str(colorshow) cv2.putText(image, txt, (50,100), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2) #座標點 x=int((box[0][0]+box[2][0])/2) y=int((box[0][1]+box[2][1])/2) txt = "Position-x:"+str(x)+" y:"+str(y) cv2.putText(image, txt, (50,150), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 255), 2) txt ="w:"+str(w)+" h:"+str(h) cv2.putText(image, txt, (50,200), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2) if rect[1][0]<90 and rect[1][1]<90: #剔除掉畫素小於90×90的框 排除干擾 pass else: cv2.drawContours(image, [np.int0(box)], -1, draw_color, 2) #為了加快速度 檢測程序連視窗都可以不顯示,影像送給給主執行緒序來顯示 cv2.imshow("RGB",image) key=cv2.waitKey(1) if key == ord('q') or key == ord('Q'): shareData[5]=0 break if mask_use==1 and detect_biaoding==1: cv2.imshow("HSV",hsv) key=cv2.waitKey(1) if key == ord('q') or key == ord('Q'): break #單獨測試程式碼 from multiprocessing import Process,Manager if __name__ == '__main__': #程序共享記憶體 manager=Manager() shareData=manager.dict()#共享資料 shareLock=manager.Lock() #程序資料鎖 #根據檢測的形狀 資料含義不同 shareData[1]=0# 圓-x 矩形-左上角h shareData[2]=0# 圓-y 矩形-左上角w shareData[3]=0# 圓-r 矩形-右下角h shareData[4]=0# 圓-無 矩形-右下角w shareData[8]=0 #wegiht shareData[9]=1# 控制標誌 控制檢測程序關閉 #開啟程序1 p1=Process(target=getColorBox,args=(shareData,shareLock)) #必須加,號 p1.deamon=True #伴隨主程序關閉而關閉 p1.start() #主程序不斷獲取程序1返回的結果 while 1: if shareData[9]==0:#串列埠按退出 break #print(shareData[1],shareData[2],shareData[3],shareData[4])