LOG与DOG边缘检测

转载:
https://blog.csdn.net/geduo_feng/article/details/81605500

一、LOG(laplace of gaussian)

laplacian 算子的定义
在这里插入图片描述
差分形式为
在这里插入图片描述
laplacian 可以检测出边缘,为了排查噪声干扰,所有先对图像用高斯滤波器做低通滤波。
高斯滤波和laplacian算子连起来就是LOG.

二、DOG(difference of gaussian)

在这里插入图片描述
DOG就是对图像进行两次不同的高斯变换,然后对应的像素相减。
DOG算子和LOG算子的效果类似,但是计算复杂量低很多。

三、代码示例

1、函数具体实现

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void gausssianFilter(Mat srcimg, Mat dstimg, double sigma1, double sigma2=-1)
{
    if (sigma1 <= 0 )
    {
        return;
    }
    if (sigma2 < 0)
    {
        sigma2 = sigma1;
    }
    int radius1 = (int)(3 * sigma1 + 0.5f);
    int radius2 = (int)(3 * sigma2 + 0.5f);
    Mat kernel(2 * radius1 + 1, 2 * radius2 + 1, CV_32F);
    float fsum = 0;
    for (int y = -radius1; y <= radius1; y++)//计算高斯卷积模板
    {
        for (int x = -radius2; x <= radius2; x++)
        {
            kernel.at<float>(y+radius1, x+radius2) = (float)exp(-x*x / (sigma2*sigma2) - y*y / (sigma1*sigma1));
            fsum += kernel.at<float>(y+radius2, x+radius1);
        }
    }

    for (int y = -radius1; y <= radius1; y++)
    {
        for (int x = -radius2; x <= radius2; x++)
        {
            kernel.at<float>(y+radius1, x+radius2) = kernel.at<float>(y+radius1, x+radius2) / fsum;
        }
    }

    //用高斯模板与原图像做卷积
    uchar *data =  srcimg.data;
    uchar *newData = dstimg.data;
    float *pixel = new float[srcimg.channels()];
    for (int row = radius1; row < srcimg.rows - radius1; row++)
    {
        int row_step = srcimg.cols * srcimg.channels();
        for (int col = radius2; col < srcimg.cols - radius2; col++)
        {
            // 每个通道值置零
            for (int channel = 0; channel < srcimg.channels();channel++)
            {
                pixel[channel] = 0;
            }
            for (int i = -radius1; i <= radius1; i++)
            {
                for (int j = -radius2; j <= radius2; j++)
                {
                    //计算每个通道的值
                    int index = (row + i)*row_step + (col + j)*srcimg.channels();
                    for (int channel = 0; channel < srcimg.channels(); channel++)
                    {
                        pixel[channel] += data[index + channel] * kernel.at<float>(i + radius1, j + radius2);
                    }

                }
            }
            int index = row*row_step + col*srcimg.channels();
            for (int channel = 0; channel < dstimg.channels(); channel++)
            {
                newData[index + channel] = saturate_cast<uchar>(pixel[channel]);
            }

        }
    }
    delete[] pixel;
    return;
}

void laplace(Mat srcimg, Mat dstimg)
{
    Mat grayimg;
    cvtColor(srcimg, grayimg, CV_BGR2GRAY);
    Mat kernel = (Mat_<char>(3, 3) << 0,-1,0,-1,4,-1,0,-1,0);
    for (int row = 1; row < grayimg.rows - 1; row++)
    {
        for (int col = 1; col < grayimg.cols - 1; col++)
        {
            int temp = 0;
            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j <= 1; j++)
                {
                    temp += grayimg.at<uchar>(row + i, col + j) * kernel.at<char>(i + 1, j + 1);
                }
            }

            if (temp > 255)
            {
                dstimg.at<uchar>(row, col) = 255;
            }
            else if (temp < -255)
            {
                dstimg.at<uchar>(row, col) = -255;
            }
            else{
                dstimg.at<uchar>(row, col) = abs(temp);
            }
        }
    }
    return;
}

void differenceOFgaussian(Mat srcimg, Mat dstimg)
{

    Mat grayimg = Mat::zeros(srcimg.size(), CV_8U);
    Mat img1 = Mat::zeros(srcimg.size(), CV_8U);
    Mat img2 = Mat::zeros(srcimg.size(), CV_8U);

    cvtColor(srcimg, grayimg, CV_BGR2GRAY);

    GaussianBlur(grayimg, img1, Size(5, 5), 0.3);
    GaussianBlur(grayimg, img2, Size(5, 5), 0.8);
//  gausssianFilter(grayimg, img1, 0.3);
//  gausssianFilter(grayimg, img2, 0.8);

    Mat result1 = img1 - img2;
    Mat result2 = img2 - img1;

    dstimg = result1 + result2;
    normalize(dstimg, dstimg, 255, 0, CV_MINMAX);//增加对比对
    return;
}

2、main函数

int main()
{
    Mat srcimg = imread("lena_color.jpg");
    Mat gaussianImg = Mat::zeros(srcimg.rows, srcimg.cols, srcimg.type());
    gausssianFilter(srcimg, gaussianImg, 0.6, 0.6);

    Mat laplaceImg = Mat::zeros(srcimg.size(), CV_8U);
    laplace(gaussianImg, laplaceImg);

    Mat DOG_img(srcimg.size(), CV_8U);
    differenceOFgaussian(srcimg, DOG_img);


    imshow("source image", srcimg);
    imshow("gaussian image", gaussianImg);
    imshow("laplace image", laplaceImg);
    imshow("DOG image", DOG_img);
    waitKey(0);
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canny边缘检测算法是一种经典的边缘检测算法,但是它本身也存在一些缺陷,需要进行改进。改进的Canny边缘检测算法可以从以下几个方面入手: 1. 改进高斯模糊:传统的Canny算法中使用高斯模糊来去除噪声,但是同时也会平滑边缘,使得边缘信息减弱,有可能漏掉一些需要的边缘。因此,可以考虑使用非线性滤波器,如双边滤波器,来代替高斯模糊,以保留更多的边缘信息。 2. 改进梯度计算:传统的Canny算法中使用的是Sobel算子来计算梯度,但是这种方法对噪声很敏感,容易检测到伪边缘或漏掉真实边缘。因此,可以考虑使用更加鲁棒的梯度算子,如Laplacian of Gaussian(LoG)算子或者Difference of Gaussian(DoG)算子。 3. 改进非极大值抑制:传统的Canny算法中使用非极大值抑制来提取边缘,但是这种方法容易漏掉一些边缘。因此,可以考虑使用更加鲁棒的方法,如基于形态学的边缘提取方法。 4. 改进双阈值处理:传统的Canny算法中使用双阈值处理来检测边缘,但是这种方法容易漏掉一些弱边缘或者将噪声误判为边缘。因此,可以考虑使用更加鲁棒的方法,如基于连通性的边缘提取方法。 综上所述,改进的Canny边缘检测算法可以通过改进高斯模糊、梯度计算、非极大值抑制和双阈值处理等方面来提高边缘检测的准确性和鲁棒性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值