# 怎么用Python OpenCV尋找兩條曲線直接的最短距離
## 引言
在計算機視覺和圖像處理中,計算兩條曲線之間的最短距離是一個常見需求。無論是工業檢測中的零件間隙測量,還是醫學圖像分析中的血管距離計算,都需要精確的距離測量技術。本文將詳細介紹如何使用Python和OpenCV庫來實現這一功能。
## 準備工作
### 安裝必要庫
```bash
pip install opencv-python numpy matplotlib
遍歷兩條曲線上的所有點組合,計算每對點之間的距離,然后取最小值。
import cv2
import numpy as np
def min_distance_brute_force(curve1, curve2):
min_dist = float('inf')
for pt1 in curve1:
for pt2 in curve2:
dist = np.linalg.norm(pt1 - pt2)
if dist < min_dist:
min_dist = dist
return min_dist
使用scipy的KDTree數據結構進行空間分區,大幅提高查詢效率。
from scipy.spatial import KDTree
def min_distance_kdtree(curve1, curve2):
tree = KDTree(curve1)
dists, _ = tree.query(curve2)
return np.min(dists)
方法 | 100點耗時 | 1000點耗時 |
---|---|---|
暴力計算 | 15ms | 1200ms |
KDTree | 3ms | 30ms |
OpenCV提供了pointPolygonTest
函數,可以計算點到輪廓的距離。
def opencv_contour_distance(contour1, contour2):
# 將輪廓轉換為凸包減少計算量
hull1 = cv2.convexHull(contour1)
hull2 = cv2.convexHull(contour2)
min_dist = float('inf')
for pt in hull1[:,0,:]:
dist = cv2.pointPolygonTest(hull2, tuple(pt), True)
if abs(dist) < min_dist:
min_dist = abs(dist)
return min_dist
img = cv2.imread('pcb.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHN_APPROX_SIMPLE)
contour1, contour2 = contours[0], contours[1] # 假設有兩個主要輪廓
distance = min_distance_kdtree(contour1[:,0,:], contour2[:,0,:])
# 繪制結果
cv2.drawContours(img, [contour1], -1, (0,255,0), 2)
cv2.drawContours(img, [contour2], -1, (0,0,255), 2)
cv2.putText(img, f"Min Distance: {distance:.2f}px", (10,30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2)
def simplify_curve(curve, epsilon=1.0):
return cv2.approxPolyDP(curve, epsilon, closed=False)
先使用低分辨率圖像快速定位可能區域,再在高分辨率區域精確計算
使用CUDA加速的OpenCV版本處理大規模數據:
cv2.cuda.setDevice(0)
gpu_contour1 = cv2.cuda_GpuMat()
gpu_contour1.upload(contour1)
A: 對于閉合曲線,建議先使用cv2.convexHull
獲取凸包
給定兩條參數曲線: [ C_1(t) = (x_1(t), y_1(t)) ] [ C_2(s) = (x_2(s), y_2(s)) ]
距離函數: [ D(t,s) = \sqrt{(x_1(t)-x_2(s))^2 + (y_1(t)-y_2(s))^2} ]
需要求解: [ \min_{t,s} D(t,s) ]
將方法擴展到3D空間,使用相同原理但增加z坐標
在視頻序列中跟蹤曲線距離變化
當檢測距離小于安全閾值時觸發報警
本文介紹了三種計算曲線間最短距離的方法,從基礎的暴力計算到高效的KDTree加速,再到OpenCV專用函數。實際應用中應根據具體場景選擇合適的方法:
附錄:完整代碼示例
import cv2
import numpy as np
from scipy.spatial import KDTree
def main():
# 生成兩條示例曲線
t = np.linspace(0, 2*np.pi, 100)
curve1 = np.column_stack([t*10, np.sin(t)*50 + 100])
curve2 = np.column_stack([t*10 + 15, np.cos(t)*40 + 120])
# 計算最短距離
tree = KDTree(curve1)
dists, _ = tree.query(curve2)
min_dist = np.min(dists)
# 可視化
img = np.zeros((300, 300, 3), dtype=np.uint8)
cv2.polylines(img, [curve1.astype(int)], False, (0,255,0), 2)
cv2.polylines(img, [curve2.astype(int)], False, (0,0,255), 2)
cv2.putText(img, f"Distance: {min_dist:.2f}", (10,30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,255,255), 2)
cv2.imshow("Result", img)
cv2.waitKey(0)
if __name__ == "__main__":
main()
”`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。