You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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];
}

额外优化建议

  1. 可以用abs()计算梯度的绝对值之和代替开平方,减少计算量,效果相近:TempG = abs(RedX) + abs(RedY);
  2. 确保round()函数的使用正确,或者直接用整数运算避免浮点误差。

内容的提问来源于stack exchange,提问作者webmessiah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:56:01