LOG和DOG边缘检测

LOG(laplace of gaussian)

  • laplacian 算子的定义
    2f(x,y)=f2(x,y)2x+f2(x,y)2y ▽ 2 f ( x , y ) = ∂ f 2 ( x , y ) ∂ 2 x + ∂ f 2 ( x , y ) ∂ 2 y

差分形式为

2f(x,y)=(f(x+1,y)f(x,y))(f(x,y)f(x1,y))+(f(x,y+1)f(x,y))(f(x,y1)f(x,y1)) ▽ 2 f ( x , y ) = ( f ( x + 1 , y ) − f ( x , y ) ) − ( f ( x , y ) − f ( x − 1 , y ) ) + ( f ( x , y + 1 ) − f ( x , y ) ) − ( f ( x , y − 1 ) − f ( x , y − 1 ) )

laplacian 可以检测出边缘,为了排查噪声干扰,所有先对图像用高斯滤波器做低通滤波。高斯滤波和laplacian算子连起来就是LOG.
至于为什么laplacian可以检测出边界,参考一下博客
OpenCV函数 Laplacian 算子实现
laplace LOG DOG边缘检测

DOG(difference of gaussian)

DOG=G(x,y,σ1)G(x,y,σ2) D O G = G ( x , y , σ 1 ) − G ( x , y , σ 2 )

DOG就是对图像进行两次不同的高斯变换,然后对应的像素相减。DOG算子和LOG算子的效果类似,但是计算复杂量低很多。
为什么DOG可以达到LOG的效果,参考一下博客
laplace LOG DOG边缘检测
DoG和LoG算子

  • c++ 代码实现
#include 

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(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(row + i, col + j) * kernel.at<char>(i + 1, j + 1);
                }
            }

            if (temp > 255)
            {
                dstimg.at(row, col) = 255;
            }
            else if (temp < -255)
            {
                dstimg.at(row, col) = -255;
            }
            else{
                dstimg.at(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;
}

test 代码


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



LOG和DOG 边缘检测

扩展延伸参考
斑点检测(LoG,DoG)
计算机视觉之一:特征检测

你可能感兴趣的:(图像处理)