一、效果
OpenCv版本4.0.0
Python版本3.7.2
編譯環境: PyCharm
二、代碼
import cv2 as cv
import numpy as np
from scipy.spatial import distance as dist
# 定義中點座標運算
def midpoint(ptA, ptB):
return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)
def measure(img):
# 轉灰度
gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
# 圖像二值化
ret, thresh = cv.threshold(gray, 127, 255, 0)
# 計算黑色方塊的4個角點座標
contours, hierarchy = cv.findContours(thresh, 1, 2)
for cnt in contours:
# 求取輪廓的幾何距
M = cv.moments(cnt)
# 獲取輪廓的外接矩形,x,y是綠框左上角的像數座標點,w,h是綠框的長,寬
x, y, w, h = cv.boundingRect(cnt)
# 計算最小輪廓,紅框
rect = cv.minAreaRect(cnt)
# 計算紅框4個角的像數座標
box = cv.boxPoints(rect)
# 像數是整型,所以將座標轉成整型
box = np.int0(box)
if M['m00'] != 0:
# print(M)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
#根據幾何距獲取的中心點,畫出中心圓,被藍線擋了所以看不到
cv.circle(image,(np.int(cx),np.int(cy)),2,(0,255,255),-1)
#畫綠框
cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
#畫紅框4個角
cv.drawContours(img, [box], 0, (0, 0, 255), 2)
for (x, y) in box:
cv2.circle(img, (int(x), int(y)), 5, (0, 0, 255), -1)
# tl左上角像數座標,tr右上角像數座標,br右下角像數座標,bl左下角像數座標
(tl, tr, br, bl) = box
# 計算紅框4條邊的中心點
(tltrX, tltrY) = midpoint(tl, tr)
(blbrX, blbrY) = midpoint(bl, br)
(tlblX, tlblY) = midpoint(tl, bl)
(trbrX, trbrY) = midpoint(tr, br)
# 畫點
cv2.circle(img, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
cv2.circle(img, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
cv2.circle(img, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
cv2.circle(img, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)
# 畫線連接4個點,也就是圖片中2條藍線
cv2.line(img, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
(255, 0, 0), 2)
cv2.line(img, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
(255, 0, 0), 2)
# 計算中心點的座標
dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
# 將像數長度轉成實際長度,6.5相當於比例尺,我用的是mm單位,也就是所1mm相當於6.5個像數
dimA = dA / 6.5
dimB = dB / 6.5
# 將計算結果打印在原圖上,也就是黃色的內容
cv2.putText(img, "{:.1f}mm".format(dimA),
(int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,
0.65, (0, 255, 255), 2)
cv2.putText(img, "{:.1f}mm".format(dimB),
(int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,
0.65, (0, 255, 255), 2)
cv.imshow("mo", img)
# 啓動攝像頭,設置分辨率
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
while(cap.isOpened()):
ret, frame = cap.read()
img = cv2.flip(frame, -1)
#創建GUI窗口,形式爲自適應
cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE)
#通過名字將圖像和窗口聯繫
cv2.imshow("input image", img)
measure(img)
# 如果按下P鍵,將保存圖片到D:/Program Files/kk.jpg並退出
if cv2.waitKey(1) & 0xFF == ord('p'):
cv2.imwrite("D:/Program Files/kk.jpg", img)
break
參考內容
1.https://www.pyimagesearch.com/2016/03/28/measuring-size-of-objects-in-an-image-with-opencv/
2.https://docs.opencv.org/4.0.0/dd/d49/tutorial_py_contour_features.html
3.https://www.cnblogs.com/XJT2018/p/9952671.html