我试图实现拉普拉斯过滤器锐化图像。但结果有点灰色,我不知道我的代码出了什么问题。
到目前为止我的工作是
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;
}这是结果

正如您在上面的代码中所看到的,我已经将像素值标准化为0-255。我还是不知道这里出了什么问题。这里有人能解释一下为什么吗?
发布于 2018-10-10 16:32:29
灰色是因为,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成为单一卷积的方法。
发布于 2018-10-10 16:21:09
问题是,您正在夹紧和重新缩放图像。看看月亮的左下角:在非常暗的像素旁边有非常亮的像素,然后除了明亮的像素,还有一些灰色的像素。你的锐化过滤器将真正尖峰在明亮的边界,并增加最大。同样,黑色像素将进一步减少。
然后确定最小值和最大值,然后重新绘制整个图像。这必然意味着当显示在上一个灰度中时,整个图像将失去对比度,因为您的过滤器输出的像素值在255以上和0以下。
在输出图像中,仔细观察月亮的边界:

有一个黑色光环(新0)和一个明亮,尖锐的边缘(新的255)。(浏览器图像缩放使其在这个屏幕截图中变得不那么清晰,看看您的原始输出)。其他的一切都被重新定标压碎了,所以以前的黑色(0)现在是深灰色的。
https://stackoverflow.com/questions/52744067
复制相似问题