CS50-出现pset4过滤器“模糊"问题 [英] CS50 - Issue with pset4 filter "blur"
问题描述
我的模糊功能表现异常.我已经从check50重新创建了3x3位图,以便从测试中获得更多近似结果,但是由于某些原因,每个右边缘或下边缘像素均无法正常工作.
My blur function is behaving oddly. I've recreated the 3x3 bitmap from check50 to get more approximate results from my tests but, for some reason, every right or lower edge pixels are not working properly.
在调试时,由于某种原因,我发现我的for循环行为异常.我将在下面显示我的代码和示例.
While debugging, I've found that, for some reason, my for loops are not behaving properly. I'll show my code and an example below.
代码:
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE temp[height][width]; // Declares temporary structure to avoid overwriting of original values while running loops
// For loop to set the value of i, rows or height
for (int i = 0; i < height; i++)
{
// For loop to set the value of j, columns or width
for (int j = 0; j < width; j++)
{
float counter = 0.0;
int sumRed = 0;
int sumGreen = 0;
int sumBlue = 0;
// For loop to set the value of k, to get surrounding pixels
for (int k = -1; k < 2; k++)
{
for (int m = -1; m < 2; m++)
{
if ((i - k) >= 0 && (i - k) < height && (j - m) >= 0 && (j - m) < width)
{
sumRed = sumRed + image[i - k][j - m].rgbtRed; // Adds the value of verified pixel to the sum
sumGreen = sumGreen + image[i - k][j - m].rgbtGreen;
sumBlue = sumBlue + image[i - k][j - m].rgbtBlue;
counter++; // To get the average
}
}
}
temp[i][j].rgbtRed = round(sumRed / counter); // Sets new color based on average of surrounding pixels
temp[i][j].rgbtGreen = round(sumGreen / counter);
temp[i][j].rgbtBlue = round(sumBlue / counter);
}
}
// Start new loops to switch original values with temp values
for (int i = 0; i < height - 1; i++)
{
for (int j = 0; j < width - 1; j++)
{
image[i][j].rgbtRed = temp[i][j].rgbtRed;
image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
image[i][j].rgbtBlue = temp[i][j].rgbtBlue;
}
}
return;
}
这是 输出.
作为我在调试过程中发现的示例,我们可以这样说:
As an example of what I've found during the debug, let's say that:
i = 0
j = 2
k = 0
m = 0
在这里,不是从sumRed
获取image[0 - 0][2 - 0] (RGB 70, 80, 90)
的值,而是从image[2][2] (RGB 240, 250, 255)
获取值.
Here, instead of sumRed
getting the value of image[0 - 0][2 - 0] (RGB 70, 80, 90)
, it's getting the values from image[2][2] (RGB 240, 250, 255)
.
我还没有测试其他错误情况,但是我想那里正在发生类似的事情.
I've not yet tested the other error cases, but I suppose something similar is happening there.
任何帮助将不胜感激.
推荐答案
这是我的最高评价的开头:
This is prefaced by my top comment:
如果
counter
是int
,可能会更好.然后,执行:round((double) sumRed / counter)
,但是,输出单元只有八位.您可能需要:sumRed = round((double) sumRed / counter); temp[i][j].rgbtRed = (sumRed < 255) ? sumRed : 255;
这是饱和度数学.否则,当您分配给8位单元时,它是模数学,等效于sumRed % 256
.这将产生257 --> 1
(接近黑色)而不是257 --> 255
(亮红色)
It might be better if
counter
were anint
. Then, do:round((double) sumRed / counter)
, But, the output cell is only eight bits. You may need:sumRed = round((double) sumRed / counter); temp[i][j].rgbtRed = (sumRed < 255) ? sumRed : 255;
This is saturation math. Otherwise, when you assign to an 8 bit cell, it's modulo math, equivalent tosumRed % 256
. That would yield257 --> 1
(nearly black) instead of257 --> 255
(bright red)
您最大的问题是卷积内核索引计算不正确.
Your biggest problem is that your convolution kernel index calculations are incorrect.
代替:
(i - k)
(j - m)
您想要:
(i + k)
(j + m)
此外,您将要从temp
复制回image
的最终循环的限制为1.
Also, your the limits on your final loops to copy back from temp
to image
are off by 1.
此外,我将使用更多描述性变量.而且,您的代码可以简化一些.这是包含错误修复的重构版本:
Plus, I'd use more descriptive variables. And, your code can be simplified a bit. Here's a refactored version that incorporates the bug fixes:
#include <math.h>
typedef struct {
unsigned char rgbtRed;
unsigned char rgbtGreen;
unsigned char rgbtBlue;
} __attribute__((__packed__)) RGBTRIPLE;
// Blur image
void
blur(int height, int width, RGBTRIPLE image[height][width])
{
// Declares temporary structure to avoid overwriting of original values
// while running loops
RGBTRIPLE temp[height][width];
#if 1
RGBTRIPLE *tmp;
RGBTRIPLE *img;
#endif
// For loop to set the value of yctr, rows or height
for (int yctr = 0; yctr < height; yctr++) {
// For loop to set the value of xctr, columns or width
for (int xctr = 0; xctr < width; xctr++) {
#if 0
float counter = 0.0;
#else
int counter = 0;
#endif
int sumRed = 0;
int sumGreen = 0;
int sumBlue = 0;
// For loop to set the value of yoff, to get surrounding pixels
for (int yoff = -1; yoff < 2; yoff++) {
// NOTE/BUG: this is the main bug
#if 0
int ycur = yctr - yoff;
#else
int ycur = yctr + yoff;
#endif
if (ycur < 0)
continue;
if (ycur >= height)
continue;
for (int xoff = -1; xoff < 2; xoff++) {
// NOTE/BUG: this is the main bug
#if 0
int xcur = xctr - xoff;
#else
int xcur = xctr + xoff;
#endif
if (xcur < 0)
continue;
if (xcur >= width)
continue;
// Adds the value of verified pixel to the sum
tmp = &image[ycur][xcur];
sumRed += tmp->rgbtRed;
sumGreen += tmp->rgbtGreen;
sumBlue += tmp->rgbtBlue;
counter++; // To get the average
}
}
// Sets new color based on average of surrounding pixels
tmp = &temp[yctr][xctr];
#if 0
tmp->rgbtRed = round(sumRed / counter);
tmp->rgbtGreen = round(sumGreen / counter);
tmp->rgbtBlue = round(sumBlue / counter);
#else
sumRed = round((double) sumRed / counter);
tmp->rgbtRed = (sumRed < 255) ? sumRed : 255;
sumGreen = round((double) sumGreen / counter);
tmp->rgbtGreen = (sumGreen < 255) ? sumGreen : 255;
sumBlue = round((double) sumBlue / counter);
tmp->rgbtBlue = (sumBlue < 255) ? sumBlue : 255;
#endif
}
}
// Start new loops to switch original values with temp values
// NOTE/BUG: the for loop ranges are incorrect
#if 0
for (int yctr = 0; yctr < height - 1; yctr++) {
for (int xctr = 0; xctr < width - 1; xctr++) {
image[yctr][xctr].rgbtRed = temp[yctr][xctr].rgbtRed;
image[yctr][xctr].rgbtGreen = temp[yctr][xctr].rgbtGreen;
image[yctr][xctr].rgbtBlue = temp[yctr][xctr].rgbtBlue;
}
}
#endif
#if 0
for (int yctr = 0; yctr < height; yctr++) {
for (int xctr = 0; xctr < width; xctr++) {
image[yctr][xctr] = temp[yctr][xctr];
}
}
#endif
#if 1
tmp = &temp[0][0];
img = &image[0][0];
int idxlim = width * height;
for (int idxcur = 0; idxcur < idxlim; idxcur++)
img[idxcur] = tmp[idxcur];
#endif
}
这篇关于CS50-出现pset4过滤器“模糊"问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!