c - CS50 模糊过滤器在小测试用例中给出了不正确的输出
问题描述
我正在为 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搜索,阅读文档),但仍然没有结果。我认为这与我如何为扩展矩阵分配内存以及如何遍历它有关。我对动态内存分配很陌生,所以也许这就是我出错的部分。
解决方案
我讨厌这样做,并且会在我有更多时间时重新访问,但是...以下内容尚未经过测试并且故意不完整-仅用作样式指南。
我将发布 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);
推荐阅读
- java - 如何在 Java 的 OpenApi yaml 文件中强制执行“非空”
- java - 如何使用 Intent 将自定义类 ArrayList 传递给另一个 Activity?
- node.js - 使用 Agora 将语音空间限制为 60 分钟
- python - 满足特定条件后在列中查找值
- webpack - 我想将域相关文件复制到我的 dist 文件夹,以便我可以提供该文件,我使用了 copy-webpack-plugin 但它不起作用
- java - IntelliJ 无法检测到 jdk.crypto.cryptoki 包
- c++ - 使用没有定义 c++ 的函数是否合法?
- swift - UITextView 字体调整
- azure-blob-storage - C#:使用 Azure.Storage.Blobs 客户端库将 blob 从一个容器移动到另一个容器
- mysql - 如何在mysql中以一个顺序获得一组结果,并以不同顺序获得另一组行?