Une brève analyse des paramètres de seuil haut et bas de Canny dans opencv

void Canny( InputArray _src, OutputArray _dst,
                double low_thresh, double high_thresh,
                int aperture_size, bool L2gradient )

Je pense que de nombreux étudiants ne connaissent l'utilité d'augmenter ou d'abaisser le seuil haut et le seuil bas que lorsqu'ils utilisent la fonction Canny, comme résumé ci-dessous :

  1. Les pixels inférieurs au seuil de 1 ne seront pas considérés comme des bords ;
  2. Les pixels supérieurs au seuil 2 seront considérés comme des bords ;
  3. Si le pixel compris entre le seuil 1 et le seuil 2 est adjacent au pixel de bord obtenu à l'étape 2, il est considéré comme un bord, sinon il n'est pas considéré comme un bord.

Mais en fait, je ne comprends pas trop d'où viennent les seuils haut et bas, et je ne sais pas comment ajuster les paramètres pour changer l'effet de Canny. Je ne peux essayer les valeurs qu'une par une. Ensuite, je vous amènerai à analyser le code source de Canny étape par étape et à vous apprendre à utiliser les seuils hauts et bas.

    Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE); 

    Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE); 

Il y a deux morceaux de code dans le code source: les valeurs de gradient horizontal et vertical du point actuel sont calculées via l'opérateur sobel et stockées dans dx et dy.

a700e5cbe3874a428668c97bb4956af2.png

 

gif.latex?%5Ctiny%20Gx%20%3D%20%5Bf%28x+1%2Cy-1%29%20+%202f%28x+1%2Cy%29%20+%20f%28x+1%2Cy+ ;1%29%5D%20-%20%5Bf%28x-1%2Cy-1%29%20+%202f%28x-1%2Cy%29%20+%20f%28x-1%2Cy+1% 29%5D

gif.latex?%5Ctiny%20Gy%20%3D%20%5Bf%28x-1%2Cy-1%29+%202f%28x%2Cy-1%29%20+%20f%28x+1%2Cy-1 %29%5D%20-%20%5Bf%28x-1%2C%20y+1%29%20+%202f%28x%2Cy+1%29%20+%20f%28x+1%2Cy+1% 29%5D

for (int i = 0; i <= src.rows; i++) // i 表示第i行
    {
 
	// i == 0 时,_norm 指向 mag_buf[1]
	// i > 0 时, _norm 指向 mag_buf[2]
	// +1 表示跳过每行的第一个元素,因为是后扩展的边,不可能是边缘
	int* _norm = mag_buf[(i > 0) + 1] + 1; 
        
            short* _dx = dx.ptr<short>(i); // _dx指向dx矩阵的第i行
            short* _dy = dy.ptr<short>(i); // _dy指向dy矩阵的第i行
 
            if (!L2gradient) // 如果 L2gradient为false
            {
                for (int j = 0; j < src.cols*cn; j++) // 对第i行里的每一个值都进行计算
                    _norm[j] = std::abs(int(_dx[j])) + std::abs(int(_dy[j])); 
                    // 用||+||计算
            }
            else
            {
                for (int j = 0; j < src.cols*cn; j++)
		    //用平方计算,当 L2gradient为 true时高低阈值都被平方了,所以此处_norm[j]无需开平方
                    _norm[j] = int(_dx[j])*_dx[j] + int(_dy[j])*_dy[j]; //
            }
 
            _norm[-1] = _norm[src.cols] = 0; // 最后一列和第一列的梯度幅值设置为0
        
}

Le code source précédent utilise la valeur de gradient directionnel calculée par l'opérateur sobel pour calculer la valeur de gradient du point actuel.

Enfin, bien sûr, vous devez savoir utiliser les paramètres de seuil haut et bas lorsque vous utilisez la fonction astucieuse !

int m = _mag[j];//m为计算出来该点的梯度值
 
            if (m > low) // 如果大于低阈值
            {
                int xs = _x[j];    // dx中 第i-1行 第j列
                int ys = _y[j];    // dy中 第i-1行 第j列
                int x = std::abs(xs);
                int y = std::abs(ys) << CANNY_SHIFT;
            }
	      //比当前的梯度幅值低阈值还低,直接被确定为非边缘
            prev_flag = 0;
            _map[j] = uchar(1); // 1 表示不属于边缘

Puis à la position du code source, le seuil bas renseigné entre en jeu. En comparant la valeur de gradient calculée du point avec le seuil bas, s'il s'agit d'un bord. Le seuil haut est similaire. Si vous êtes intéressé, vous pouvez lire le code source vous-même.

Changez simplement le nom du chemin en fonction de votre propre C:\yx\opencv\sources\modules\imgproc\src\canny.cpp

 

Je suppose que tu aimes

Origine blog.csdn.net/qq_51710331/article/details/130400469
conseillé
Classement