Die Aufgabe, das Vorhandensein einer Handfläche auf einem Venenscanner festzustellen

Irgendwie bin ich in die Hände einer Testaufgabe gefallen. Das akademische Interesse war groß und ich beschloss, mich dieser Aufgabe zu widmen. Meine Lösung erhebt keinen Anspruch auf Optimalität und Richtigkeit. Ich war nur neugierig, es zu lösen.


Ausgangsdaten


Der Kern der Aufgabe besteht darin, ein Programm zu schreiben, das bestimmt, ob die Handfläche durch das Bild von Bildern vom Handflächenvenenscanner am Scanner befestigt ist.


Anfangsdaten - mehrere Bilder mit bekanntem Ergebnis.



Ergebnis


Das Programm mit einer grafischen Oberfläche mit der Möglichkeit, Bilder aus der Liste auszuwählen. Nach der Auswahl wird das Bild analysiert und nach der Analyse wird das Ergebnis in Form der Aufschrift Gut oder Schlecht angezeigt.




Algorithmus


Der Bildanalysealgorithmus ist recht einfach. Zu Beginn habe ich die ImageAnalyser- Klasse mit der folgenden Schnittstelle erstellt


class ImageAnalyser { public: ImageAnalyser(); explicit ImageAnalyser(const QImage&); bool analyze(const QImage&); bool analyze(); std::vector<std::vector<int>> data(); virtual ~ImageAnalyser(); }; 

Innerhalb dieser Klasse habe ich beschlossen, das Bild für jede Lichtquelle bedingt in 4 Teile zu unterteilen. Berechnen Sie für jedes Bild die durchschnittliche Helligkeit relativ zur X- und Y- Achse. Dies wird im folgenden Bild deutlich.



Als Ergebnis erhalten wir acht Diagramme mit einer durchschnittlichen Helligkeit.



Als nächstes müssen Sie diese Diagramme analysieren. Ich entschied mich für die Korrelationsfunktion, indem ich die resultierenden Diagramme mit einem „perfekten“ Diagramm verglich. Das ideale Diagramm in diesem Fall ist nur ein Rechteck, das ich folgendermaßen erhalte:


 std::vector<int> ImageAnalyser::prepare_ideal_array(const std::vector<int>& array) { unsigned long min = static_cast<unsigned long>(array.size() * 0); unsigned long max = static_cast<unsigned long>(array.size() * 0.45); int ideal_value = 100; std::vector<int> ideal; ideal.resize(array.size()); for(unsigned long i = min; i < max; ++i) { ideal[i] = ideal_value; } return ideal; } 

Um die Graphen zu vergleichen und dementsprechend den Korrelationswert zu erhalten, habe ich die Funktion gsl_stats_correlation verwendet, deren Implementierung ich ehrlich aus der GNU Scientific Library gestohlen habe.


 double ImageAnalyser::gsl_stats_correlation(const std::vector<int>& data) { std::vector<int> ideal = prepare_ideal_array(data); const int stride1 = 1; const int stride2 = 1; double sum_xsq = 0.0; double sum_ysq = 0.0; double sum_cross = 0.0; double mean_x = data[0]; double mean_y = ideal[0]; for (unsigned int i = 1; i < data.size(); ++i) { double ratio = i / (i + 1.0); double delta_x = data[i * stride1] - mean_x; double delta_y = ideal[i * stride2] - mean_y; sum_xsq += delta_x * delta_x * ratio; sum_ysq += delta_y * delta_y * ratio; sum_cross += delta_x * delta_y * ratio; mean_x += delta_x / (i + 1.0); mean_y += delta_y / (i + 1.0); } double r = sum_cross / (sqrt(sum_xsq) * sqrt(sum_ysq)); return r; } 

Als nächstes müssen Sie nur die Korrelationswerte analysieren. Ich entschied, dass wenn mindestens ein Korrelationswert kleiner als 0,5 ist, die Handfläche nicht am Sensor oder schlecht befestigt ist.


 bool ImageAnalyser::is_good(const vector<double>& correlation, const vector<int>& maximums) { bool result = true; double min_corr = *std::min_element(correlation.begin(), correlation.end()); if (min_corr < 0.5) { result = false; } double min_val = *std::min_element(maximums.begin(), maximums.end()); if (min_val < 30) { result = false; } return result; } 

Aus dem Code geht auch hervor, dass die Analyse des Helligkeitsniveaus durchgeführt wird. Wenn der Wert weniger als 30 beträgt, glauben wir auch, dass die Handfläche nicht angebracht ist.


Stapel der verwendeten Technologien


  • C / c ++
  • Qt Schöpfer
  • QtCharts
  • GNU Scientific Library

Quellcode


https://github.com/techlinked/PalmDetector.git

Source: https://habr.com/ru/post/de472280/


All Articles