2016-08-06 84 views
0

Ich arbeite an einem Projekt mit einem Papierstreifen, der basierend auf bestimmten Faktoren die Farbe von Weiß nach Dunkelbraun ändert, und ich muss eine App schreiben, die diese Farbe klassifizieren kann. Ich habe den Feature-Recognition-Teil davon schon in OpenCV geschrieben, allerdings habe ich Probleme, unterschiedliche Lichtverhältnisse zu berücksichtigen. Ich habe ein Rechteck eingefügt, das 6 verschiedene Farben enthält: Schwarz, Weiß und 4 verschiedene Grautöne auf dem Streifen, um mir dabei zu helfen. Aber ich kämpfe immer noch mit der richtigen Farbe des Indikators. Kann mir jemand in die richtige Richtung zeigen? Vielen Dank.OpenCV Farbkorrektur

+1

Hallo, Willkommen zu Stack Overflow, bitte fügen Sie Ihren Code und was Sie bisher versucht haben. – FishStix

+0

Nun, ich habe noch nichts gemacht, da ich keine Ahnung habe, wo ich anfangen soll. Im Moment habe ich eine Methode, die ein Foto des Streifens macht, einige Bildanalysen durchführt und ein Objekt mit 6 Farben aus dem Foto im bgr-Format (1 Byte pro Kanal) zurückgibt. Die Farben sind: Musterfarbe, Schwarz, Weiß, Hellgrau, Grau und Dunkelgrau. Für alle außer der Musterfarbe kenne ich die wahren bgr-Werte. Ich muss in der Lage sein, den wahren bgr-Wert der Musterfarbe zu berechnen. –

Antwort

0

Das ist eine interessante Aufgabe. Sie können versuchen, mit einem einfachen Ansatz zu beginnen, z. B. mit linearer Algebra und Minimierung der kleinsten Quadrate.

Wir können echte und registrierte Farben als 3D-Vektoren betrachten (ich nehme an, Sie arbeiten mit Farbbildern in RGB oder einem anderen Farbraum) und wirken als Matrixoperator (3x3).

Jedes Paar von Farben schafft eine Beschränkung einer folgenden Form:

, wo ist Betreiber die Sie suchen, reale Farbe und wird Farbe beobachtet.

Sie können diese Randbedingungen in eine andere umzuschreiben:

wo sind Bestandteile von (Notation für beobachtete Farbe ist analog).

Dieses Formular ermöglicht uns, mehrere Beobachtungen einfach durch Stapeln von Matrizen zu kombinieren. Sie benötigen mindestens drei Farbübereinstimmungen, um den Operator genau zu schätzen, und mehr, wenn Sie robust gegenüber Rauschen und anderen unerwünschten Effekten sein möchten.

Nachdem Sie die Matrizen gemäß Ihren Beobachtungen erstellt haben, können Sie eine Reihe von linearen Gleichungen in der Methode der kleinsten Quadrate lösen, um den Operator (Abbildung von echten Farben zu beobachteten) zu erhalten.

Sobald Sie den Operator geschätzt haben, können Sie einfach jede Farbe multiplizieren, die Sie beobachten, mit , um echte Farbe zu erhalten.

Dies ist ein einfach zu verstehen und effektiver Ansatz, aber es hat einige Nachteile.

Erstens - es nimmt an, dass es eine lineare Beziehung zwischen realen und beobachteten Farben gibt, die eine falsche Annahme sein kann (ich habe keine Experimente gemacht, um es zu überprüfen).

Auch wenn die Beleuchtung als ein linearer Operator fungiert - da der dynamische Bereich der Kamera festgelegt ist - können Probleme auftreten, wenn eine bestimmte Farbe aufgrund der hellen Beleuchtung außer Reichweite ist, da das Clipping dies verursacht nicht linear.

Auch sollten Sie sorgfältig die Farben für Ihren Marker auswählen (ich würde Farben mit verschiedenen Farbtönen wählen, um die Basis des Farbraums zu erfassen, außerdem sollten sie in der Mitte des Dynamikbereichs liegen, um die Wahrscheinlichkeit zu verringern, außerhalb des Bereichs zu gehen). Vergiss nicht, dass wenn die Komponenten deiner Farben zu stark korreliert sind (wenn du zum Beispiel Grautöne verwendest) - die Beobachtungsmatrix kann ihren Rang verlieren und singulär werden, was das Lösen für Elemente unmöglich macht/bedeutungslos macht.

Ich habe ein einfaches Python-Skript gemacht, um zu überprüfen, ob der Operator, den ich beschrieben habe, unter einfachen Bedingungen geschätzt werden kann (homogene 2x Verdunkelung). Es kann auch nützlich sein, um mit verschiedenen Farben für Marker zu experimentieren.

import numpy as np 

# choose colors for marker 
Cr = np.array([[10, 200, 30], 
       [40, 50, 160], 
       [10, 80, 90], 
       [150, 60, 10]], dtype = np.float32) 

# simulate effect from light 
Co = (Cr/2) 

# form a set of constraints for a color pair 
def genConstr(pt): 
    constr = np.zeros((3, 9), dtype = np.float32) 
    constr[0, 0:3] = pt 
    constr[1, 3:6] = pt 
    constr[2, 6:9] = pt 
    return constr 

# form constraints for all colors on marker 
cs = np.zeros((0, 9), dtype = np.float32) 

for i in xrange(Cr.shape[0]): 
    cs = np.vstack((cs, genConstr(Cr[i, :]))) 

# estimate operator 
Ai = np.linalg.lstsq(cs, Co.flatten())[0].reshape((3, 3)) 
A = np.linalg.inv(Ai) 

#display results 
print 'operator:' 
print A 

print '' 

print 'reconstructed colors:' 
for i in xrange(Co.shape[0]): 
    print A.dot(Co[i]) 

Es erzeugt folgendes Ergebnis:

operator: 
[[ 2.00000000e+00 -3.12988124e-16 -3.83156015e-16] 
[ -1.77322970e-32 2.00000000e+00 -3.60822483e-16] 
[ 9.82882077e-17 -4.07302066e-16 2.00000000e+00]] 

reconstructed colors: 
[ 10. 200. 30.] 
[ 40. 50. 160.] 
[ 10. 80. 90.] 
[ 150. 60. 10.] 

Wie Sie sehen können, geschätzter Operator ganz nahe an theoretischen (2s auf Hauptdiagonale) und echte Farben korrekt rekonstruiert.

+0

Vielen Dank für eine ausführliche Beschreibung. Nachdem ich diese Methode an einigen meiner Beispielbilder versucht habe, kann ich leider sagen, dass es nicht funktioniert. Aus meinen Beobachtungen scheint es, dass die Beziehung zwischen realer und beobachteter Farbe nicht linear ist - hellere Farbbeobachtungen scheinen mehr von der wahren Farbe abzuweichen als die dunkleren. –

+0

Sie können einige Ihrer Testdaten dann teilen, um relevantere Antworten zu erhalten :) – alexisrozhkov

+0

Hier sind zwei Beispielbilder mit meinem Telefon http://imgur.com/a/68Hf2. Die Farbe des Kreises innerhalb der Blackbox ist, was ich zu klassifizieren versuche. Die wahren Farben sind: Die Box um den Kreis ist schwarz, also RGB (0,0,0), die hellste Farbe auf dem großen Rechteck unter der Box ist weiß (255, 255, 255), dann (200, 201, 205), (149, 152, 157), (100, 105, 109) und das dunkelste Rechteck ist (52, 60, 63). Es muss auf einem Schwarz-Weiß-Drucker gedruckt werden, so dass ich diese Rechtecke nicht anders als Graustufen machen kann. –