Wie erkennt man eine Laserlinie in einem Bild mit Python?



Answers

Geben Sie zuerst die Farbe ein, die der Laser ist und lassen Sie nur die rote Farbe (in diesem Fall). Wenden Sie dann die gleichen Effekte an und überprüfen Sie das Ergebnis.

In diesem Fall haben Sie ein viel weniger verschmutztes Ergebnis. Ergebnis

Ein Problem tritt bei der Analyse des Rots an der Tür auf, das verloren gegangen ist.

Question

Was ist die schnellste und zuverlässigste Methode, um eine ungefähr horizontale rote Laserlinie in einem Bild mit Python zu erkennen? Ich arbeite an einem kleinen Projekt im Zusammenhang mit 3D-Laserscanning, und ich muss in der Lage sein, den Laser in einem Bild zu erkennen, um die Entfernung von seiner Verzerrung zu berechnen.

Zu Beginn habe ich zwei Bilder, ein Referenzbild A, von dem bekannt ist, dass es keine Laserlinie enthält, und ein Bild B, das definitiv eine Laserlinie enthält, möglicherweise verzerrt. z.B

Beispielbild A:

Beispielbild B:

Da dies RGB sind, aber der Laser rot ist, entferne ich etwas Rauschen, indem ich die blauen und grünen Kanäle mit dieser Funktion entferne:

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

Das bringt mir diese Bilder:

Als nächstes versuche ich, mehr Rauschen zu eliminieren, indem ich die Differenz dieser zwei Bilder mit PIL.ImageChops.difference() . Idealerweise wäre die Belichtung zwischen den beiden Bildern identisch, wodurch die Differenz nichts als die Laserlinie enthält. Da der Laser jedoch Licht hinzufügt, sind die Belichtung und die Gesamthelligkeit jedes Bildes leider erheblich unterschiedlich, was zu einem Unterschied führt, der immer noch beträchtliches Rauschen aufweist. z.B

Mein letzter Schritt ist eine "bestmögliche Schätzung", wo die Linie ist. Da ich weiß, dass die Linie ungefähr horizontal ist und die Laserlinie die hellste im Bild sein sollte, scanne ich jede Spalte und finde die Reihe mit dem hellsten Pixel, die ich für die Laserlinie halte. Der Code dafür lautet:

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

Alles, was ich wirklich brauche, um meine Distanzberechnung durchzuführen, ist die Anordnung der col_max Werte, aber die laser-line.png hilft mir, den Erfolg zu visualisieren und sieht so aus:

Wie Sie sehen können, ist die Schätzung ziemlich nah, aber es hat immer noch etwas Rauschen, hauptsächlich auf der linken Seite des Bildes, wo die Laserlinie von einem mattschwarzen Finish absorbiert wird.

Was kann ich tun, um meine Genauigkeit und / oder Geschwindigkeit zu verbessern? Ich versuche, dies auf einer ARM-Plattform wie dem Raspberry Pi auszuführen, daher mache ich mir Sorgen, dass mein Code zu ineffizient sein könnte, um gut zu laufen.

Ich bin mit Numpys Matrixfunktionen nicht ganz vertraut, also musste ich mich mit einer langsamen for-Schleife begnügen, um jede Spalte zu scannen, anstatt etwas effizienter zu machen. Gibt es eine schnelle Möglichkeit, die Zeile mit dem hellsten Pixel pro Spalte in Numpy zu finden?

Gibt es auch eine zuverlässige Möglichkeit, die Bilder vor der Differenz zu entzerren, ohne die Laserlinie zu dimmen?




Links