尝试在 CS50 中为 PSET4 的图像实施框模糊时,为什么我的 RGB 值略有偏差?
Why are my RGB values slightly off when trying to implement a box blur on a image for PSET4 in CS50?
我已经为此工作了几个星期但无济于事。我认为逻辑和实现是合理的,但它没有通过所有测试,除了模糊角像素。
我的逻辑:将原始文件图像中的每个像素复制到相同的图像,计算每个相邻像素(如果存在)的 RGB 值的平均值,然后应用回原始图像。我的实现通过嵌套循环扫描每个像素的上行、下行和下行。我知道这不是最简洁的实施方式——我是新手。
下面是一个此类错误的示例:
:( blur incorrectly filters 3x3 image
Expected Output
70 85 95
80 95 105
90 105 115
117 130 140
127 140 149
137 150 159
163 178 188
170 185 194
178 193 201
我的结果:
Actual Output
70 85 95
90 106 116
103 119 129
135 150 160
145 160 169
155 169 178
175 188 197
178 191 200
180 193 201
这是我的代码(用 C 语言编写):
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE imageCopy[height][width];
//assign new image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
imageCopy[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int red = 0;
int green = 0;
int blue = 0;
float pixelCount = 0.00;
//scan top row
for (int k = -1; k < 2; k++)
{
if ((i - 1) >= 0 && (j + k) >= 0 && (j + k) < width)
{
red += imageCopy[i - 1][j + k].rgbtRed;
green += imageCopy[i - 1][j + k].rgbtGreen;
blue += imageCopy[i - 1][j + k].rgbtBlue;
pixelCount++;
}
}
//scan same row
for (int m = -1; m < 2; m++)
{
if ((j + m) >= 0 && (j + m) < width)
{
red += imageCopy[i][j + m].rgbtRed;
green += imageCopy[i][j + m].rgbtGreen;
blue += imageCopy[i][j + m].rgbtBlue;
pixelCount++;
}
}
//scan below row
for (int n = -1; n < 2; n++)
{
if ((i + 1) < height && (j + n) >= 0 && (j + n) < width)
{
red += imageCopy[i + 1][j + n].rgbtRed;
green += imageCopy[i + 1][j + n].rgbtGreen;
blue += imageCopy[i + 1][j + n].rgbtBlue;
pixelCount++;
}
}
// find averages
imageCopy[i][j].rgbtRed = round(red / pixelCount);
imageCopy[i][j].rgbtGreen = round(green / pixelCount);
imageCopy[i][j].rgbtBlue = round(blue / pixelCount);
}
}
// assign back to original image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = imageCopy[i][j];
}
}
return;
}
提前致谢。
好的,我找到了问题。
你为每个像素计算一个新的 "blurred" 值,逻辑似乎没问题。最后,您要做的是使用这段代码将像素分配给它们的 "new blurred value"。
imageCopy[i][j].rgbtRed = round(red / pixelCount);
imageCopy[i][j].rgbtGreen = round(green / pixelCount);
imageCopy[i][j].rgbtBlue = round(blue / pixelCount);
这不行,因为您对已更改的图像应用 "blur" 过滤。所以你所做的实际上是你用一个模糊的像素改变一个像素,然后对于邻域像素你使用它旁边的"blurred"像素来计算这是错误的。
解决办法;
imageCopy
在计算的时候不要改变,因为所有的模糊计算都应该在"original image"上完成。在每个像素的末尾,您应该将值直接传递给 image
。将 imageCopy
替换为 image
,如下所示。
image[i][j].rgbtRed = round(red / pixelCount);
image[i][j].rgbtGreen = round(green / pixelCount);
image[i][j].rgbtBlue = round(blue / pixelCount);
并从代码中删除这个 for 循环。
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = imageCopy[i][j];
}
}
我已经为此工作了几个星期但无济于事。我认为逻辑和实现是合理的,但它没有通过所有测试,除了模糊角像素。
我的逻辑:将原始文件图像中的每个像素复制到相同的图像,计算每个相邻像素(如果存在)的 RGB 值的平均值,然后应用回原始图像。我的实现通过嵌套循环扫描每个像素的上行、下行和下行。我知道这不是最简洁的实施方式——我是新手。
下面是一个此类错误的示例:
:( blur incorrectly filters 3x3 image
Expected Output
70 85 95
80 95 105
90 105 115
117 130 140
127 140 149
137 150 159
163 178 188
170 185 194
178 193 201
我的结果:
Actual Output
70 85 95
90 106 116
103 119 129
135 150 160
145 160 169
155 169 178
175 188 197
178 191 200
180 193 201
这是我的代码(用 C 语言编写):
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE imageCopy[height][width];
//assign new image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
imageCopy[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int red = 0;
int green = 0;
int blue = 0;
float pixelCount = 0.00;
//scan top row
for (int k = -1; k < 2; k++)
{
if ((i - 1) >= 0 && (j + k) >= 0 && (j + k) < width)
{
red += imageCopy[i - 1][j + k].rgbtRed;
green += imageCopy[i - 1][j + k].rgbtGreen;
blue += imageCopy[i - 1][j + k].rgbtBlue;
pixelCount++;
}
}
//scan same row
for (int m = -1; m < 2; m++)
{
if ((j + m) >= 0 && (j + m) < width)
{
red += imageCopy[i][j + m].rgbtRed;
green += imageCopy[i][j + m].rgbtGreen;
blue += imageCopy[i][j + m].rgbtBlue;
pixelCount++;
}
}
//scan below row
for (int n = -1; n < 2; n++)
{
if ((i + 1) < height && (j + n) >= 0 && (j + n) < width)
{
red += imageCopy[i + 1][j + n].rgbtRed;
green += imageCopy[i + 1][j + n].rgbtGreen;
blue += imageCopy[i + 1][j + n].rgbtBlue;
pixelCount++;
}
}
// find averages
imageCopy[i][j].rgbtRed = round(red / pixelCount);
imageCopy[i][j].rgbtGreen = round(green / pixelCount);
imageCopy[i][j].rgbtBlue = round(blue / pixelCount);
}
}
// assign back to original image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = imageCopy[i][j];
}
}
return;
}
提前致谢。
好的,我找到了问题。
你为每个像素计算一个新的 "blurred" 值,逻辑似乎没问题。最后,您要做的是使用这段代码将像素分配给它们的 "new blurred value"。
imageCopy[i][j].rgbtRed = round(red / pixelCount);
imageCopy[i][j].rgbtGreen = round(green / pixelCount);
imageCopy[i][j].rgbtBlue = round(blue / pixelCount);
这不行,因为您对已更改的图像应用 "blur" 过滤。所以你所做的实际上是你用一个模糊的像素改变一个像素,然后对于邻域像素你使用它旁边的"blurred"像素来计算这是错误的。
解决办法;
imageCopy
在计算的时候不要改变,因为所有的模糊计算都应该在"original image"上完成。在每个像素的末尾,您应该将值直接传递给 image
。将 imageCopy
替换为 image
,如下所示。
image[i][j].rgbtRed = round(red / pixelCount);
image[i][j].rgbtGreen = round(green / pixelCount);
image[i][j].rgbtBlue = round(blue / pixelCount);
并从代码中删除这个 for 循环。
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = imageCopy[i][j];
}
}