辨識圖片中兩物體的實際距離 Measuring distance between objects in an image
★範例所使用的圖檔下載位置
★程式範例執行
#以圖片最左矩形寬作為依據的距離測量 from scipy.spatial import distance as dist from imutils import perspective from imutils import contours import numpy as np import argparse import imutils import cv2 def midpoint(ptA, ptB): return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5) ap = argparse.ArgumentParser() #讓圖檔於開啟指令執行時輸入最左端的矩形寬度 #cmd進入py檔和圖檔所在資料夾後,輸入python 1117_distance.py --width 寬度(inch) 開啟 #寬度可直接輸入數字 ap.add_argument("-w", "--width", type=float, required=True) args = vars(ap.parse_args()) #讀取圖檔→灰階→模糊 #cv2.GaussianBlur模糊程度可以用3x3, 5x5, 7x7 img = cv2.imread("gear4.png", 1) Gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(Gray, (3, 3), 0) #輪廓描邊→補空&侵蝕 edged = cv2.Canny(gray, 50, 100) edged = cv2.dilate(edged, None, iterations=1) edged = cv2.erode(edged, None, iterations=1) #進行偵測 cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] #以最左矩形四點&中心為基準到其他物品的距離標示線顏色 (cnts, _) = contours.sort_contours(cnts) colors = ((0, 0, 255), (240, 0, 159), (0, 165, 255), (255, 255, 0), (255, 0, 255)) refObj = None #進行一連串的輪廓校準 for c in cnts: # 忽略過小的輪廓 (限定輪廓描繪範圍) if cv2.contourArea(c) < 1500: continue # 計算輪廓旋轉邊界 gear4 = cv2.minAreaRect(c) gear4 = cv2.cv.BoxPoints(gear4) if imutils.is_cv2() else cv2.boxPoints(gear4) gear4 = np.array(gear4, dtype="int") # 重新設定邊界角落座標的順序, 由左上 右上 右下 左下, 順時針方向繞 gear4 = perspective.order_points(gear4) # 計算物體的中心 cX = np.average(gear4[:, 0]) cY = np.average(gear4[:, 1]) # 以左邊邊界輪廓當基準, 當參考對象 if refObj is None: # 計算物品左右邊界的中點 (tl, tr, br, bl) = gear4 (tlblX, tlblY) = midpoint(tl, bl) (trbrX, trbrY) = midpoint(tr, br) # 用座標法計算兩物體中心距離 D = dist.euclidean((tlblX, tlblY), (trbrX, trbrY)) refObj = (gear4, (cX, cY), D / args["width"]) continue # 輪廓描繪 orig = img.copy() cv2.drawContours(orig, [gear4.astype("int")], -1, (0, 255, 0), 2) # 其餘物品的輪廓描繪 cv2.drawContours(orig, [refObj[0].astype("int")], -1, (0, 255, 0), 2) # 最左邊物品的輪廓描繪 # refCoords為基準物, objCoords為測量物 refCoords = np.vstack([refObj[0], refObj[1]]) objCoords = np.vstack([gear4, (cX, cY)]) for ((xA, yA), (xB, yB), color) in zip(refCoords, objCoords, colors): # 基準物的四個角&中心點 測量物的四個角&中心點 點到點的距離 cv2.circle(orig, (int(xA), int(yA)), 5, color, -1) cv2.circle(orig, (int(xB), int(yB)), 5, color, -1) cv2.line(orig, (int(xA), int(yA)), (int(xB), int(yB)), color, 2) #用座標距離法算出圖中的座標距離,並和實際的距離做比值,求出待測實際距離 D = dist.euclidean((xA, yA), (xB, yB)) / refObj[2] (mX, mY) = midpoint((xA, yA), (xB, yB)) cv2.putText(orig, "{:.1f}in".format(D), (int(mX), int(mY - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.55, color, 2) # "{:.1f}in" 取到小數點第一位 cv2.imshow("Image", orig) cv2.waitKey(0)
Comments
comments powered by Disqus