天天看點

實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

導讀

本期将介紹使用OpenCV用兩種不同的方法實作快速查找計算直線/網格線交點坐标。

直線交點計算思路與常用方法

直線交點的計算這裡列舉幾個比較常用的方法:

① 在知道直線方程的前提下(或知道直線上一點和直線角度),聯立方程求解交點坐标(注意數學坐标系和圖像坐标系的關系);

② 不知道直線方程,通過檢測直線的方法(例如霍夫變換)計算直線方程,然後聯立方程求解交點坐标;

第一種方法當然是最理想的情況,這樣計算的交點也最準确。但是大多數情況我們并不能預先知道直線方程。第二種方法在幹擾少的情況比較适用,當然我們還要考慮OpenCV的直線檢測方法可能會有重複直線被檢測,還需要做剔除操作。

綜上來看,前面兩種方法并不是非常好用,下面來介紹兩種簡單實用的方法:

③;

本文使用方法③和方法④,設定合适的參數即可檢測到直線交點位置。

效果展示

本文示範圖檔包含2張,一張是簡單的三條直線相交,另一張是多條直線相交形成網格,分别計算它們的交點位置并辨別,效果如下:

原圖:

實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

結果圖:

實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

原圖:

實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

結果圖:

實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

實作步驟與對應代碼

方法③實作步驟與代碼:

(1) Harris角點檢測+門檻值處理;

import cv2
import numpy as np


img = cv2.imread('1.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
mask = np.zeros(gray.shape,np.uint8)
dst = cv2.cornerHarris(gray,2,3,0.04)
ret,thresh = cv2.threshold(dst,0.01,255,cv2.THRESH_BINARY)
cv2.imshow('thresh',thresh)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

(2) 形态學膨脹(将角點連接配接起來);

k1=np.ones((5,5), np.uint8)#指定膨脹核大小
mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, k1)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

(3) 輪廓篩選,w>10 and h > 10,直線交點位置輪廓更大。

contours,hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
  (x, y, w, h) = cv2.boundingRect(cnt)
  if w > 10 and h > 10:
      cx = int(x + w / 2)
      cy = int(y + h / 2)
      cv2.circle(img,(cx, cy),10,(0,255,0),2, cv2.LINE_AA)
      cv2.circle(img,(cx, cy),2,(0,0,255),-1, cv2.LINE_AA)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

對于圖2,代碼修改兩處參數:

k1=np.ones((1,7), np.uint8)
......
if w > 1 and h > 1:
......      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

方法④實作步驟與代碼:

(1) 固定門檻值二值化凸顯直線為白色,背景為黑色;

import numpy as np
import cv2


img= cv2.imread('1.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thres= cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY) 
cv2.imshow('thres', thres)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

(2) 指定核做開運算,再做閉運算;

k1=np.ones((1,7), np.uint8)
k2=np.ones((7,1), np.uint8)


mask = cv2.morphologyEx(thres, cv2.MORPH_OPEN, k1)
cv2.imshow('open', mask)


mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, k2)
cv2.imshow('close', mask)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

(3) 輪廓查找與中心計算标示;

contours,hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
  (x, y, w, h) = cv2.boundingRect(cnt)
  #cv2.rectangle(img, (x, y),(x+w,y+h),(0, 255, 0), 2)
  cx = int(x + w / 2)
  cy = int(y + h / 2)
  cv2.circle(img,(cx, cy),10,(0,255,0),2, cv2.LINE_AA)
  cv2.circle(img,(cx, cy),2,(0,0,255),-1, cv2.LINE_AA)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

對于圖2,代碼修改兩處參數:

ret, thres= cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
......
k1=np.ones((3,1), np.uint8)
k2=np.ones((1,7), np.uint8)      
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)
實用技巧 | OpenCV快速計算直線/網格線交點坐标(附源碼)

此處涉及到的形态學技巧原來有介紹過,可以參看下面連結檢視:

​​OpenCV形态學處理使用技巧與應用示範​​

結尾語:

文章實作的步驟并非最優,但基本檢測效果還OK,大家跟着上述步驟和代碼完全可以自己做出來。當然如果你懶得動手,那就加入知識星球擷取吧,那裡為你準備了完整源碼和測試素材,還有C++源碼。

更多實用文章請移步至--精華文章--專題文章分類。

—THE END—

繼續閱讀