C语言方框模糊(Box Blur)代码的RGB取整问题求助
图像方框模糊RGB值取整偏低的问题
我正在完成C语言课程作业,实现图像的方框模糊(Box Blur)功能,但教授指出多数情况下图像的RGB值取整结果低于实际应有的水平。以下是我的代码:
// Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { // Create a copy of image RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } // for every row for (int i=0;i<height;i++) { // for every pixel for (int j=0;j<width;j++) { // initalising colours int blue=copy[i][j].rgbtBlue; int red = copy[i][j].rgbtRed; int green =copy[i][j].rgbtGreen; // initialising turns int tblue=1; int tred=1; int tgreen =1; // if the pixel is between top and 2nd last if ((i>=0)&&(i<=height-2)) { // add the values for the pixel below it blue+=copy[i+1][j].rgbtBlue; red+=copy[i+1][j].rgbtRed; green+=copy[i+1][j].rgbtGreen; // add a turn tblue++; tred++; tgreen++; // if the pixel is between left adn 2nd last if ((j>=0)&&(j<=width-2)) { // add the avlue of right side below it blue+=copy[i+1][j+1].rgbtBlue; red+=copy[i+1][j+1].rgbtRed; green+=copy[i+1][j+1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } // if the pixel is between right and 2nd if ((j<=height-1)&&(j>=1)) { // add the values of left side below it blue+=copy[i+1][j-1].rgbtBlue; red+=copy[i+1][j-1].rgbtRed; green+=copy[i+1][j-1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } } // if the pixel is between bottom and 2nd if ((i<=height-1)&&(i>=1)) { // add the values for the pixel above it blue+=copy[i-1][j].rgbtBlue; red+=copy[i-1][j].rgbtRed; green+=copy[i-1][j].rgbtGreen; // add a turn tblue++; tred++; tgreen++; // if the pixel is between left adn 2nd last if ((j>=0)&&(j<=width-2)) { // add the avlue of right side above it blue+=copy[i-1][j+1].rgbtBlue; red+=copy[i-1][j+1].rgbtRed; green+=copy[i-1][j+1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } // if the pixel is between right and 2nd if ((j<=height-1)&&(j>=1)) { // add the values of left side above it blue+=copy[i-1][j-1].rgbtBlue; red+=copy[i-1][j-1].rgbtRed; green+=copy[i-1][j-1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } } // if the pixel is between left and 2nd last if ((j>=0)&&(j<=width-2)) { // add the avlue of the one right of it blue+=copy[i][j+1].rgbtBlue; red+=copy[i][j+1].rgbtRed; green+=copy[i][j+1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } // if the pixel is between right and 2nd if((j<=height-1)&&(j>=1)) { // add the avlue of the one left of it blue+=copy[i][j-1].rgbtBlue; red+=copy[i][j-1].rgbtRed; green+=copy[i][j-1].rgbtGreen; // add a turn tblue++; tred++; tgreen++; } // divide socre by turns and put it in round () image[i][j].rgbtBlue = round(blue/tblue); image[i][j].rgbtRed = round(red/tred); image[i][j].rgbtGreen = round(green/tgreen); } } return; }
问题根源分析
- 整数除法截断问题:代码中
blue/tblue是整数除法,在调用round()之前就已经丢失了小数部分。比如5/2会先得到2,再round还是2,但实际5/2=2.5,round后应该是3,这就直接导致结果偏低。 - 边界判断错误:多处判断中误用了
height来判断列(j)的范围,比如if ((j<=height-1)&&(j>=1)),这里应该用width而不是height,会导致边缘像素的邻域计算错误,进而拉低平均值。 - 冗余计数变量:tblue、tred、tgreen三个变量完全可以合并成一个count变量,因为每个邻域像素对三个通道的计数是一致的,分开统计只会增加代码复杂度。
修复后的代码
// Blur image void blur(int height, int width, RGBTRIPLE image[height][width]) { // Create a copy of image RGBTRIPLE copy[height][width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } // 遍历每个像素 for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int blue = 0, red = 0, green = 0; int count = 0; // 遍历当前像素周围3x3范围内的所有有效像素 for (int di = -1; di <= 1; di++) { for (int dj = -1; dj <= 1; dj++) { int ni = i + di; int nj = j + dj; // 判断邻域像素是否在图像范围内 if (ni >= 0 && ni < height && nj >= 0 && nj < width) { blue += copy[ni][nj].rgbtBlue; red += copy[ni][nj].rgbtRed; green += copy[ni][nj].rgbtGreen; count++; } } } // 先做浮点除法再取整,避免整数截断 image[i][j].rgbtBlue = round((double)blue / count); image[i][j].rgbtRed = round((double)red / count); image[i][j].rgbtGreen = round((double)green / count); } } return; }
修复说明
- 解决整数截断问题:将
blue等整数强制转换为double类型后再做除法,确保小数部分被保留,之后用round()进行正确的四舍五入,避免结果偏低。 - 简化邻域遍历逻辑:用两层循环遍历当前像素周围的3x3区域,通过坐标判断筛选有效像素,彻底修复了原代码中用height判断列范围的错误,同时大幅简化了边界条件。
- 合并计数变量:使用单个
count变量统计有效邻域像素的数量,减少代码冗余,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Daksh Punia
相关产品推荐
相关产品推荐

