以最左物體重心當基準點,測量各物體重心到基準點距離。
★範例所使用的圖檔下載位置
★程式範例執行
from scipy.spatial import distance as dist from imutils import perspective from imutils import contours from PIL import Image 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() # 原尺寸單位為inch ap.add_argument("-w", "--width", type=float, required=True) args = vars(ap.parse_args()) # 剪裁圖片→只留基準物 imgC = Image.open("A.png") cut = imgC.crop((0, 0, 200, 200)) cut.save("AA.png") imgC = cv2.imread("AA.png", 1) grayC = cv2.cvtColor(imgC, cv2.COLOR_BGR2GRAY) blurredC = cv2.GaussianBlur(grayC, (5, 5), 0) threshC = cv2.threshold(blurredC, 60, 255, cv2.THRESH_BINARY)[1] cntsC = cv2.findContours(threshC.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cntsC = cntsC[0] if imutils.is_cv2() else cntsC[1] (cntsC, _) = contours.sort_contours(cntsC) for b in cntsC: # 辨識基準物重心 M = cv2.moments(b) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) # 讀取圖檔→灰階→模糊 # cv2.GaussianBlur模糊程度可以用3x3, 5x5, 7x7 img = cv2.imread("A.png", 1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] # 進行輪廓偵測 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] (cnts, _) = contours.sort_contours(cnts) refObj = None for c in cnts: cv2.drawContours(img, [c], -1, (220, 255, 250), 1) cv2.circle(img, (cX, cY), 6, (255, 255, 255), -1) cv2.putText(img, "datummark", (cX - 20, cY - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 220), 2) # 計算輪廓旋轉邊界 gear7 = cv2.minAreaRect(c) gear7 = cv2.cv.BoxPoints(gear7) if imutils.is_cv2() else cv2.boxPoints(gear7) gear7 = np.array(gear7, dtype="int") # 計算輪廓旋轉邊界 gear7C = cv2.minAreaRect(c) gear7C = cv2.cv.BoxPoints(gear7C) if imutils.is_cv2() else cv2.boxPoints(gear7C) gear7C = np.array(gear7C, dtype="int") gear7 = perspective.order_points(gear7) gear7C = perspective.order_points(gear7C) # 辨識物體重心 M = cv2.moments(c) PcX = int(M["m10"] / M["m00"]) PcY = int(M["m01"] / M["m00"]) print (PcX ,PcY) if refObj is None: # 計算基準物的中點 (tl, tr, br, bl) = gear7C (tlblX, tlblY) = midpoint(tl, bl) (trbrX, trbrY) = midpoint(tr, br) # 用座標法計算兩物體重心距離 # 單位換算成mm D = dist.euclidean((tlblX, tlblY), (trbrX, trbrY)) refObj = (gear7C, (cX, cY), D / args["width"] / 2.54 / 100) continue orig = img.copy() # 基準物和測量物中心點&點到點的距離 cv2.circle(orig, (int(PcX), int(PcY)), 5, (240, 0, 150), -1) cv2.circle(orig, (int(cX), int(cY)), 5, (240, 0, 150), -1) cv2.line(orig, (int(PcX), int(PcY)), (int(cX), int(cY)), (240, 0, 150), 2) # 用座標距離法算出圖中的座標距離,並和實際的距離做比值,求出待測實際距離 D = dist.euclidean((PcX, PcY), (cX, cY)) / refObj[2] (mX, mY) = midpoint((PcX, PcY), (cX, cY)) cv2.putText(orig, "{:.2f}mm".format(D), (int(mX), int(mY - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (240, 0, 100), 2) # "{:.1f}mm" 取到小數點第一位,依此類推 cv2.imshow("Image", orig) cv2.waitKey(0)
★範例執行結果
★細部程式介紹
【PIL裁剪圖片】 ◎範例程式:
#導入pillow from PIL import Image #載入原始圖片 img = Image.open("A1.png") #從左上角開始裁剪200*200的圖片,再以B1檔名存取 cut = img.crop((0, 0, 200, 200)) cut.save("B1.png")
◎結果: 【cv2.moments】→取物品重心座標 ◎使用格式: ◎範例程式:
from imutils import contours import imutils import cv2 image = cv2.imread("A1.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cnts = cv2.findContours(gray.copy(), 1, 2) cnts = cnts[0] if imutils.is_cv2() else cnts[1] (cnts,_) = contours.sort_contours(cnts) for c in cnts: M = cv2.moments(c) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print (cX,cY) cv2.drawContours(image, [c], -1, (0, 255, 0), 2) cv2.circle(image, (cX, cY), 7, (0, 255, 255), -1) cv2.imshow("Image", image) cv2.waitKey(0)
◎結果:
Comments
comments powered by Disqus