CS50边缘检测函数:3x3测试通过但4x4失败,求排查
CS50边缘检测函数4x4图像测试失败问题排查
为CS50编写的Edges边缘检测函数通过了多数测试用例,但4x4及更大尺寸的NxN图像测试未通过,3x3图像运行完全正常,无法定位逻辑差异,寻求技术支持。
原代码
// Detect edges void edges(int height, int width, RGBTRIPLE image[height][width]) { 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++) { edges_helper(height, width, i, j, image, copy); } } return; } void edges_helper(int height, int width, int current_row, int current_column, RGBTRIPLE image[height][width], RGBTRIPLE copy[height][width]) { // 创建当前像素周围的3x3红/绿/蓝值网格,与Gx、Gy卷积后计算新像素值 int red[3][3]; int blue[3][3]; int green[3][3]; int gx[3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}}; int gy[3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}}; create_grids(current_row, current_column, height, width, red, blue, green, copy); int new_red = pow(matrix_multiply(3, 3, gx, red),2) + pow(matrix_multiply(3, 3, gy, red),2); int new_blue = pow(matrix_multiply(3, 3, gx, blue),2) + pow(matrix_multiply(3, 3, gy, blue),2); int new_green = pow(matrix_multiply(3, 3, gx, green),2) + pow(matrix_multiply(3, 3, gy, green),2); image[current_row][current_column].rgbtRed = minimum(round(sqrt(new_red)),255); image[current_row][current_column].rgbtBlue = minimum(round(sqrt(new_blue)),255); image[current_row][current_column].rgbtGreen = minimum(round(sqrt(new_green)),255); return; } // 填充用于与Gx、Gy卷积的3x3红/绿/蓝网格 void create_grids(int current_row, int current_column, int height, int width, int red[height][width], int blue[height][width], int green[height][width], RGBTRIPLE copy[height][width]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (current_row + i - 1 < 0 || current_row + i - 1 >= height || current_column + j - 1 < 0 || current_column + j - 1 >= width) { red[i][j] = 0; blue[i][j] = 0; green[i][j] = 0; } else { red[i][j] = copy[current_row+i-1][current_column+j-1].rgbtRed; blue[i][j] = copy[current_row+i-1][current_column+j-1].rgbtBlue; green[i][j] = copy[current_row+i-1][current_column+j-1].rgbtGreen; } } } } // 两个矩阵相乘并返回结果值 int matrix_multiply(int height, int width, int x[height][width], int y[height][width]) { int sum = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { sum += x[i][j] * y[i][j]; } } return sum; } int minimum(int x, int y) { return ((x<y)? x : y); }
问题根源
问题出在create_grids函数的参数定义上:
- 调用该函数时传入的
red、blue、green是固定3x3大小的数组 - 但函数声明中却将这三个参数定义为
int red[height][width],即尺寸与图像一致的数组
当图像是3x3时,height=3、width=3,参数定义的数组尺寸和传入的数组刚好匹配,内存访问正常;但当图像是4x4时,height=4、width=4,函数会把传入的3x3数组当作4x4数组来访问,导致内存越界,读取到错误的垃圾值,最终计算出错误的像素值。
修复方案
修改create_grids函数的参数,将red、blue、green的类型改为固定的3x3数组,同时同步修改函数声明和定义:
修改后的create_grids函数
// 填充用于与Gx、Gy卷积的3x3红/绿/蓝网格 void create_grids(int current_row, int current_column, int height, int width, int red[3][3], int blue[3][3], int green[3][3], RGBTRIPLE copy[height][width]) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (current_row + i - 1 < 0 || current_row + i - 1 >= height || current_column + j - 1 < 0 || current_column + j - 1 >= width) { red[i][j] = 0; blue[i][j] = 0; green[i][j] = 0; } else { red[i][j] = copy[current_row+i-1][current_column+j-1].rgbtRed; blue[i][j] = copy[current_row+i-1][current_column+j-1].rgbtBlue; green[i][j] = copy[current_row+i-1][current_column+j-1].rgbtGreen; } } } }
额外优化建议
- 用整数乘法替代
pow(val,2),避免浮点数精度风险:比如将pow(val,2)改为val * val - 确保代码包含
<math.h>头文件,避免round、sqrt等函数的编译错误
内容的提问来源于stack exchange,提问作者Aaditya Jain
相关产品推荐
相关产品推荐

