【问题标题】:The output image is not converted to sepia. What is wrong with my sepia code?输出图像不会转换为棕褐色。我的棕褐色代码有什么问题?
【发布时间】:2021-09-29 14:58:53
【问题描述】:

我真的找不到我的代码有什么问题。输出图像甚至根本没有转换为棕褐色;它有点像灰度,有粉红色的天空。我应用的算法是正确的,并且我确实使用了 math.h 中实现的 round 函数。我猜我的 if-else 语句可能有问题?

void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    //process pixels by row
    for (int i = 0; i < height; i++)
    {
        //process a single pixel in a row
        for(int j = 0; j < width; j++)
        {
           //implement the algorithm
           float sepiaRed = 0.393 * image[i][j].rgbtRed + 0.769 * image[i][j].rgbtGreen + 0.189 * image[i][j].rgbtBlue;
        
            //round sepiaRed
            image[i][j].rgbtRed = round(sepiaRed);
            if (image[i][j].rgbtRed > 255)
            {
               image[i][j].rgbtRed = 255;
            }
            else
            {
               image[i][j].rgbtRed = image[i][j].rgbtRed;
            }
        
            float sepiaGreen = 0.349 * image[i][j].rgbtRed + 0.686 * image[i][j].rgbtGreen + 0.168 * image[i][j].rgbtBlue;
        
            //round sepiaGreen
            image[i][j].rgbtGreen = round(sepiaGreen);
            if (image[i][j].rgbtGreen > 255)
            {
                image[i][j].rgbtGreen = 255;
            }
            else
            {
                image[i][j].rgbtGreen = image[i][j].rgbtGreen;
            }
        
            float sepiaBlue = 0.272 * image[i][j].rgbtRed + 0.534 * image[i][j].rgbtGreen + 0.131 * image[i][j].rgbtBlue;
            //round sepiaBlue
            image[i][j].rgbtBlue = round(sepiaBlue);
            if (image[i][j].rgbtBlue > 255)
            {
                image[i][j].rgbtBlue = 255;
            }
            else
            {
               image[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
       }
    }
    return;
}

【问题讨论】:

  • imageunsigned char 的数组吗?如果是,则任何元素都不会大于 255:无符号算术回绕((unsigned char)((unsigned char)100 + (unsigned char)200) 产生 44
  • 是的,我可以看到。 RGBTRIPLE 的数组。 RGBTRIPLE 是由什么组成的?
  • @pmg 我不确定。问题来自cs50.harvard.edu/x/2021/psets/4/filter/less,它带有一堆 .h 和 .c 文件,我对它们只有一点了解,但我的工作是为过滤器编写代码。
  • 我的意思是:如果image[i][j].rgbtRed 是一个unsigned char 分配超过255 将环绕(image[i][j].rgbtRed = 280; 实际上是image[i][j].rgbtRed = 24;
  • @pmg 它由 BYTE rgbtBlue 制成;字节 rgbtGreen; BYTE rgbtRed;

标签: c filter cs50


【解决方案1】:

问题出在: image[i][j].rgbtRed = round(sepiaRed); 我假设rgbtRed 是 8 位长的无符号整数(通常称为“字节”)。因此,此操作将只留下sepiaRed 舍入部分的 8 个最低有效位。在转换为 8 位整数期间,其余位将被截断。

稍后的检查如下:

if (image[i][j].rgbtGreen > 255)

没有意义,因为 8 位无符号整数可以表示 0-255 范围内的数字。它不可能大于 255。

而且,下面这行看起来很多余:

image[i][j].rgbtRed = image[i][j].rgbtRed;

正确的解决方案应该限制 float 值,然后对其进行下一轮并存储为 8 位整数。

if (sepiaGreen > 255)
  sepiaGreen = 255;
image[i][j].rgbtGreen = round(sepiaGreen);

另一个问题。 在更新image[i][j]之前计算所有棕褐色组件。 否则,sepiaRed 将在计算 sepiaGreen 期间用作 rgbtRed


内部循环体的最终代码可能是:

// extract color component for give pixel
float r = image[i][j].rgbtRed;
float g = image[i][j].rgbtGreen;
float b = image[i][j].rgbtBlue;

// compute sepia components
float sepiaRed   = 0.393 * r + 0.769 * g + 0.189 * b;
float sepiaGreen = 0.349 * r + 0.686 * g + 0.168 * b;
float sepiaBlue  = 0.272 * r + 0.534 * g + 0.131 * b;

// truncate to 0-255
if (sepiaRed   > 255) sepiaRed   = 255;
if (sepiaGreen > 255) sepiaGreen = 255;
if (sepiaBlue  > 255) sepiaBlue  = 255;

// round and store
image[i][j].rgbtRed   = round(sepiaRed);
image[i][j].rgbtGreen = round(sepiaGreen);
image[i][j].rgbtBlue  = round(sepiaBlue);

【讨论】:

  • 您能否进一步扩展对“image[i][j].rgbtRed = round(sepiaRed);”的解释就像,为什么它们是最不重要的位?是的,我确实觉得“image[i][j].rgbtRed = image[i][j].rgbtRed;”有一些问题。对于限制部分,你的意思是我必须为 image[i][j].rgbtRed 创建一个 int 变量,一个为 image[i][j].rgbtGreen 和另一个为 image[i][j].rgbtBlue ?
  • @Sherri,查看更新答案
  • 非常感谢!还有一个问题,如果我只计算一个棕褐色分量然后更新 image[i][j] 的相应 RGB 值,为什么它不会给我正确的输出图像?在更新 image[i][j] 之前计算所有棕褐色组件有何不同?
  • @Sherri,因为在计算sepiaGreen 的原始代码中,您使用了image[i][j].rgbtRed,它之前已经更新了几行。结果 sepiaGreen 的值将不同于从原始 image[i][j].rgbtRed 计算的值。这是输入和输出是相同图像的许多“就地”操作的常见问题。
  • 现在我明白为什么这些语句的顺序很重要了。我觉得在编写程序时可能会遇到很多问题,这需要程序员非常谨慎地避免它们。无论如何,我真的很感谢你的帮助和时间!
猜你喜欢
  • 1970-01-01
  • 2012-03-15
  • 2020-08-19
  • 1970-01-01
  • 2011-05-07
  • 2021-03-28
  • 2012-10-22
  • 2011-06-05
相关资源
最近更新 更多