2015-10-19 764 views
10

使用Python檢測圖像中大致水平的紅色激光線的最快最可靠的方法是什麼?我正在研究一個與3D激光掃描相關的小型項目,並且我需要能夠檢測圖像中的激光,以計算距離失真的距離。如何使用Python在圖像中檢測激光線

首先,我有兩個圖像,一個已知不包含激光線的參考圖像A和一個包含可能失真的激光線的圖像B.例如

樣品圖像A:

enter image description here

樣品圖像B:

enter image description here

由於這些是RGB,但激光是紅色的,我去除由剝出藍色一些噪聲和綠色通道使用此功能:

from PIL import Image 
import numpy as np 

def only_red(im): 
    """ 
    Strips out everything except red. 
    """ 
    data = np.array(im) 
    red, green, blue, alpha = data.T 
    im2 = Image.fromarray(red.T) 
    return im2 

這讓我這些圖片:

enter image description here

enter image description here

接下來,我嘗試通過採取利用PIL.ImageChops.difference()這兩個圖像的差異消除更多的噪音。理想情況下,兩幅圖像之間的曝光將是相同的,導致除了激光線之外的差異不包含任何內容。不幸的是,由於激光增加了光線,每幅圖像的曝光和整體亮度明顯不同,導致差異仍然存在相當大的噪音。例如

enter image description here

我的最後一步是做一個「最好的猜測」在何處線路。因爲我知道這條線會大致水平,激光線應該是圖像中最亮的部分,所以我掃描每一列並找到具有最亮像素的行,我假定它是激光線。這個代碼是:

import os 
from PIL import Image, ImageOps 
import numpy as np 

x = Image.open('laser-diff.png', 'r') 
x = x.convert('L') 

out = Image.new("L", x.size, "black") 
pix = out.load() 

y = np.asarray(x.getdata(), dtype=np.float64).reshape((x.size[1], x.size[0])) 
print y.shape 
for col_i in xrange(y.shape[1]): 
    col_max = max([(y[row_i][col_i], row_i) for row_i in xrange(y.shape[0])]) 
    col_max_brightness, col_max_row = col_max 
    print col_i, col_max 
    pix[col_i, col_max_row] = 255 

out.save('laser-line.png') 

我真正需要執行我的距離計算是col_max值的數組,但laser-line.png幫助我想象的成功,看起來像:

enter image description here

正如您所看到的,估計非常接近,但它仍然有一些噪音,主要是在圖像的左側,激光線被亞光黑色表面吸收。

我該怎麼做才能提高我的準確度和/或速度?我試圖在ARM平臺(如Raspberry Pi)上運行它,所以我擔心我的代碼可能效率太低而無法正常運行。

我對Numpy的矩陣函數並不完全熟悉,所以我不得不解決一個慢循環來掃描每列而不是更有效的東西。有沒有一種快速的方法來找到Numpy中每列最亮像素的行?

此外,有沒有一種可靠的方法來平衡圖像之前執行差異而不使激光線變暗?

+0

也許最後,您可以刪除y座標不在25%〜75%分位數中的所有點。然後你可以得到一個更好的結果,然後使用locf ..等 –

+0

@ B.Mr.W填寫缺失的值,你部分正確。由於激光器安裝在相機下方並平行於其焦平面,因此所有激光點都應低於中間行,這意味着以上所有點都是噪音。謝謝。 – Cerin

回答

1

首先,您可以重新調整負像的強度,然後再從正像中減去它,以消除更多噪點。例如,可能通過平均強度的比例來重新縮放比例可能是一個很好的第一次嘗試?

您也可以嘗試把一個門檻:如果你的最大下面任何良好的價值,那麼它可能不是你的激光,但嘈雜的點...

然後是numpy的能找到的最好行/列具有argmax功能。

1

首先輸入激光顏色,只留下紅色(在這種情況下)。然後應用相同的效果並檢查結果。

在這種情況下,您的污染結果會少得多。 Result

在分析門上的紅色時遇到了問題,該紅色已經丟失。

+0

我不知道激光的顏色,除了它大致是紅色的。我不能簡單地認爲紅色是激光,因爲場景中可能有紅色的物體。該解決方案必須自動化,因此我無法在每幅圖像中手動指示激光顏色。 – Cerin

+0

然後使用您的圖片,滾動圖表。可能最大的辦法是找到一條激光線。在圖形的入口處將是具有兩個黑色和兩個白色像素的像素。 –

1

我試着做點什麼。我不認爲它是完全健壯的。但在你的例子中,它工作得相當好。

我用canny邊緣檢測來檢測你的「差異」圖像中的邊緣。然後應用霍夫線變換,如this tutorial。 所以我開始處理你的圖像(我在代碼中調用lineDetection.jpg)。

enter image description here

下面是最終腳本

import cv2 
import numpy as np 

img = cv2.imread('lineDetection.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray,10,100) 
minLineLength = 50 
maxLineGap = 20 
lines = cv2.HoughLinesP(edges,0.05,np.pi/5000,10,minLineLength,maxLineGap) 
print(len(lines)) 
for i in range(len(lines)): 
    x1,y1,x2,y2 = lines[i][0] 
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2) 

cv2.imwrite('houghlines5.jpg',img) 

在處理的圖像上檢測到的綠線。 (你可以將其添加到原始圖像的效果更好)

enter image description here

希望它能幫助。