边缘检测之krisch算子

边缘检测的方法有主要有两种:

一种是基于模板匹配的,简单来说即用多个方向的检测模板与图像进行卷积,然后取邻域像素点的最大值。这种方法简单方便,容易理解,容易得到平滑的边缘,但是由于采用非常有限方向的模板(一般是8个方向,但是由于对称性可以减少为4个),因此不能检测出所有的边缘方向。

一种是基于求图像梯度的方法,一阶二阶的梯度算子,如sobel、prewitt、Robert等一阶算子和拉普拉斯算子。检测的灵敏度高,精度定位准确,但同时容易受到噪声点的影响。

Kirsch算子属于模板匹配算子,采用八个模板来处理图像的检测图像的边缘,运算量比较大。

8个3x3模板如下:

通过矩阵变换发现经过kirsch算子得到的像素值直接的关系,事实上需要直接由邻域像素点计算得到的只有p0,,因此可以大大减少计算量。

void MainWindow::on_krisch_edge_clicked()
{
    Mat gradimg,gray2Img,f_1,f_2,f_3,f_4,f_5,f_6,f_7,f_8;
    QImage Qtemp,Qtemp2;
    gray2Img.create(grayImg.rows, grayImg.cols, CV_8UC1);
    gradimg.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_1.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_2.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_3.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_4.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_5.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_6.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_7.create(grayImg.rows, grayImg.cols, CV_8UC1);
    f_8.create(grayImg.rows, grayImg.cols, CV_8UC1);
    for (int i = 1; i < srcImg.rows - 1; i++)
    {
        for (int j = 1; j < srcImg.cols - 1; j++)
        {
            f_1.at<uchar>(i, j) = saturate_cast<uchar>(fabs(-5*grayImg.at<uchar>(i - 1, j - 1) -5* grayImg.at<uchar>(i - 1, j) -5* grayImg.at<uchar>(i - 1, j + 1)
                                                           +3*grayImg.at<uchar>(i, j - 1) +3*grayImg.at<uchar>(i, j + 1)
                                                           + 3*grayImg.at<uchar>(i + 1, j - 1) + 3*grayImg.at<uchar>(i + 1, j) + 3*grayImg.at<uchar>(i + 1, j + 1)));
            f_2.at<uchar>(i, j) = saturate_cast<uchar>(fabs(3*grayImg.at<uchar>(i - 1, j - 1) -5* grayImg.at<uchar>(i - 1, j) -5* grayImg.at<uchar>(i - 1, j + 1)
                                                           +3*grayImg.at<uchar>(i, j - 1) -5*grayImg.at<uchar>(i, j + 1)
                                                           + 3*grayImg.at<uchar>(i + 1, j - 1) + 3*grayImg.at<uchar>(i + 1, j) + 3*grayImg.at<uchar>(i + 1, j + 1)));
            f_3.at<uchar>(i, j) = saturate_cast<uchar>(fabs(3*grayImg.at<uchar>(i - 1, j - 1) +3* grayImg.at<uchar>(i - 1, j) -5* grayImg.at<uchar>(i - 1, j + 1)
                                                           +3*grayImg.at<uchar>(i, j - 1) -5*grayImg.at<uchar>(i, j + 1)
                                                           + 3*grayImg.at<uchar>(i + 1, j - 1) + 3*grayImg.at<uchar>(i + 1, j) -5*grayImg.at<uchar>(i + 1, j + 1)));
            f_4.at<uchar>(i, j) = saturate_cast<uchar>(fabs(3*grayImg.at<uchar>(i - 1, j - 1) +3* grayImg.at<uchar>(i - 1, j) +3* grayImg.at<uchar>(i - 1, j + 1)
                                                           +3*grayImg.at<uchar>(i, j - 1) -5*grayImg.at<uchar>(i, j + 1)
                                                           + 3*grayImg.at<uchar>(i + 1, j - 1) -5*grayImg.at<uchar>(i + 1, j) -5*grayImg.at<uchar>(i + 1, j + 1)));
            f_5.at<uchar>(i, j) = saturate_cast<uchar>(fabs(3*grayImg.at<uchar>(i - 1, j - 1) +3* grayImg.at<uchar>(i - 1, j) +3* grayImg.at<uchar>(i - 1, j + 1)
                                                           +3*grayImg.at<uchar>(i, j - 1) +3*grayImg.at<uchar>(i, j + 1)
                                                           -5*grayImg.at<uchar>(i + 1, j - 1) -5*grayImg.at<uchar>(i + 1, j) -5*grayImg.at<uchar>(i + 1, j + 1)));
            f_6.at<uchar>(i, j) = saturate_cast<uchar>(fabs(3*grayImg.at<uchar>(i - 1, j - 1) +3* grayImg.at<uchar>(i - 1, j) +3* grayImg.at<uchar>(i - 1, j + 1)
                                                           -5*grayImg.at<uchar>(i, j - 1) +3*grayImg.at<uchar>(i, j + 1)
                                                           -5*grayImg.at<uchar>(i + 1, j - 1) -5*grayImg.at<uchar>(i + 1, j) +3*grayImg.at<uchar>(i + 1, j + 1)));
            f_7.at<uchar>(i, j) = saturate_cast<uchar>(fabs(-5*grayImg.at<uchar>(i - 1, j - 1) +3* grayImg.at<uchar>(i - 1, j) +3* grayImg.at<uchar>(i - 1, j + 1)
                                                           -5*grayImg.at<uchar>(i, j - 1) +3*grayImg.at<uchar>(i, j + 1)
                                                           -5*grayImg.at<uchar>(i + 1, j - 1) +3*grayImg.at<uchar>(i + 1, j) +3*grayImg.at<uchar>(i + 1, j + 1)));
            f_8.at<uchar>(i, j) = saturate_cast<uchar>(fabs(-5*grayImg.at<uchar>(i - 1, j - 1) -5* grayImg.at<uchar>(i - 1, j) +3* grayImg.at<uchar>(i - 1, j + 1)
                                                           -5*grayImg.at<uchar>(i, j - 1) +3*grayImg.at<uchar>(i, j + 1)
                                                           +3*grayImg.at<uchar>(i + 1, j - 1) +3*grayImg.at<uchar>(i + 1, j) +3*grayImg.at<uchar>(i + 1, j + 1)));
            QVector<int> goal = {f_1.at<uchar>(i, j),f_2.at<uchar>(i, j),f_3.at<uchar>(i, j),f_4.at<uchar>(i, j),f_5.at<uchar>(i, j),f_6.at<uchar>(i, j),f_7.at<uchar>(i, j),f_8.at<uchar>(i, j)};
            int max_8 = 0;
            for(int i = 0 ; i<8;i++){
                if(goal[i] > max_8){
                    max_8 = goal[i];
                }
            }

            gradimg.at<uchar>(i, j) = max_8;
            gray2Img.at<uchar>(i, j) = saturate_cast<uchar>(grayImg.at<uchar>(i, j) - gradimg.at<uchar>(i, j));
        }
    }
    Qtemp = QImage((const uchar*)(gray2Img.data), gray2Img.cols, gray2Img.rows, gray2Img.cols*gray2Img.channels(), QImage::Format_Indexed8);
    ui->label_3->setPixmap(QPixmap::fromImage(Qtemp));
    Qtemp = Qtemp.scaled(250, 250, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    ui->label_3->setScaledContents(true);
    ui->label_3->resize(Qtemp.size());
    ui->label_3->show();

    Qtemp2 = QImage((const uchar*)(gradimg.data), gradimg.cols, gradimg.rows, gradimg.cols*gradimg.channels(), QImage::Format_Indexed8);
    ui->label_2->setPixmap(QPixmap::fromImage(Qtemp2));
    Qtemp2 = Qtemp2.scaled(250, 250, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    ui->label_2->setScaledContents(true);
    ui->label_2->resize(Qtemp2.size());
    ui->label_2->show();
}

猜你喜欢

转载自blog.csdn.net/cyy1104/article/details/129728921