10

ゴンザレスの本の標準的な画像をシャープにしようとしていました。以下は私が試したいくつかのコードですが、シャープな画像の結果に近づいていません。

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

問題は、2次導関数を取得する前に画像がぼやけていることだと思います。

これが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が最高だったことを覚えていますが、おそらく大学で読んだ本の1つで、それをどこで読んだかわかりません。

于 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 *現在–左–右–上–下

ここに画像の説明を入力してください

したがって、コードは次のようになります。

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 に答える