【问题标题】:cs50 pset4 - edge detection filter not working - sobel operatorcs50 pset4 - 边缘检测过滤器不起作用 - sobel 算子
【发布时间】:2020-11-13 13:15:20
【问题描述】:

我编写的以下代码旨在使用 sobel 算子检测像素中的边缘。但是,它无法通过 check50(cs50 提供的工具)给出的所有测试。输出图像也与输入完全相同。

在继续阅读之前,请访问the pset's link

  • 注意: 我应该在像素周围形成一个 3x3 网格 我要过滤,以便可以迭代 GX 和 GY 值中的每个值。我使用整数 hhww 来执行此操作。
       // Detect edges
        void edges(int height, int width, RGBTRIPLE image[height][width])
        {
            int sqrtRedd;
            int sqrtGreenn;
            int sqrtBluee;
        
        //make copy of image
            RGBTRIPLE copy[height][width];
        
            for(int h = 0; h < height; h++)
            {
                for(int w = 0; w < width; w++)
                {
                    copy[h][w] = image[h][w];
                }
            }
        
        //loop through pixels
            for(int h = 0; h < height; h++)
            {
                for(int w = 0; w < width; w++)
                {
                    int GXred = 0;
                    int GYred = 0;
                    int GXgreen = 0;
                    int GYgreen = 0;
                    int GXblue = 0;
                    int GYblue = 0;
                    
                    for(int hh = -1; hh <= 1; hh++)
                    {
                        for(int ww = -1; ww <= 1; ww++)
                        {
                            if( h + hh >= 0 && h + hh < height && w + ww >= 0 && w + ww < width)
                            {
                                //form 3x3 grid
                            GXred += ww * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
                            GYred += hh * copy[2 - hh * hh][2 - ww * ww].rgbtRed;
     
    
                       
                        GXgreen += ww * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
                        GYgreen += hh * copy[2 - hh * hh][2 - ww * ww].rgbtGreen;
                        
                        GXblue += ww * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
                        GXblue += hh * copy[2 - hh * hh][2 - ww * ww].rgbtBlue;
                        
                            }
                        }
                    }
                    
                    int red = round(sqrt(GXred * GXred + GYred * GYred));
                    int green = round(sqrt(GXgreen * GXgreen + GYgreen * GXgreen));
                    int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));
                    
                    if(red > 225)
                    {
                        red = 225;
                    }
                    
                    else if(green > 225)
                    {
                        green = 225;
                    }
                    
                    else if(blue > 225)
                    {
                        blue = 225
                    }
                    
                    image[h][w].rgbtRed = red;
                    image[h][w].rgbtGreen = green;
                    image[h][w].rgbtBlue = blue;
                    
                }
            }
                
            return;
        }

RGBTRIPLE:

typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

这些是 check50 给出的错误信息:

    :( edges correctly filters middle pixel
        expected "210 150 60\n", not "143 105 30\n"
    :( edges correctly filters pixel on edge
        expected "213 228 255\n", not "164 144 79\n"
    :( edges correctly filters pixel in corner
        expected "76 117 255\n", not "58 77 64\n"
    :( edges correctly filters 3x3 image
        expected "76 117 255\n21...", not "58 77 64\n164 ..."
    :( edges correctly filters 4x4 image
        expected "76 117 255\n21...", not "58 77 64\n164 ..."

如您所见,输出值与实际值相差甚远,甚至不接近应有的值。问题是:我不知道这些错误是否是由 a)我试图从内核中找到 GX 和 GY 值的方式引起的,或者 b)我应用 sobel 运算符的方式。

我尝试过以其他方式查找 GX 和 GY 值(无效),例如:

                         if(hh == -1)
                         {
                            GYred += copy[h - 1][w + ww].rgbtRed * -1;
                            GYgreen += copy[h - 1][w + ww].rgbtGreen * -1;
                            GYblue += copy[h - 1][w + ww].rgbtBlue * -1;
                         }
                         
                         else if( hh == 0)
                         {
                             GYred += copy[h][w + ww].rgbtRed * 0;
                             GYgreen += copy[h][w + ww].rgbtGreen * 0;
                             GYblue += copy[h][w + ww].rgbtBlue * 0;
                         }
                         
                         else if(hh == 1)
                         {
                             GYred += copy[h + 1][w + ww].rgbtRed * 1;
                             GYgreen += copy[h + 1][w + ww].rgbtGreen * 1;
                             GYblue += copy[h + 1][w + ww].rgbtBlue * 2;
                         }
                         
                         else if(hh == 2)
                         {
                             GYred += copy[h + 2][w + ww].rgbtRed * 2;
                             GYgreen += copy[h + 2][w + ww].rgbtGreen * 2;
                             GYblue += copy[h + 2][w + ww].rgbtBlue * 2;
                         }
                         
    //start setting GX values
                         if(ww == -2)
                         {
                             GXred += copy[h + hh][w - 2].rgbtRed * -2;
                             GXgreen += copy[h + hh][w - 2].rgbtGreen * -2;
                             GXblue += copy[h + hh][w - 2].rgbtBlue * -2;
                         }
                         
                         else if(ww == -1)
                         {
                             GXred += copy[h + hh][w - 1].rgbtRed * -1;
                             GXgreen += copy[h + hh][w - 1].rgbtGreen * -1;
                             GXblue += copy[h + hh][w - 1].rgbtBlue * -1;
                         }
                         
                         else if(ww == 0)
                         {
                             GXred += copy[h + hh][w].rgbtRed * 0;
                             GXgreen += copy[h + hh][w].rgbtGreen * 0;
                             GXblue += copy[h + hh][w].rgbtBlue * 0;
                         }
                         
                         else if(ww == 1)
                         {
                             GXred += copy[h + hh][w + 1].rgbtRed * 1;
                             GXgreen += copy[h + hh][w + 1].rgbtGreen * 1;
                             GXblue += copy[h + hh][w + 1].rgbtBlue * 1;
                         }

我已经被这个 pset 卡住了将近一个星期,所以此时我不知道还能尝试什么。

【问题讨论】:

  • 你的计算很可能是错误的。你试过调试吗?另一种方法是在检查点打印值,这可以让您了解正在发生的事情..
  • 我可能已经提到过......您不会在任何地方应用矩阵中的因子。你的第二种方法也没有增加任何价值。这也很混乱。现在你有范围 -1..1 但仍然检查 hh==2ww==-2 这没有任何意义。
  • 你不明白。检查点不代表最终结果。在您知道期望值的地方打印中间值。然后比较打印的值。
  • 这是做什么用的? GXred += ww * copy[2 - hh * hh][2 - ww * ww].rgbtRed; 请开始写下将用作索引的值。
  • else if(blue &gt; 225) 为什么你认为,如果绿色溢出,你不需要检查蓝色溢出?你在哪里得到限制225?应该是255

标签: c cs50 edge-detection sobel


【解决方案1】:

您有相当多的部分没有真正意义或缺失。

  • 您没有在任何地方应用 sobel 因子。仅采用 3x3 网格内的偏移量不会产生正确的值,
  • 您只能限制 1 个颜色通道以防溢出,
  • 您限制为 225 而不是 255,
  • 您将GXblueGYblue 混合在一起,GXgreenGYgreen 也是如此。

我准备了一个新版本,应该可以解决问题。 现在已经过测试,测试数据来自最初失败的 4x4 图像测试。


#include <stdio.h>
#include <math.h>

typedef unsigned char BYTE;

typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int sqrtRedd;
    int sqrtGreenn;
    int sqrtBluee;

    //make copy of image
    RGBTRIPLE copy[height][width];
    for(int h = 0; h < height; h++)
    {
        for(int w = 0; w < width; w++)
        {
            copy[h][w] = image[h][w];
        }
    }

    //loop through pixels
    for(int h = 0; h < height; h++)
    {
        for(int w = 0; w < width; w++)
        {
            int GXred = 0;
            int GYred = 0;
            int GXgreen = 0;
            int GYgreen = 0;
            int GXblue = 0;
            int GYblue = 0;
            
            int index = 0;
            int factorsX[] = {-1,  0,  1, -2, 0, 2, -1, 0, 1};
            int factorsY[] = {-1, -2, -1,  0, 0, 0,  1, 2, 1};

            //form 3x3 grid
            for(int hh = -1; hh <= 1; hh++)
            {
                for(int ww = -1; ww <= 1; ww++)
                {
                    int x = w+ww;
                    int y = h+hh;
                    if( y >= 0 && y < height && x >= 0 && x < width)
                    {
                        GXred += factorsX[index] * copy[y][x].rgbtRed;
                        GYred += factorsY[index] * copy[y][x].rgbtRed;

                        GXgreen += factorsX[index] * copy[y][x].rgbtGreen;
                        GYgreen += factorsY[index] * copy[y][x].rgbtGreen;

                        GXblue += factorsX[index] * copy[y][x].rgbtBlue;
                        GYblue += factorsY[index] * copy[y][x].rgbtBlue;
                    }                   
                    index++;
                }
            }

            int red = round(sqrt(GXred * GXred + GYred * GYred));
            int green = round(sqrt(GXgreen * GXgreen + GYgreen * GYgreen));
            int blue = round(sqrt(GXblue * GXblue + GYblue * GYblue));

            if(red > 255)
            {
                red = 255;
            }
            if(green > 255)
            {
                green = 255;
            }
            if(blue > 255)
            {
                blue = 255;
            }

            image[h][w].rgbtRed = red;
            image[h][w].rgbtGreen = green;
            image[h][w].rgbtBlue = blue;
        }
    }

    return;
}

int main(void)
{
    RGBTRIPLE test_4x4[4][4] = {
        {{0, 10, 25}, {0, 10, 30}, {40, 60, 80}, {50, 60, 80}},
        {{20, 30, 90}, {30, 40, 100}, {80, 70, 90}, {80, 80, 90}},
        {{20, 20, 40}, {30, 10, 30}, {50, 40, 10}, {50, 40, 100}},
        {{50, 20, 40}, {50, 20, 40}, {50, 40, 80}, {50, 40, 80}},
    };

    edges(4, 4, test_4x4);
    for(int h = 0; h < 4; h++)
    {
        for(int w = 0; w < 4; w++)
        {
            printf("%d %d %d\n", test_4x4[h][w].rgbtBlue, test_4x4[h][w].rgbtGreen, test_4x4[h][w].rgbtRed);
        }
    }

    return 0;
}

【讨论】:

  • 您能解释一下您添加的整数的意义吗(factorsX[]、factorsY[]、x、h 和 index)。因为我不想在不完全理解这一切的情况下改变我自己的代码。谢谢!
  • 正如我多次提到的 Sobel 因子,这些数字对您来说应该很熟悉。它们是您提供的链接中的因素:cs50.harvard.edu/x/2020/psets/4/filter/more/sobel.png 我只是在穿过 3x3 网格时一个接一个地使用它们。
  • 所以我做了你推荐的事情,这些是我得到的错误::(边缘正确过滤了预期的中间像素“210 150 60\n”,而不是“210 150 30\n”:) 边缘正确过滤边缘上的像素 :) 边缘正确过滤角落中的像素 :( 边缘正确过滤预期的 3x3 图像“76 117 255\n21...”,而不是“76 117 255\n21...” :( 边缘正确过滤预期的 4x4 图像“76 117 255\n21...”,而不是“76 117 255\n21...”。你知道我该如何解决吗?
  • 我在编辑中引入了一个错字。一个因素是错误的。我有错误的变量名h 而不是y。您使用了我的 sn-p 还是使用了任务描述中的正确因素?如前所述,代码未经测试
  • 此外,您在评论中添加的值在某些情况下也不会显示错误。你能分享结果的链接吗?
猜你喜欢
  • 2021-02-01
  • 2020-09-25
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
相关资源
最近更新 更多