2015-10-19 11 views
10

Jaka jest najszybsza najbardziej niezawodna metoda wykrywania poziomej czerwonej linii laserowej w obrazie za pomocą języka Python? Pracuję nad małym projektem związanym z 3d skanowaniem laserowym i muszę być w stanie wykryć laser na obrazie, aby obliczyć odległość od jego zniekształceń.Jak wykryć linię lasera na obrazie używając Pythona

Na początek mam dwa obrazy, obraz odniesienia Znany z braku linii laserowej i obraz B, który zdecydowanie zawiera linię laserową, prawdopodobnie zniekształcony. na przykład

Przykładowy obraz A:

enter image description here

Przykładowy obraz B:

enter image description here

Ponieważ są to RGB, ale laser czerwony, zdjąć trochę hałasu przez odpędzanie na niebiesko i zielone kanały używające tej funkcji:

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 

że dostaje mi te obrazy:

enter image description here

enter image description here

Następnie spróbuj i eliminować więcej hałasu poprzez różnicę tych dwóch obrazów przy użyciu PIL.ImageChops.difference(). Idealnie, ekspozycja pomiędzy dwoma obrazami byłaby identyczna, powodując, że różnica nie zawiera niczego poza linią lasera. Niestety, ponieważ laser dodaje światło, ekspozycja i ogólna jasność każdego obrazu są znacząco różne, co powoduje różnicę, która wciąż ma znaczny hałas. na przykład

enter image description here

Moja Ostatnim krokiem jest stworzenie „najbardziej prawdopodobne”, jak do miejsca, gdzie linia jest. Ponieważ wiem, że linia będzie w przybliżeniu pozioma, a linia lasera powinna być najjaśniejszą rzeczą na obrazie, skanuję każdą kolumnę i znajduję wiersz z najjaśniejszym pikselem, który uważam za linię laserową. Kod na to:

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') 

All I naprawdę trzeba wykonać moje obliczenia odległość jest tablica col_max wartości, ale laser-line.png pomaga mi wyobrazić sobie sukces, a wygląda tak:

enter image description here

Jak widać, oszacowanie jest dość zbliżone, ale nadal ma trochę szumu, głównie po lewej stronie obrazu, gdzie linia lasera jest pochłaniana przez matowe czarne wykończenie.

Co mogę zrobić, aby poprawić swoją dokładność i/lub prędkość? Próbuję uruchomić to na platformie ARM, takiej jak Raspberry Pi, więc obawiam się, że mój kod może być zbyt nieefektywny, by działał dobrze.

Nie jestem w pełni obeznany z funkcjami macierzy Numpy'ego, więc musiałem zadowolić się wolną pętlą do skanowania każdej kolumny zamiast czegoś bardziej wydajnego. Czy istnieje szybki sposób na znalezienie rzędu z najjaśniejszym pikselem na kolumnę w Numpy?

Czy istnieje również niezawodny sposób wyrównywania obrazów przed wykonaniem różnicy bez ściemniania linii laserowej?

+0

Może w końcu można usunąć wszystkie punkty, których współrzędne y nie znajdują się w kwarce 25% ~ 75%. Następnie możesz uzyskać lepszy wynik, a następnie uzupełnij brakujące wartości, używając locf..etc –

+0

@ B.Mr.W. Masz częściowo rację. Ponieważ laser był zamontowany pod kamerą i równolegle do jego płaszczyzny ogniskowej, wszystkie punkty lasera powinny znajdować się poniżej środkowego rzędu, co oznacza, że ​​wszystkie punkty powyżej to szum. Dzięki. – Cerin

Odpowiedz

1

Najpierw prawdopodobnie można przeskalować intensywność negatywowego obrazu przed odjęciem go od dodatniego, aby usunąć więcej szumów. Na przykład, czy przeskalowanie przez stosunek średniej intesity może być dobrą pierwszą próbą?

Można także spróbować umieścić próg: jeśli cokolwiek poniżej max w dobrej cenie, to chyba nie twój laser ale głośny punkt ...

Następnie tak numpy można znaleźć wiersz/COL z funkcją argmax.

1

Najpierw wprowadź kolor, który jest laserem, i pozostawia tylko czerwony kolor (w tym przypadku). Następnie zastosuj te same efekty i sprawdź wynik.

W takim przypadku wynik będzie znacznie mniej zanieczyszczony. Result

Wystąpił problem przy analizie czerwonego na drzwiach, który został utracony.

+0

Nie znam koloru lasera, poza tym, że jest z grubsza czerwony. Nie mogę po prostu założyć, że czerwony jest laserem, ponieważ na scenie mogą znajdować się czerwone obiekty. To rozwiązanie musi być zautomatyzowane, więc nie mogę ręcznie wskazać koloru lasera na każdym obrazie. – Cerin

+0

następnie użyj obrazu, przewiń wykres. prawdopodobnie największym sposobem będzie linia laserowa. przy wejściu do twojego wykresu będzie każdy piksel, który ma dwa czarne i dwa białe sąsiadujące piksele. –

1

Próbowałem coś zrobić. Nie sądzę, że jest całkowicie solidny. Ale na twoim przykładzie działa całkiem dobrze.

Do wykrywania krawędzi w obrazie "różnicy" użyłem funkcji wykrywania wąskich krawędzi. Następnie zastosował transformację linii Hough, tak jak w this tutorial. Więc zacząłem od przetworzonego obrazu (który nazywam lineDetection.jpg w kodzie).

enter image description here

Oto ostateczny skrypt

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) 

W zielonej linii wykrytej na przetwarzanego obrazu. (Można by go dodać do oryginalnego obrazu za ładniejszy efekt)

enter image description here

Nadzieję, że to pomaga.