C-rgb值-计算模糊过滤器rgb值的平均值
前两个没那么难,但第三个让我抓狂。 模糊滤波器必须计算特定像素组的rgb值的平均值,以便替换居中像素的值。 想象一个3x3网格,其中中心的像素必须使用周围八个像素的平均值和中心像素本身的rgb值进行操作 到目前为止,我所做的工作如下:C-rgb值-计算模糊过滤器rgb值的平均值,c,loops,average,rgb,blur,C,Loops,Average,Rgb,Blur,前两个没那么难,但第三个让我抓狂。 模糊滤波器必须计算特定像素组的rgb值的平均值,以便替换居中像素的值。 想象一个3x3网格,其中中心的像素必须使用周围八个像素的平均值和中心像素本身的rgb值进行操作 到目前为止,我所做的工作如下: // Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { int n; int m; int averageRed; int a
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
int n;
int m;
int averageRed;
int averageBlue;
int averageGreen;
//For each row..
for (int i = 0; i < height; i++)
{
//..and then for each pixel in that row...
for (int j = 0; j < width; j++)
{
//...if i and j equal 0...
if (i == 0 && j == 0)
{
for (m = i; m <= 1; m++)
{
for (n = j; n <= 1; n++)
{
averageRed = averageRed + image[m][n].rgbtRed;
averageBlue = averageBlue + image[m][n].rgbtBlue;
averageGreen = averageGreen + image[m][n].rgbtGreen;
printf("%i\n", averageRed);
printf("%i\n", averageBlue);
printf("%i\n", averageGreen);
}
}
image[i][j].rgbtRed = round((float)averageRed / 4);
image[i][j].rgbtBlue = round((float)averageBlue / 4);
image[i][j].rgbtGreen = round((float)averageGreen / 4);
printf("%i\n", image[i][j].rgbtRed);
printf("%i\n", image[i][j].rgbtBlue);
printf("%i\n", image[i][j].rgbtGreen);
}
//If i equals 0 and j is greater than 0...
else if (i == 0 && j > 0)
{
//..take the line that equals i..
for (m = i; m <= 1; m++)
{
//..and take from each pixel ot that line...
for (n = j - 1; n <= 1; n++)
{
//..the color values and add them to the average-variables
averageRed = averageRed + image[m][n].rgbtRed;
averageBlue = averageBlue + image[m][n].rgbtBlue;
averageGreen = averageGreen + image[m][n].rgbtGreen;
}
}
//Set the current pixel values to the averages
image[i][j].rgbtRed = round((float)averageRed / 6);
image[i][j].rgbtBlue = round((float)averageBlue / 6);
image[i][j].rgbtGreen = round((float)averageGreen / 6);
printf("%i\n", image[i][j].rgbtRed);
printf("%i\n", image[i][j].rgbtBlue);
printf("%i\n", image[i][j].rgbtGreen);
}
else if (i > 0 && j == 0)
{
for (m = i - 1; m <= 1; m++)
{
for (n = j; n <= 1; n++)
{
averageRed = averageRed + image[m][n].rgbtRed;
averageBlue = averageBlue + image[m][n].rgbtBlue;
averageGreen = averageGreen + image[m][n].rgbtGreen;
}
}
image[i][j].rgbtRed = round((float)averageRed / 6);
image[i][j].rgbtBlue = round((float)averageBlue / 6);
image[i][j].rgbtGreen = round((float)averageGreen / 6);
}
else if (i > 0 && j > 0 )
{
// ..take every line from i - 1 to i + 1...
for (m = i - 1; m <= 1; m++)
{
//...and in each line take every pixel from j - 1 to j + 1...
for (n = j - 1; n <= 1; n++)
{
//...and add the RGB value to average-variables
averageRed = averageRed + image[m][n].rgbtRed;
averageBlue = averageBlue + image[m][n].rgbtBlue;
averageGreen = averageGreen + image[m][n].rgbtGreen;
}
}
//Set current value to the rounded average
image[i][j].rgbtRed = ((float)averageRed / 9);
image[i][j].rgbtBlue = ((float)averageBlue / 9);
image[i][j].rgbtGreen = ((float)averageGreen / 9);
}
}
}
return;
}
非常感谢您的建议
Greetz注意,
平均值*
变量是未初始化的,所以当你对它们求和时,你有UB。它们需要预设为0,当然是在开始时,但可能在每个主循环之前
此外,除了你的其他问题,其他人已经注意到,你可能需要做饱和数学 这是因为for
rgbt*
(例如rgbtRed
)是一个字节,因此值可能被错误地剪裁
你正在做:
image[i][j].rgbtRed = round((float)averageRed / 6);
这可以改写为:
averageRed = round((float)averageRed / 6);
image[i][j].rgbtRed = averageRed;
但是,如果(例如)平均值
为256,则rgbtRed
将最终为1[因为图像
的赋值是[有效的]:
image[i][j].rgbtRed = averageRed & 0xFF;
因此,不是存储鲜红色,而是存储接近黑色的颜色。最终值需要是255,即“饱和”最大颜色值
因此,为了解决这个问题[或者仅仅是为了防范它],我们应该:
averageRed = round((float)averageRed / 6);
if (averageRed > 255)
averageRed = 255;
image[i][j].rgbtRed = averageRed;
编辑:进一步思考后,您只需要在右侧可以超过255的情况下执行此操作,但我[现在]不确定它是否可以。要检查此情况,您可以添加(例如):
您可以将其包装在一个#ifdef
中,进行测试,如果它没有触发,您可以稍后删除它
更新:
这个问题听起来可能很愚蠢,但这个值怎么可能达到256?即使每个像素都是白色的,也没有一个值能达到256,或者我的错误在哪里?(1白色像素:255 255 255->10白色像素:2550 2550/10--> 是的,根据我上面的“编辑:”可能不是。我最近回答了一个类似的问题,该值可能超过255 但是,运行时错误显示该值确实超过了字节的容量(即
无符号字符
)
这可能是由于未初始化的总和变量
但是,这也是因为总和/平均值变量在循环开始时没有被重置。你从来没有重置它们,所以它们只是不断地增长
完成每个3x3卷积内核后(即存储每个输出像素后),需要重置它们
而且,我不认为你的
for(n=j;n注意average*
变量是未初始化的,所以当你对它们求和时,你有UB。它们需要被预设为0,当然是在开始时,但可能在每个主循环之前
此外,除了你的其他问题,其他人已经注意到,你可能需要做饱和数学
这是因为forrgbt*
(例如rgbtRed
)是一个字节,因此值可能被错误地剪裁
你正在做:
image[i][j].rgbtRed = round((float)averageRed / 6);
这可以改写为:
averageRed = round((float)averageRed / 6);
image[i][j].rgbtRed = averageRed;
但是,如果(例如)平均值
为256,则rgbtRed
将最终为1[因为图像
的赋值是[有效的]:
image[i][j].rgbtRed = averageRed & 0xFF;
因此,不是存储鲜红色,而是存储接近黑色的颜色。最终值需要是255,即“饱和”最大颜色值
因此,为了解决这个问题[或者仅仅是为了防范它],我们应该:
averageRed = round((float)averageRed / 6);
if (averageRed > 255)
averageRed = 255;
image[i][j].rgbtRed = averageRed;
编辑:进一步思考后,您只需要在右侧可以超过255的情况下执行此操作,但我[现在]不确定它是否可以。要检查此情况,您可以添加(例如):
您可以将其包装在一个#ifdef
中,进行测试,如果它没有触发,您可以稍后删除它
更新:
这个问题听起来可能很愚蠢,但这个值怎么可能达到256?即使每个像素都是白色的,也没有一个值能达到256,或者我的错误在哪里?(1白色像素:255 255 255->10白色像素:2550 2550/10-->
是的,根据我上面的“编辑:”可能不是。我最近回答了一个类似的问题,该值可能超过255
但是,运行时错误显示该值确实超过了字节的容量(即无符号字符
)
这可能是由于未初始化的总和变量
但是,这也是因为总和/平均值变量在循环开始时没有被重置。你从来没有重置它们,所以它们只是不断地增长
完成每个3x3卷积内核后(即存储每个输出像素后),需要重置它们
而且,我不认为你的(n=j;n的正确性需要保留原始值
为了提高速度,您只需保留原始值,直到不再需要它们;并且水平总和可以循环使用,以最大限度地减少添加
更具体地说,对于每一行像素,忽略上/下/左/右边缘(需要特别注意)并假装它是单色的(对于RGB,您只需执行全部3次):
- 对于行中的每个像素,执行
buffer[next\u buffer\u row][x]=image[y+2][x-1]+image[y+2][x]+image[y+2][x+1]
以将水平和存储在缓冲区中
- 对于行中的每个像素,计算模糊值,如
image[y][x]=(buffer[previous\u buffer\u row][x]+buffer[current\u buffer\u row][x]+buffer[next\u buffer\u row][x])/9
- 前进到图像中的下一行(
y++
),并旋转缓冲区(previous\u buffer\u row++);如果(previous\u buffer\u row>=3)previous\u buffer\u row=0;
和current\u buffer\u row++;如果(current\u buffer\u row>=3)current\u buffer\u row=0;
要处理左/右边缘,您需要“剥离”第一次迭代的“for each pixel in row”循环,然后
| 1 2 1 |
| 2 4 2 |
| 1 2 1 |