CS50 模糊滤镜在小测试用例中给出了不正确的输出
CS50 Blur filter gave incorrect outputs with small test cases
我正在为 CS50(更舒适的版本)中的过滤任务编写均值模糊过滤器。当我用我的一些照片测试它时,它似乎工作正常。但是,当我使用 CS50 测试用例对其进行测试时,它给出了小矩阵的错误结果。下面是我的代码
#define KERNEL_HEIGHT 3
#define KERNEL_WIDTH 3
#define KERNEL_SIZE 9
#define CORNER 4
#define EDGE 6
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// height and width are the height and width of the input image.
RGBTRIPLE(*extension)[width + 2] = calloc(height + 2, (width + 2) * sizeof(RGBTRIPLE)); // I will handle edge and corner cases by creating a new 2d array with 0s around
RGBTRIPLE(*newImage)[width] = calloc(height, width * sizeof(RGBTRIPLE)); //output
int cof = 0, redSum = 0, greenSum = 0, blueSum = 0;
int kernel[3][3] = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}; // Kernel for mean blur
if (newImage == NULL || extension == NULL)
{
fprintf(stderr, "Not enough memory to create a new image.\n");
return;
}
for(int i = 0; i < height; ++i)
{
memcpy(extension[i + 1], image[i], sizeof(image[i])); // Copy values from original images into extension, note that I intentionally copy at the i + 1 position.
}
for(int i = 1; i < height + 1; ++i)
{
for(int j = 1; j < width + 1; ++j)
{
redSum = 0; greenSum = 0; blueSum = 0; //Reset red, green, blue sum values.
for(int k = 0; k < KERNEL_HEIGHT; ++k)
{
for(int t = 0; t < KERNEL_WIDTH; ++t)
{
cof = kernel[k][t]; // I will multiply each value in the kernel with the pixel value and its neighbors.
redSum += cof * extension[i - 1 + k][j - 1 + t].rgbtRed;
greenSum += cof * extension[i - 1 + k][j - 1 + t].rgbtGreen;
blueSum += cof * extension[i - 1 + k][j - 1 + t].rgbtBlue;
}
}
if(i == 1 || i == height) // Detecting edge cases and corner
{
if(j == 1 || j == width) // Corner
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) CORNER);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) CORNER);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) CORNER);
}
else // Edges
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) EDGE);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) EDGE);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) EDGE);
}
}
else //Normal cases
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) KERNEL_SIZE);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) KERNEL_SIZE);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) KERNEL_SIZE);
}
}
}
for(int i = 0; i < height; ++i)
{
memcpy(image[i], newImage[i], sizeof(newImage[i])); // Copy back the results into my original image.
}
free(extension);
free(newImage);
return;
}
这是测试用例之一:
使用样本 3x3 图像进行测试(过滤中间像素)
第一行:(10, 20, 30), (40, 50, 60), (70, 80, 90)
第二行:(110, 130, 140), (120, 140, 150), (130, 150, 160)
第三行:(200, 210, 220), (220, 230, 240), (240, 250, 255)
预期输出:127 140 149
实际输出:91 100 106
几天来我一直在尝试修复此功能(gg 搜索、阅读文档),但仍然没有结果。我认为这与我如何为扩展矩阵分配内存以及如何遍历它有关。我对动态内存分配还很陌生,所以也许这就是我出错的部分。
我讨厌这样做,当我有更多时间时会重新访问但是...以下内容尚未经过测试且有意不完整 - 仅用作风格指南。
我将post BlurPixel() 的大部分内容向您展示如何以合乎逻辑的方式处理每个像素。请注意,我们没有疯狂的索引,并且每次写入都由 if 语句进行边界检查。
int r=0, g=0, b=0; // Sums accumulators
int numElements = 0; // Counts number of items accumulated.
// Loop from 1 less to 1 more than the current X and Y position.
for(int xOffset=-1; xOffset<=1; xOffset++)
{
for(int yOffset=-1; yOffset<=1; yOffset++)
{
const int newX = x + xOffset;
const int newY = y + yOffset;
// Bounds check...
if(newX >= 0 && newX < width &&
newY >= 0 && newY < height)
{
// In range, add to accumulators and increment element counter.
r += image[newY][newX].red;
g += image[newY][newX].green;
b += image[newY][newX].blue;
numElements++;
}
}
}
// Assign the rounded values to the new structure. Could do this with integers
// if we added numElements/2 to list before divide.
newImage[j][i].red = (int)round((float) r / numElements);
newImage[j][i].green = (int)round((float) g / numElements);
newImage[j][i].blue = (int)round((float) b / numElements);
我正在为 CS50(更舒适的版本)中的过滤任务编写均值模糊过滤器。当我用我的一些照片测试它时,它似乎工作正常。但是,当我使用 CS50 测试用例对其进行测试时,它给出了小矩阵的错误结果。下面是我的代码
#define KERNEL_HEIGHT 3
#define KERNEL_WIDTH 3
#define KERNEL_SIZE 9
#define CORNER 4
#define EDGE 6
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// height and width are the height and width of the input image.
RGBTRIPLE(*extension)[width + 2] = calloc(height + 2, (width + 2) * sizeof(RGBTRIPLE)); // I will handle edge and corner cases by creating a new 2d array with 0s around
RGBTRIPLE(*newImage)[width] = calloc(height, width * sizeof(RGBTRIPLE)); //output
int cof = 0, redSum = 0, greenSum = 0, blueSum = 0;
int kernel[3][3] = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}; // Kernel for mean blur
if (newImage == NULL || extension == NULL)
{
fprintf(stderr, "Not enough memory to create a new image.\n");
return;
}
for(int i = 0; i < height; ++i)
{
memcpy(extension[i + 1], image[i], sizeof(image[i])); // Copy values from original images into extension, note that I intentionally copy at the i + 1 position.
}
for(int i = 1; i < height + 1; ++i)
{
for(int j = 1; j < width + 1; ++j)
{
redSum = 0; greenSum = 0; blueSum = 0; //Reset red, green, blue sum values.
for(int k = 0; k < KERNEL_HEIGHT; ++k)
{
for(int t = 0; t < KERNEL_WIDTH; ++t)
{
cof = kernel[k][t]; // I will multiply each value in the kernel with the pixel value and its neighbors.
redSum += cof * extension[i - 1 + k][j - 1 + t].rgbtRed;
greenSum += cof * extension[i - 1 + k][j - 1 + t].rgbtGreen;
blueSum += cof * extension[i - 1 + k][j - 1 + t].rgbtBlue;
}
}
if(i == 1 || i == height) // Detecting edge cases and corner
{
if(j == 1 || j == width) // Corner
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) CORNER);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) CORNER);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) CORNER);
}
else // Edges
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) EDGE);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) EDGE);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) EDGE);
}
}
else //Normal cases
{
newImage[i - 1][j - 1].rgbtRed = (int) round((float) redSum / (float) KERNEL_SIZE);
newImage[i - 1][j - 1].rgbtGreen = (int) round((float) greenSum / (float) KERNEL_SIZE);
newImage[i - 1][j - 1].rgbtBlue = (int) round((float) blueSum / (float) KERNEL_SIZE);
}
}
}
for(int i = 0; i < height; ++i)
{
memcpy(image[i], newImage[i], sizeof(newImage[i])); // Copy back the results into my original image.
}
free(extension);
free(newImage);
return;
}
这是测试用例之一:
使用样本 3x3 图像进行测试(过滤中间像素)
第一行:(10, 20, 30), (40, 50, 60), (70, 80, 90)
第二行:(110, 130, 140), (120, 140, 150), (130, 150, 160)
第三行:(200, 210, 220), (220, 230, 240), (240, 250, 255)
预期输出:127 140 149
实际输出:91 100 106
几天来我一直在尝试修复此功能(gg 搜索、阅读文档),但仍然没有结果。我认为这与我如何为扩展矩阵分配内存以及如何遍历它有关。我对动态内存分配还很陌生,所以也许这就是我出错的部分。
我讨厌这样做,当我有更多时间时会重新访问但是...以下内容尚未经过测试且有意不完整 - 仅用作风格指南。
我将post BlurPixel() 的大部分内容向您展示如何以合乎逻辑的方式处理每个像素。请注意,我们没有疯狂的索引,并且每次写入都由 if 语句进行边界检查。
int r=0, g=0, b=0; // Sums accumulators
int numElements = 0; // Counts number of items accumulated.
// Loop from 1 less to 1 more than the current X and Y position.
for(int xOffset=-1; xOffset<=1; xOffset++)
{
for(int yOffset=-1; yOffset<=1; yOffset++)
{
const int newX = x + xOffset;
const int newY = y + yOffset;
// Bounds check...
if(newX >= 0 && newX < width &&
newY >= 0 && newY < height)
{
// In range, add to accumulators and increment element counter.
r += image[newY][newX].red;
g += image[newY][newX].green;
b += image[newY][newX].blue;
numElements++;
}
}
}
// Assign the rounded values to the new structure. Could do this with integers
// if we added numElements/2 to list before divide.
newImage[j][i].red = (int)round((float) r / numElements);
newImage[j][i].green = (int)round((float) g / numElements);
newImage[j][i].blue = (int)round((float) b / numElements);