OpenCV直線擬合檢測
點擊上方“小白學視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
本文轉自:opencv學堂
霍夫直線檢測容易受到線段形狀與噪聲的干擾而失真,這個時候我們需要另辟蹊徑,通過對圖像進行二值分析,提取骨架,對骨架像素點擬合生成直線,這種做法在一些場景下非常有效,而且效果很好,在各個論壇以及QQ群中經(jīng)常有人問OpenCV中如何通過一些點來擬合直線,其實OpenCV中都有現(xiàn)成的函數(shù)可以使用。在介紹具體的編碼之前,首先介紹一下相關知識點:
1. 距離變換
距離變換是二值圖像處理與操作中常用手段,在骨架提取,圖像窄化中常有應用。距離變換的結果是得到一張與輸入圖像類似的灰度圖像,但是灰度值只出現(xiàn)在前景區(qū)域。并且越遠離背景邊緣的像素灰度值越大。OpenCV中距離變換的函數(shù)如下:
distanceTransform(src, distanceType, maskSize, dst=None, dstType=None):
- src 表示輸入的二值圖像
- distanceType,常見的有DIST_L1、DIST_L2、DIST_C三種方式
- maskSize,支持3x3、5x5、DIST_MASK_PRECISE
- dst輸出距離變換圖像
- dstType 數(shù)據(jù)類型、默認是CV_32F
DIST_L1、DIST_L2、DIST_C計算像素距離方式如下:

其中當選擇DIST_L2與DIST_MASK_PRECISE時候,OpenCV會使用TBB并行計算加速,DIST_L1與DIST_C是比較精確的距離計算方式、DIST_L2是比較快而粗糙的距離計算方式。下圖是基于DIST_L2計算得到結果:

2. 水平與垂直投影
關于這個OpenCV中我沒有發(fā)現(xiàn)直接可以使用的相關API,所以我自己寫了點代碼,二值圖像的水平或者垂直投影可以用于粘連字符分割、對象分離,發(fā)現(xiàn)局部極大值像素等處理,是非常重要的二值圖像分析與處理手段。假設有二值圖像與其像素分布如下:

其水平與垂直投影則分別如下:

二:案例分析

對上面這樣一張圖像,需要對其提取水平與垂直的兩條直線,完整的代碼實現(xiàn)分為如下幾步:1.對二值圖像實現(xiàn)距離變換
h, w, ch = frame.shape
# 二值化圖像
print("start to detect lines...\n")
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("binary image", binary)
cv.imwrite("D:/binary.png", binary)
dist = cv.distanceTransform(binary, cv.DIST_L1, cv.DIST_MASK_PRECISE)
2.水平與垂直投影提取骨架
result = np.zeros((h, w), dtype=np.uint8)
ypts = []
for row in range(h):
cx = 0
cy = 0
max_d = 0
for col in range(w):
d = dist[row][col]
if d > max_d:
max_d = d
cx = col
cy = row
result[cy][cx] = 255
ypts.append([cx, cy])
xpts = []
for col in range(w):
cx = 0
cy = 0
max_d = 0
for row in range(h):
d = dist[row][col]
if d > max_d:
max_d = d
cx = col
cy = row
result[cy][cx] = 255
xpts.append([cx, cy])
cv.imshow("lines", result)
cv.imwrite("D:/skeleton.png", result)
3.根據(jù)骨架像素點擬合直線
frame = self.line_fitness(ypts, image=frame)
frame = self.line_fitness(xpts, image=frame, color=(255, 0, 0))
cv.imshow("fit-lines", frame)
cv.imwrite("D:/fitlines.png", frame)
每步執(zhí)行之后的輸出分別如下:
距離變換結果

骨架提取結果

擬合直線結果

交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關微信群。請勿在群內發(fā)送廣告,否則會請出群,謝謝理解~

