2017-06-06 1431 views
5

我有一張激光線的照片,我想從圖像中提取該線。現在在圖像中提取激光線(使用OpenCV)

enter image description here

的問題是,即:

enter image description here

作爲激光線是紅色的,我走圖像的紅色通道,然後在每一行中搜索的最高強度還有一些點不屬於激光線(如果放大第二張圖片,則可以看到這些點)。

有沒有人有下一步的想法(去除單點,也提取線)?

這是另一種檢測線條的方法: 首先我模糊了帶有內核的「黑白」線,然後將細線(骨架)細化爲細線,然後將OpenCV函數應用於檢測線..結果是如下圖像中:enter image description here

NEW:

現在我有另一個困難的情況。 我必須提取綠色激光。
這裏存在的問題是激光線的顏色範圍更寬和更改。
在激光線的某些部分,像素只有很高的綠色分量,而在其他部分,像素也有很高的藍色分量。 enter image description here

+0

問題是你採取每一行中最高的那個。所以你總是會得到每行一個點。也許你可以基於該值設置閾值(例如,如果Red分量大於100)。您仍然可以獲得其他紅色物體或指向圖像。你也應該考慮藍色和綠色組件的值,例如,白色是(255,255,255),所以它們都是高的。你應該把那些紅色高和其他頻道相當低的值。此外,您可以使用線條檢測算法來過濾其他斑點 – api55

+0

我確實已經做到了這一點(以紅色爲高,但綠色和藍色相當低的像素) – Mirnyy

+0

您也可以嘗試擴張和侵蝕,因爲線條點相當一起,並且噪音點不是。或者嘗試[Hough line transform](http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html)以僅獲取線條,但我不確定曲線將被檢測到。 – api55

回答

1

我真的很抱歉沒有任何代碼的簡短答案,但我建議你採取輪廓和處理它們。

我不知道你需要確切的東西,所以這裏爲大家介紹兩種方法:

  • 只是收集儘可能多的爲上一行可能輪廓(利用中心,並嘗試找到最小的平均直線)

  • 作爲第一種方式,但試圖啓發式地組合分離的線....這是很難,但這可能會給你幾乎完整的激光線從圖像。

-

一些示例爲你的圖片:

import cv2 
import numpy as np 
import math 

img = cv2.imread('image.png') 
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) 
# filtering red area of hue 
redHueArea = 15 
redRange = ((hsv[:, :, 0] + 360 + redHueArea) % 360) 
hsv[np.where((2 * redHueArea) > redRange)] = [0, 0, 0] 
# filtering by saturation 
hsv[np.where(hsv[:, :, 1] < 95)] = [0, 0, 0] 
# convert to rgb 
rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) 
# select only red grayscaled channel with low threshold 
gray = cv2.cvtColor(rgb, cv2.COLOR_RGB2GRAY) 
gray = cv2.threshold(gray, 15, 255, cv2.THRESH_BINARY)[1] 
# contours processing 
(_, contours, _) = cv2.findContours(gray.copy(), cv2.RETR_LIST, 1) 
for c in contours: 
    area = cv2.contourArea(c) 
    if area < 8: continue 
    epsilon = 0.1 * cv2.arcLength(c, True) # tricky smoothing to a single line 
    approx = cv2.approxPolyDP(c, epsilon, True) 
    cv2.drawContours(img, [approx], -1, [255, 255, 255], -1) 

cv2.imshow('result', img) 
cv2.waitKey(0) 

在你的情況下,它的工作完美,但是,正如我已經說過,你需要做的輪廓,更多的工作。

enter image description here

+0

我也已經試過..你可以看到我現在張貼的新形象的結果.. – Mirnyy

+0

首先非常感謝! 我剛剛在C++中實現了你的代碼,它的工作非常可靠...... 但是對於我來說,提取那個*弧*線並不僅僅是一條近似的直線更重要(因爲我們想要使用該線來進行三角測量法測量到物體/地面的距離)... 你有一個想法如何擴展它來提取該曲線而不是一條直線? – Mirnyy

+1

請參閱https://stackoverflow.com/questions/44406469/draw-a-curve-line-going-through-through-the-blobs-in-opencv/44410748#44410748這也許對您有所幫助。 –

3

獲取每一行中的最高值總是輸出值,而不是當值不夠高忽視。考慮使用一個門檻,以便你可以丟棄那些不夠高的門檻。

但是,這根本不是一種非常有效的方法。更好更容易的解決方案是使用OpenCV功能inRange();在所有三個通道中定義紅色的下限和上限,並且這將返回具有白色像素的二值圖像,其中圖像強度在該BGR範圍內。

這是蟒蛇,但它的工作,應該很容易看到如何使用功能:

import cv2 
import numpy as np 

img = cv2.imread('image.png') 
lowerb = np.array([0, 0, 120]) 
upperb = np.array([100, 100, 255]) 
red_line = cv2.inRange(img, lowerb, upperb) 

cv2.imshow('red', red_line) 
cv2.waitKey(0) 

這將產生輸出: Red line binary iamge

這可以通過尋找進一步處理輪廓或其他方法將點變成一條好曲線。

+0

首先非常感謝您的努力! 直到這一步當然非常清楚.. 但主要問題是檢測您張貼的圖像上這些點的線/曲線.. 如果我例如嘗試連接最近的點在一起,我得到很不幸的是,「zig-zag」線... – Mirnyy

+0

你*可以*使用多項式擬合方法,但是否則,你想要對線/曲線做什麼?你需要它作爲一個二進制圖像的行是一個像素寬嗎? –

+0

是的,確切! 我想得到理想情況下爲1像素寬的曲線/曲線。 – Mirnyy