拉普拉斯锐化结果有点灰C ++

时间:2018-10-10 15:43:42

标签: c++ opencv image-processing

我正在尝试实现拉普拉斯滤镜以锐化图像。 但是结果有点灰色,我不知道我的代码出了什么问题。

到目前为止,这是我的工作

     img = imread("moon.png", 0);
     Mat convoSharp() {

    //creating new image
    Mat res = img.clone();
    for (int y = 0; y < res.rows; y++) {
        for (int x = 0; x < res.cols; x++) {
            res.at<uchar>(y, x) = 0.0;
        }
    }

    //variable declaration
    //change -5 to -4 for original result.
    int filter[3][3] = { {0,1,0},{1,-4,1},{0,1,0} };
    //int filter[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
    int height = img.rows;
    int width = img.cols;
    int **temp = new int*[height];
    for (int i = 0; i < height; i++) {
        temp[i] = new int[width];
    }
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            temp[i][j] = 0;
        }
    }
    int filterHeight = 3;
    int filterWidth = 3;
    int newImageHeight = height - filterHeight + 1;
    int newImageWidth = width - filterWidth + 1;
    int i, j, h, w;

    //convolution
    for (i = 0; i < newImageHeight; i++) {
        for (j = 0; j < newImageWidth; j++) {
            for (h = i; h < i + filterHeight; h++) {
                for (w = j; w < j + filterWidth; w++) {
                    temp[i][j] += filter[h - i][w - j] * (int)img.at<uchar>(h, w);
                }
            }
        }
    }

    //find max and min
    int max = 0;
    int min = 100;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (temp[i][j] > max) {
                max = temp[i][j];
            }
            if (temp[i][j] < min) {
                min = temp[i][j];
            }
        }
    }

    //clamp 0 - 255
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            res.at<uchar>(i, j) = 0 + (temp[i][j] - min)*(255 - 0) / (max - min);
        }
    }

    //empty the temp array
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            temp[i][j] = 0;
        }
    }

    //img - res and store it in temp array
    for (int y = 0; y < res.rows; y++) {
        for (int x = 0; x < res.cols; x++) {
            //int a = (int)img.at<uchar>(y, x) - (int)res.at<uchar>(y, x);
            //cout << a << endl;
            temp[y][x] = (int)img.at<uchar>(y, x) - (int)res.at<uchar>(y, x);

        }
    }

    //find the new max and min
    max = 0;
    min = 100;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            if (temp[i][j] > max) {
                max = temp[i][j];
            }
            if (temp[i][j] < min) {
                min = temp[i][j];
            }
        }
    }

    //clamp it back to 0-255
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            res.at<uchar>(i, j) = 0 + (temp[i][j] - min)*(255 - 0) / (max - min);
            temp[i][j] = (int)res.at<uchar>(i, j);
        }
    }



    return res;
}

这是结果

Result

正如您在上面的代码中看到的那样,我已经将像素值标准化为0-255。我仍然不知道这里出了什么问题。这里有人可以解释为什么吗?

2 个答案:

答案 0 :(得分:0)

问题是您正在夹紧并重新缩放图像。看一下月亮的左下边界:在非常暗的像素旁边有非常亮的像素,然后在明亮的像素旁边还有一些灰色像素。您的锐化滤镜将真正刺破该明亮的边框并增加最大值。同样,黑色像素将进一步减少。

然后确定最小和最大并重新缩放整个图像。这必然意味着当以以前的灰度显示时,整个图像将失去对比度,因为您的滤镜输出的像素值大于255而小于0。

在输出图像中仔细查看月亮的边界:

enter image description here

有一个黑色的光环(新的0)和一个明亮而锋利的边缘(新的255)。 (浏览器图像的缩放使此屏幕截图变得不那么清晰,请查看原始输出)。缩放后,其他所有内容均被压缩,因此以前的黑色(0)现在变为深灰色。 >

答案 1 :(得分:0)

灰色是因为as Max suggested in his answer,您正在缩放到0-255的范围,而不是钳位(如代码中的注释所建议的那样)。

但是,这并不是代码中的所有问题。 Laplace运算符的输出包含负值。您可以将它们很好地存储在int中。但是随后您可以缩放并复制到char。不要那样做!

您需要将Laplace的结果原样添加到图像中。这样,图像中的某些像素会变暗,而某些会变亮。这就是导致边缘显得更清晰的原因。

仅跳过代码中的某些循环,并保留执行temp = img - temp的循环。这样一来,您可以自由缩放或限制到输出范围,然后投射到char

要进行钳位,只需将任何像素值设置为0到0以下,以及将任何像素值设置为255到255以上。不要像这样做那样计算最小/最大和缩放,因为这样会降低对比度并在图像上产生灰色阴影。

您最近的问题非常相似(尽管代码中的问题有所不同),请再次阅读my answer there,它提出了一种进一步简化代码以使img-Laplace成为单个卷积的方法。 / p>