Sobel算子边缘检测函数输出全白图像问题排查求助
Sobel算子边缘检测输出全白图像问题排查
我实现了Sobel算子的边缘检测函数,但运行后输出全白图像,未得到预期的边缘检测效果。我认为代码逻辑大致正确,但怀疑问题出在像素与Gx/Gy数组的关联部分,无法定位具体错误点。
- 预期输出:带有清晰边缘的彩色/灰度边缘检测图像
- 实际输出:全白图像
- Sobel算子定义:3x3卷积核,Gx为横向梯度检测核
[[1,0,-1],[2,0,-2],[1,0,-1]],Gy为纵向梯度检测核[[1,2,1],[0,0,0],[-1,-2,-1]]
附实现代码
// Detect edges void edges(int height, int width, RGBTRIPLE image[height][width]) { // Grid 3x3 then every Color * Gy * Gx, new color = G (sqrt(Gx^2 + Gy^2)) 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]; //temp array for (int i = 0; i < height; i++) //copy to temporary array { for (int j = 0; j < width; j++) { temp[i][j].rgbtRed = image[i][j].rgbtRed; temp[i][j].rgbtGreen = image[i][j].rgbtGreen; temp[i][j].rgbtBlue = image[i][j].rgbtBlue; } } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) //going through array of pixels { signed int RedX = 0, GreenX = 0, BlueX = 0, RedY = 0, GreenY = 0, BlueY =0; //average color value = 0 unsigned int TempG = 0; for (int k = (i - 1); k <= i + 1; k++) //boundaries of Sobel (3x3) { for( int l = (j - 1); l <= j + 1; l++) //boundaries { if (k >= 0 && k <= (height - 1) && l >= 0 && l <= (width - 1)) //checking if pixel exists { RedX += (temp[k][l].rgbtRed * Gx[k - i][l - j]); //Calculating value in X direction GreenX += (temp[k][l].rgbtGreen * Gx[k - i][l - j]); BlueX += (temp[k][l].rgbtBlue * Gx[k - i][l - j]); //problem here RedY += (temp[k][l].rgbtRed * Gy[k - i][l - j]); // In Y direction GreenY += (temp[k][l].rgbtGreen * Gy[k - i][l - j]); BlueY += (temp[k][l].rgbtBlue * Gy[k - i][l - j]); } } } TempG = round (sqrt (pow (RedX, 2) + pow (RedY, 2))); //G = SquareRoot(Gx^2 + Gy^2) if (TempG > 255) { TempG = 255; //limiting color value } image[i][j].rgbtRed = TempG; //assigning TempG = round (sqrt (pow (GreenX, 2) + pow (GreenY, 2))); if (TempG > 255) { TempG = 255; } image[i][j].rgbtGreen = TempG; TempG = round (sqrt (pow (BlueX, 2) + pow (BlueY, 2))); if (TempG > 255) { TempG = 255; } image[i][j].rgbtBlue = TempG; } } return; }
问题根源与修正方案
核心错误
代码中访问Gx/Gy数组时使用的索引k - i和l - j会出现负数(比如当k=i-1时,k-i=-1),这会导致数组越界,访问到内存中随机的非法值,最终计算出的梯度值TempG会异常偏大,超过255后被截断为255,所以输出全白图像。
修正方法
将相对偏移转换为合法的0-2数组索引:把k - i加上1得到(k - i) + 1,l - j加上1得到(l - j) + 1,这样索引范围就变成了0、1、2,对应3x3卷积核的正确位置。
修正后的卷积计算部分代码:
if (k >= 0 && k <= (height - 1) && l >= 0 && l <= (width - 1)) //checking if pixel exists { int row_idx = (k - i) + 1; int col_idx = (l - j) + 1; RedX += temp[k][l].rgbtRed * Gx[row_idx][col_idx]; GreenX += temp[k][l].rgbtGreen * Gx[row_idx][col_idx]; BlueX += temp[k][l].rgbtBlue * Gx[row_idx][col_idx]; RedY += temp[k][l].rgbtRed * Gy[row_idx][col_idx]; GreenY += temp[k][l].rgbtGreen * Gy[row_idx][col_idx]; BlueY += temp[k][l].rgbtBlue * Gy[row_idx][col_idx]; }
额外优化建议
- 可以用
abs()计算梯度的绝对值之和代替开平方,减少计算量,效果相近:TempG = abs(RedX) + abs(RedY); - 确保
round()函数的使用正确,或者直接用整数运算避免浮点误差。
内容的提问来源于stack exchange,提问作者webmessiah
相关产品推荐
相关产品推荐

