Notas de desenvolvimento do OpenCV (44): O homem gordo vermelho leva você em 8 minutos para entender a transformação do círculo de Hough em profundidade (com imagens e texto + fácil de entender + código fonte do programa)

Se o artigo for um artigo original, ele não poderá ser reproduzido sem permissão.O
endereço do blog do blogueiro original: https://blog.csdn.net/qq21497936 A
navegação do blog do blogueiro original: https://blog.csdn.net/qq21497936/article/details / 102478062
O endereço do blog deste artigo: https://blog.csdn.net/qq21497936/article/details/105575546
leitores, o conhecimento é infinito e a mão-de-obra é fraca, altere a demanda ou encontre um profissional ou estude sozinho

Diretório

Prefácio

Demo

Transformação Hough

Visão geral

Transformação do círculo de Hough

Visão geral

Princípio

1. O espaço bidimensional de uma imagem de círculo pode ser representado por um sistema de coordenadas cartesianas

2. Princípio de formação da curva tridimensional

3. A base para julgar o círculo

Princípio do gradiente de Hough

Vantagens do método gradiente de Hough

Desvantagens do método gradiente de Hough

Protótipo da função de transformação do círculo de Hough

Código fonte da demonstração

Modelo de engenharia: número da versão correspondente v1.39.0


Coluna de desenvolvimento OpenCV (clique no portal)

 

    Notas de desenvolvimento do OpenCV (44): O homem gordo vermelho leva você em 8 minutos para entender a transformação do círculo de Hough em profundidade (com imagens e texto + fácil de entender + código fonte do programa)

 

Prefácio

      Homem gordo vermelho também vem! ! !

Após denoising e detecção de borda, é a extração de recursos.Um dos métodos básicos para identificar gráficos é a transformação de Hough.A transformação de Hough é uma tecnologia de extração de recursos no processamento de imagens.Este capítulo explica principalmente a transformação do círculo de Hough.

 

Demo

      As duas primeiras demonstrações não são muito precisas, porque o autor ampliou a imagem original, o que causou deformações no círculo original e a última foi desenhada de acordo com a resolução em escala.

 

Transformação Hough

Visão geral

      Hough Transform (Hough Transform) é uma tecnologia de extração de recursos no processamento de imagens.O processo de modificação calcula o valor máximo local do resultado acumulado em um espaço de parâmetro para obter um conjunto em conformidade com a forma específica como resultado do Hough Transform.

      A transformação Hough clássica é usada para detectar linhas retas na imagem.Mais tarde, a transformação Hough foi estendida ao reconhecimento de objetos de formas arbitrárias, principalmente círculos e elipses.

      A transformação Hough usa a transformação entre dois espaços de coordenadas para mapear uma curva ou uma linha reta com a mesma forma em um espaço para um ponto em outro controle de coordenadas para formar um pico, transformando o problema de detectar qualquer forma em um problema estatístico de pico .

      A transformação Hough no OpenCV é dividida em dois tipos e a transformação de linha é dividida em três tipos, conforme mostrado abaixo:

Transformação do círculo de Hough

Visão geral

      Transformação do círculo de Hough, você pode saber pelo nome que ele é realmente um círculo. Obviamente, é um método para encontrar um círculo. Aqui prestamos especial atenção. Antes de usar a transformação do círculo de Hough, é necessário pré-processar a imagem: redução de ruído, processamento de detecção de borda , A transformação de círculo de Hough procura apenas círculos e pode reconhecer apenas imagens binárias de borda; portanto, a entrada pode ser apenas imagens binarizadas (canal único de 8 bits).

      A transformação do círculo de Hough encontrará um grande número de círculos, mas alguns círculos são realmente inúteis e, como a transformação da linha de Hough, eles podem produzir dados "barulhentos".

Princípio

1. O espaço bidimensional de uma imagem de círculo pode ser representado por um sistema de coordenadas cartesianas

  • No sistema de coordenadas cartesianas (o método adotado pela transformação do círculo de Hough): pode haver um centro do círculo (a, b), e o raio r representa;

O caminho do círculo no sistema de coordenadas cartesianas:

A fórmula é:

E

Portanto, em um sistema de coordenadas tridimensional composto por abr, um ponto pode definir exclusivamente um círculo.

2. Princípio de formação da curva tridimensional

Todos os círculos que passam em um determinado ponto no sistema de coordenadas cartesianas xy são mapeados para abr o sistema de coordenadas como uma curva tridimensional.

Todos os círculos que passam por todos os pixels diferentes de zero no sistema de coordenadas xy constituem muitas curvas tridimensionais no sistema de coordenadas abr.

3. A base para julgar o círculo

A equação do círculo de todos os pontos no mesmo círculo no sistema de coordenadas xy é a mesma, e eles são mapeados para o mesmo ponto no sistema de coordenadas abr, portanto, no sistema de coordenadas abr, deve haver um total de N0 curvas do círculo. Interseção. Ao julgar o número de interseções (cumulativas) de cada ponto em abr, um ponto maior que um determinado limite é considerado um círculo.

O problema acima é o algoritmo padrão de transformação do círculo de Hough. O problema é que sua superfície de acumulação é um espaço tridimensional, o que significa que requer mais custo computacional do que a transformação da linha de Hough.

A Opencv Hough Circle Transform otimiza a Hough Circle Transform padrão. Ele usa o "método gradiente Hough". Sua idéia de detecção é atravessar e acumular o centro do círculo correspondente a todos os pontos diferentes de zero e considerar o centro do círculo.

O centro do círculo deve estar no vetor de módulo de cada ponto do círculo, ou seja, na linha vertical perpendicular ao ponto e passando pela tangente do ponto, a interseção dos vetores de módulo nesses círculos é o centro do círculo.

O método do gradiente de Hough é encontrar esses pontos centrais e fazer um julgamento final de acordo com o limite de acordo com o número de interseções dos vetores de módulo no "ponto central".

Princípio do gradiente de Hough

  1. Primeiro, execute a detecção de borda na imagem, como o uso de detecção de borda inteligente;
  2. Para cada ponto diferente de zero na imagem da aresta, o gradiente local é considerado, ou seja, a função Sobel () é usada para calcular a derivada de Sobel nas direções x e y para obter o gradiente;
  3. Usando o gradiente obtido, todos os pontos na linha especificada de alguma taxa são acumulados no acumulador, onde a inclinação é a distância de um valor máximo especificado até o valor máximo especificado;
  4. Ao mesmo tempo, marque cada posição diferente de zero na imagem de borda;
  5. Selecione os centros candidatos a partir desses pontos no acumulador bidimensional, para que os centros sejam todos maiores que um determinado limite e maiores que todos os seus vizinhos. Os centros desses candidatos são organizados em ordem decrescente de valor acumulado, e o centro do lado que suporta o pixel aparece primeiro;
  6. Para cada centro, considere todos os pixels diferentes de zero;
  7. Nesse caso, os pixels são organizados de acordo com a distância do centro e, da menor distância até o maior raio, um raio suportado por um pixel diferente de zero é selecionado;
  8. Se um centro for totalmente suportado por pixels diferentes de zero da imagem da borda e houver uma distância suficiente do centro selecionado anteriormente, ele será retido;

Vantagens do método gradiente de Hough

      O algoritmo é eficiente e pode resolver o problema esparso e instável que gera muito ruído no acumulador tridimensional e torna os resultados instáveis;

Desvantagens do método gradiente de Hough

  • Usar os derivativos de Sobel para calcular pode causar mais ruído;
  • Na imagem de borda, todo o pixel diferente de zero é considerado o centro candidato, portanto, definir o valor baixo do acumulador fará com que o ponto suba, de modo que a quantidade de cálculo seja grande e o algoritmo consuma muito tempo;
  • Os centros são organizados em ordem crescente de seus acumuladores associados e, se o novo centro estiver muito próximo do ponto central aceito anteriormente, o ponto não será retido, o que equivale a um círculo concêntrico que retém apenas o maior círculo de raio;

Protótipo da função de transformação do círculo de Hough

void HoughCircles( InputArray image,
                OutputArray circles,
                int method,
                double dp,
                double minDist,
                double param1 = 100,
                double param2 = 100,
                int minRadius = 0,
                int maxRadius = 0);
  • Parâmetro 1: Imagem do tipo InputArray, imagem de origem de 8 bits, imagem binária de canal único. Você pode carregar qualquer imagem original e modificá-la para este formato pela função e preencha aqui;
  • Parâmetro dois: cirlces do tipo OutputArray, vetor do círculo de saída, cada vetor inclui três elementos de ponto flutuante - abcissa central do círculo, ordenada do centro do círculo e raio do círculo;
  • Parâmetro três: método do tipo int, que é um algoritmo usando a detecção de círculo de transformação de Hough;

Número de série

Enumeração

Valor

Descrição do produto

1

HOUGH_STANDARD

0 0

CV_HOUGH_STANDARD - Transformada Hough tradicional ou padrão (SHT). Cada segmento de linha é representado por dois números de ponto flutuante (ρ, θ), onde ρ é a distância entre a linha e a origem (0,0) e o ângulo entre o segmento de linha θ e o eixo x. Portanto, o tipo de matriz deve ser do tipo CV_32FC2;

2

HOUGH_PROBABILISTIC

1

CV_HOUGH_PROBABILISTIC- Transformação Probabilística de Hough ( PPHT ). Se a imagem contiver alguns segmentos lineares longos, a eficiência será maior. Retorna o segmento do segmento em vez do segmento inteiro. Cada segmento é representado por um ponto inicial e um ponto final; portanto, o tipo de matriz (ou sequência criada) é do tipo CV_32SC4 ;

3

HOUGH_MULTI_SCALE

2

Variante em várias escalas da transformação Hough tradicional . Segmento que codifica o CV_HOUGH_STANDARD consistente

4

HOUGH_GRADIENT

3

Basicamente 21HT

  • Parâmetro 4: Tipo duplo dp, dp: Encontre a resolução cumulativa do centro do arco.Este parâmetro permite criar um acumulador com uma resolução menor que a imagem de entrada. (Isso ocorre porque há motivos para acreditar que os círculos presentes na imagem diminuirão naturalmente para a mesma quantidade que a largura e a altura da imagem). Se dp estiver definido como 1, a resolução será a mesma; se definido como um valor maior (como 2), a resolução do acumulador será reduzida por esse efeito (metade nesse caso); o valor de dp não poderá ser maior que 1 Pequeno
  • Parâmetro cinco: minDist do tipo duplo , precisão, esse parâmetro é a distância mínima entre dois círculos diferentes que o algoritmo pode distinguir claramente;
  • Parâmetro seis: tipo duplo param1 , o padrão é 100 , usado para o limite superior do limite da borda de Canny , o limite inferior é definido como metade do limite superior ;
  • Sete parâmetros: Duplo tipo param2 , o padrão é 100 , no caso do gradiente de Hough, que é o centro fase de detecção do limiar de acumulador do círculo. Quanto menor, mais círculos que não existem podem ser detectados e mais círculos podem passar pela detecção, mais próximo do protótipo perfeito;
  • Parâmetro oito: minRadius do tipo int , o padrão é 0 , o raio mínimo do círculo de detecção;
  • Parâmetro 9: int tipo maxRadius , o padrão é 0 , o raio máximo do círculo de detecção, quando 0 , o máximo é o tamanho da matriz de pixels;

 

Código fonte da demonstração

void OpenCVManager::testHoughCircles()
{
    QString fileName1 =
            "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/17.jpg";
    cv::Mat srcMat = cv::imread(fileName1.toStdString());
    int width = 400;
    int height = 300;

    cv::resize(srcMat, srcMat, cv::Size(width, height));
    cv::Mat colorMat = srcMat.clone();

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3),
                                srcMat.type());

    cv::cvtColor(srcMat, srcMat, CV_BGR2GRAY);

    int threshold1 = 200;
    int threshold2 = 100;
    int apertureSize = 1;

    int dp = 10;            // 默认1像素
    int minDist = 10;       // 默认1°
    int minRadius = 0;
    int maxRadius = 0;

    while(true)
    {
        qDebug() << __FILE__ << __LINE__;
        windowMat = cv::Scalar(0, 0, 0);

        cv::Mat mat;
        cv::Mat dstMat;
        cv::Mat grayMat;

        // 转换为灰度图像
        // 原图先copy到左边
        cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
                                    cv::Range(0, srcMat.cols));
        cv::cvtColor(srcMat, grayMat, CV_GRAY2BGR);
        cv::addWeighted(leftMat, 0.0f, grayMat, 1.0f, 0.0f, leftMat);

        {
            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 0 + 20,
                         "threshold1");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           height * 0 + 50,
                           200,
                           &threshold1,
                           0,
                           255);
            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 0 + 100, "threshold2");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           srcMat.cols * 0 + 130,
                           200,
                           &threshold2,
                           0,
                           255);

            qDebug() << __FILE__ << __LINE__;
            cv::Canny(srcMat, dstMat, threshold1, threshold2, apertureSize * 2 + 1);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));

            cv::cvtColor(dstMat, grayMat, CV_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, grayMat, 1.0f, 0.0f, mat);

            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 1 + 20 - 80,
                         "dp = value / 10");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           height * 1 + 50 - 80,
                           200,
                           &dp,
                           1,
                           1000);
            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 1 + 100 - 80,
                         "minDist = value / 2");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           height * 1 + 130 - 80,
                           200,
                           &minDist,
                           1,
                           720);
            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 1 + 180 - 80,
                         "minRadius");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           height * 1 + 210 - 80,
                           200,
                           &minRadius,
                           0,
                           100);
            cvui::printf(windowMat,
                         width * 1 + 100,
                         height * 1 + 260 - 80,
                         "maxRadius");
            cvui::trackbar(windowMat,
                           width * 1 + 100,
                           height * 1 + 290 - 80,
                           200,
                           &maxRadius,
                           0,
                           1000);
            // 边缘检测后,进行霍夫圆检测
            std::vector<cv::Vec3f> circles;
            cv::HoughCircles(dstMat,
                             circles,
                             cv::HOUGH_GRADIENT,
                             dp / 10.0f,
                             minDist / 10.0f,
                             200,
                             100,
                             minRadius,
                             maxRadius);
            // 在图中绘制出每条线段
            dstMat = colorMat.clone();
            for(int index = 0; index < circles.size(); index++)
            {
                cv::Point center(cvRound(circles[index][0]),
                                 cvRound(circles[index][1]));
                int radius = cvRound(circles[index][2]);
                // 绘制圆心
                cv::circle(dstMat, center, 3, cv::Scalar(255, 255, 255));
                // 绘制圆
                cv::circle(dstMat, center, radius, cv::Scalar(0, 0, 255));
            }
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);


            // 在图中绘制出每条线段
            for(int index = 0; index < circles.size(); index++)
            {
                cv::Point center(cvRound(circles[index][0]),
                                 cvRound(circles[index][1]));
                int radius = cvRound(circles[index][2]);
                // 绘制圆心
                cv::circle(grayMat, center, 3, cv::Scalar(255, 255, 255));
                // 绘制圆
                cv::circle(grayMat, center, radius, cv::Scalar(0, 0, 255));
            }
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat, 0.0f, grayMat, 1.0f, 0.0f, mat);
        }
        // 更新
        cvui::update();
        // 显示
        cv::imshow(windowName, windowMat);
        // esc键退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}

 

Modelo de engenharia: número da versão correspondente v1.39.0

      Número da versão correspondente v1.39.0

 

O endereço do blog do blogueiro original: https://blog.csdn.net/qq21497936 A
navegação do blog do blogueiro original: https://blog.csdn.net/qq21497936/article/details/102478062
O endereço do blog deste artigo: https: // blog .csdn.net / qq21497936 / article / details / 105575546

Publicado 268 artigos originais · Gosto 466 · Visitas: 540.000+

Acho que você gosta

Origin blog.csdn.net/qq21497936/article/details/105575546
Recomendado
Clasificación