La tarea de determinar la presencia de una palma en un escáner de venas

De alguna manera caí en manos de una tarea de prueba. El interés académico prevaleció y decidí sentarme en esta tarea. Mi solución no pretende ser óptima y correcta. Tenía curiosidad por resolverlo.


Datos de origen


La esencia de la tarea es escribir un programa que determine si la palma está unida al escáner por la imagen de imágenes del escáner de venas de la palma.


Datos iniciales: varias imágenes con un resultado conocido.



Resultado


El programa con una interfaz gráfica con la capacidad de seleccionar imágenes de la lista. Después de la selección, la imagen se analiza y después del análisis, el resultado se muestra en forma de la inscripción Bueno o Malo .




Algoritmo


El algoritmo de análisis de imágenes es bastante simple. Para comenzar, creé la clase ImageAnalyser con la siguiente interfaz


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

Dentro de esta clase, decidí dividir condicionalmente la imagen en 4 partes para cada fuente de luz. Y para cada imagen, calcule el brillo promedio en relación con los ejes X e Y. Esto se demuestra claramente en la imagen a continuación.



Como resultado, obtenemos ocho gráficos con un nivel de brillo promedio.



A continuación, debe analizar estos gráficos. Decidí usar la función de correlación comparando los gráficos resultantes con algún gráfico "perfecto". El gráfico ideal en este caso es solo un rectángulo, que obtengo de la siguiente manera:


 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; } 

Para comparar los gráficos y, en consecuencia, obtener el valor de correlación, utilicé la función gsl_stats_correlation , cuya implementación honestamente robé de la Biblioteca Científica GNU .


 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; } 

A continuación, solo necesita analizar los valores de correlación. Decidí que si al menos un valor de correlación es inferior a 0,5, entonces la palma no está conectada al sensor o está mal conectada.


 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; } 

También se ve en el código que se realiza el análisis del nivel de brillo: si el valor es inferior a 30, entonces también creemos que la palma no está unida.


Pila de tecnologías utilizadas


  • C / c ++
  • Creador de Qt
  • Gráficos Qt
  • Biblioteca científica GNU

Código fuente


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

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


All Articles