10

我试图对 Gonzalez 书中的一些标准图像进行锐化。以下是我尝试过的一些代码,但它并没有接近锐化图像的结果。

cvSmooth(grayImg, grayImg, CV_GAUSSIAN, 3, 0, 0, 0);

IplImage* laplaceImg = cvCreateImage(cvGetSize(oriImg), IPL_DEPTH_16S, 1);

IplImage* abs_laplaceImg = cvCreateImage(cvGetSize(oriImg), IPL_DEPTH_8U, 1);

cvLaplace(grayImg, laplaceImg, 3);

cvConvertScaleAbs(laplaceImg, abs_laplaceImg, 1, 0);

IplImage* dstImg = cvCreateImage(cvGetSize(oriImg), IPL_DEPTH_8U, 1);
cvAdd(abs_laplaceImg, grayImg, dstImg, NULL); 

锐化前锐化前

我的锐化结果我的锐化结果

期望的结果期望的结果

绝对拉普拉斯绝对拉普拉斯

4

4 回答 4

6

我认为问题在于您在进行二阶导数之前模糊了图像。

这是使用 C++ API 的工作代码(我使用的是 Opencv 2.4.3)。我也尝试了 MATLAB,结果是一样的。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>

using namespace cv;
using namespace std;


int main(int /*argc*/, char** /*argv*/) {

    Mat img, imgLaplacian, imgResult;

    //------------------------------------------------------------------------------------------- test, first of all
    // now do it by hand
    img = (Mat_<uchar>(4,4) << 0,1,2,3,4,5,6,7,8,9,0,11,12,13,14,15); 

    // first, the good result
    Laplacian(img, imgLaplacian, CV_8UC1);
    cout << "let opencv do it" << endl;
    cout << imgLaplacian << endl;

    Mat kernel = (Mat_<float>(3,3) << 
        0,  1, 0,
        1, -4, 1,
        0,  1, 0); 
    int window_size = 3;

    // now, reaaallly by hand
    // note that, for avoiding padding, the result image will be smaller than the original one.
    Mat frame, frame32;
    Rect roi;
    imgLaplacian = Mat::zeros(img.size(), CV_32F);
    for(int y=0; y<img.rows-window_size/2-1; y++) {
        for(int x=0; x<img.cols-window_size/2-1; x++) {
            roi = Rect(x,y, window_size, window_size);
            frame = img(roi);
            frame.convertTo(frame, CV_32F);
            frame = frame.mul(kernel);
            float v = sum(frame)[0];
            imgLaplacian.at<float>(y,x) = v;
        }
    }
    imgLaplacian.convertTo(imgLaplacian, CV_8U);
    cout << "dudee" << imgLaplacian << endl;

    // a little bit less "by hand"..
    // using cv::filter2D
    filter2D(img, imgLaplacian, -1, kernel);
    cout << imgLaplacian << endl;


    //------------------------------------------------------------------------------------------- real stuffs now
    img = imread("moon.jpg", 0); // load grayscale image

    // ok, now try different kernel
    kernel = (Mat_<float>(3,3) << 
        1,  1, 1,
        1, -8, 1,
        1,  1, 1); // another approximation of second derivate, more stronger

    // do the laplacian filtering as it is
    // well, we need to convert everything in something more deeper then CV_8U
    // because the kernel has some negative values, 
    // and we can expect in general to have a Laplacian image with negative values
    // BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
    // so the possible negative number will be truncated
    filter2D(img, imgLaplacian, CV_32F, kernel);
    img.convertTo(img, CV_32F);
    imgResult = img - imgLaplacian;

    // convert back to 8bits gray scale
    imgResult.convertTo(imgResult, CV_8U);
    imgLaplacian.convertTo(imgLaplacian, CV_8U);

    namedWindow("laplacian", CV_WINDOW_AUTOSIZE);
    imshow( "laplacian", imgLaplacian );

    namedWindow("result", CV_WINDOW_AUTOSIZE);
    imshow( "result", imgResult );

    while( true ) {
        char c = (char)waitKey(10);
        if( c == 27 ) { break; }
    }

    return 0;
}

玩得开心!

于 2013-01-16T21:22:04.857 回答
1

我认为主要问题在于你做 img + laplace 的事实,而 img - laplace 会给出更好的结果。我记得 img - 2*laplace 是最好的,但我找不到我在哪里读到的,可能是在我在大学读过的一本书中。

于 2014-06-24T13:37:42.413 回答
1

你需要做img - laplace而不是img + laplace.

laplace: f(x,y) = f(x-1,y+1) + f(x-1,y-1) + f(x,y+1) + f(x+1,y) - 4*f(x,y)

因此,如果您从原始图像中看到减去拉普拉斯,您会看到 4*f(x,y) 前面的减号被否定,并且该项变为正。

您还可以使用内核-5 in the center pixel instead of -4来使拉普拉斯算子成为一步过程,而不是获得拉普拉斯算子并执行img - laplace为什么?尝试自己推导出来。

这将是最终的内核。

垫内核 = (Mat_(3,3) << -1, 0, -1, 0, -5, 0, -1, 0, -1);

于 2015-09-01T14:19:53.000 回答
0

这确实是图像处理中众所周知的结果,如果从图像中减去其拉普拉斯算子,图像边缘会被放大,从而获得更清晰的图像。

拉普拉斯滤波器内核算法:sharpened_pixel = 5 * current – left – right – up – down

在此处输入图像描述

所以代码看起来像这样:

void sharpen(const Mat& img, Mat& result)
{    
    result.create(img.size(), img.type());
    //Processing the inner edge of the pixel point, the image of the outer edge of the pixel should be additional processing
    for (int row = 1; row < img.rows-1; row++)
    {
        //Front row pixel
        const uchar* previous = img.ptr<const uchar>(row-1);
        //Current line to be processed
        const uchar* current = img.ptr<const uchar>(row);
        //new row
        const uchar* next = img.ptr<const uchar>(row+1);
        uchar *output = result.ptr<uchar>(row);
        int ch = img.channels();
        int starts = ch;
        int ends = (img.cols - 1) * ch;
        for (int col = starts; col < ends; col++)
        {
            //The traversing pointer of the output image is synchronized with the current row, and each channel value of each pixel in each row is given a increment, because the channel number of the image is to be taken into account.
            *output++ = saturate_cast<uchar>(5 * current[col] - current[col-ch] - current[col+ch] - previous[col] - next[col]);
        }
    } //end loop
    //Processing boundary, the peripheral pixel is set to 0
    result.row(0).setTo(Scalar::all(0));
    result.row(result.rows-1).setTo(Scalar::all(0));
    result.col(0).setTo(Scalar::all(0));
    result.col(result.cols-1).setTo(Scalar::all(0));
}

int main()
{    
    Mat lena = imread("lena.jpg");
    Mat sharpenedLena;
    ggicci::sharpen(lena, sharpenedLena);

    imshow("lena", lena);
    imshow("sharpened lena", sharpenedLena);
    cvWaitKey();
    return 0;
}

如果你是个懒人。享受以下乐趣。

 int main()
 {    
     Mat lena = imread("lena.jpg");
     Mat sharpenedLena;
     Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
     cv::filter2D(lena, sharpenedLena, lena.depth(), kernel);

     imshow("lena", lena);
     imshow("sharpened lena", sharpenedLena);
    cvWaitKey();
    return 0;
}

结果像这样。在此处输入图像描述

于 2016-08-24T03:18:10.207 回答