A tarefa de determinar a presença de uma palma em um scanner de veias

De alguma forma, caí nas mãos de uma tarefa de teste. O interesse acadêmico prevaleceu e eu decidi fazer parte dessa tarefa. Minha solução não afirma ser ótima e correta. Eu só estava curioso para resolvê-lo.


Dados de origem


A essência da tarefa é escrever um programa que determine se a palma da mão está conectada ao scanner pela imagem das imagens do scanner de veias palmeiras.


Dados iniciais - várias imagens com um resultado conhecido.



Resultado


O programa com uma interface gráfica com a capacidade de selecionar imagens da lista. Após a seleção, a imagem é analisada e, após análise, o resultado é exibido na forma de inscrição Bom ou Ruim .




Algoritmo


O algoritmo de análise de imagem é bastante simples. Para começar, criei a classe ImageAnalyser com a seguinte interface


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

Dentro desta aula, decidi dividir condicionalmente a imagem em 4 partes para cada fonte de luz. E para cada imagem, calcule o brilho médio em relação aos eixos X e Y. Isso está claramente demonstrado na imagem abaixo.



Como resultado, obtemos oito gráficos com um nível de brilho médio.



Em seguida, você precisa analisar esses gráficos. Decidi usar a função de correlação comparando os gráficos resultantes com algum gráfico "perfeito". O gráfico ideal, neste caso, é apenas um retângulo, obtido da seguinte maneira:


 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 os gráficos e, consequentemente, obter o valor de correlação, usei a função gsl_stats_correlation , cuja implementação eu honestamente roubei da GNU Scientific Library .


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

Em seguida, você só precisa analisar os valores de correlação. Decidi que, se pelo menos um valor de correlação é menor que 0,5, a palma da mão não está conectada ao sensor ou 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; } 

Também é visto a partir do código que uma análise do nível de brilho é realizada - se o valor for menor que 30, também acreditamos que a palma da mão não está anexada.


Pilha de tecnologias usadas


  • C / c ++
  • Qt creator
  • QtCharts
  • Biblioteca Científica GNU

Código fonte


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

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


All Articles