CS50 - pset4 过滤器问题 "blur"
CS50 - Issue with pset4 filter "blur"
我的模糊函数运行异常。我已经从 check50 重新创建了 3x3 位图,以便从我的测试中获得更近似的结果,但是由于某种原因,每个右边缘或下边缘像素都无法正常工作。
在调试时,我发现出于某种原因,我的 for 循环没有正常运行。我将在下面展示我的代码和示例。
代码:
// 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;
}
这是
output.
作为我在调试过程中发现的示例,假设:
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)
.
获取值
我还没有测试其他错误情况,但我想那里也发生了类似的事情。
如有任何帮助,我们将不胜感激。
这是我的最高评论开头:
It might be better if counter
were an int
. 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 to sumRed % 256
. That would yield 257 --> 1
(nearly black) instead of 257 --> 255
(bright red)
你最大的问题是你的卷积核指标计算不正确
而不是:
(i - k)
(j - m)
你想要:
(i + k)
(j + m)
此外,从 temp
复制回 image
的最终循环的限制关闭了 1。
此外,我会使用更具描述性的变量。而且,您的代码可以简化一点。这是包含错误修复的重构版本:
#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
}
我的模糊函数运行异常。我已经从 check50 重新创建了 3x3 位图,以便从我的测试中获得更近似的结果,但是由于某种原因,每个右边缘或下边缘像素都无法正常工作。
在调试时,我发现出于某种原因,我的 for 循环没有正常运行。我将在下面展示我的代码和示例。
代码:
// 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;
}
这是 output.
作为我在调试过程中发现的示例,假设:
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)
.
我还没有测试其他错误情况,但我想那里也发生了类似的事情。
如有任何帮助,我们将不胜感激。
这是我的最高评论开头:
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)
你最大的问题是你的卷积核指标计算不正确
而不是:
(i - k)
(j - m)
你想要:
(i + k)
(j + m)
此外,从 temp
复制回 image
的最终循环的限制关闭了 1。
此外,我会使用更具描述性的变量。而且,您的代码可以简化一点。这是包含错误修复的重构版本:
#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
}