CS50滤镜进阶任务:Edges滤镜仅保留边角像素其余全黑问题
CS50 Edges滤镜问题修复
问题根源
你代码里的核心错误是计算卷积时引用了错误的像素:在遍历周围3x3像素的循环中,你始终使用image[i][j](当前目标像素)的颜色值来计算Gx和Gy,而不是使用偏移后的image[i+a][j+b]的颜色值。
对于图像中间的像素,3x3卷积核的权重会相互抵消(比如Gx的列权重-1、0、1,行相加后对于相同像素值来说总和为0),所以计算出来的gxred、gyred等都是0,最终sqrt后结果为0,导致像素全黑;而边缘/角落像素因为部分偏移超出图像范围,对应的权重没有被完全抵消,所以还能显示出像素值。
修正后的代码
把卷积计算部分的image[i][j]替换成image[i+a][j+b]即可:
void edges(int height, int width, RGBTRIPLE image[height][width]) { int Gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; int Gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; RGBTRIPLE temp[height][width]; for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { double gxred = 0, gxgreen = 0, gxblue = 0; double gyred = 0, gygreen = 0, gyblue = 0; double red = 0, green = 0, blue = 0; for(int a = -1; a <= 1; a++) { for(int b = -1; b <=1; b++) { if(a+i >= 0 && a+i < height && b+j >= 0 && b+j < width) { // 修正:使用偏移后的像素而非当前像素 gxred += Gx[a+1][b+1] * image[i+a][j+b].rgbtRed; gxgreen += Gx[a+1][b+1] * image[i+a][j+b].rgbtGreen; gxblue += Gx[a+1][b+1] * image[i+a][j+b].rgbtBlue; gyred += Gy[a+1][b+1] * image[i+a][j+b].rgbtRed; gygreen += Gy[a+1][b+1] * image[i+a][j+b].rgbtGreen; gyblue += Gy[a+1][b+1] * image[i+a][j+b].rgbtBlue; } } } red = sqrt(((gxred*gxred) + (gyred*gyred))); if(red > 255) red = 255; green = sqrt(((gxgreen*gxgreen) + (gygreen*gygreen))); if(green > 255) green = 255; blue = sqrt(((gxblue*gxblue) + (gyblue*gyblue))); if(blue > 255) blue = 255; temp[i][j].rgbtRed = red; temp[i][j].rgbtGreen = green; temp[i][j].rgbtBlue = blue; } } // 复制临时图像到原图像 for(int i = 0; i < height; i++) { for(int j = 0; j < width; j++) { image[i][j].rgbtRed = temp[i][j].rgbtRed; image[i][j].rgbtGreen = temp[i][j].rgbtGreen; image[i][j].rgbtBlue = temp[i][j].rgbtBlue; } } return; }
额外调试技巧
可以用一张小尺寸的测试图(比如3x3或5x5)来debug,这样能清晰看到每个像素的计算过程,避免大图无法查看中间值的问题。
内容的提问来源于stack exchange,提问作者Gabriel Accetta
相关产品推荐
相关产品推荐

