C语言实现数独检测的Hough Transform负Rho索引问题求助
问题核心原因
- 角度单位不匹配:C标准库的
cos()、sin()函数输入要求为弧度,你当前直接传入0-180的整数角度值,会导致三角函数计算结果完全错误,这是你得到异常负Rho值的主要诱因。 - Rho取值范围未做偏移处理:极坐标定义下,Rho的合法取值范围是
[-max_rho, max_rho],其中max_rho为图像对角线长度,直接用原始Rho作为数组索引必然会出现负数越界问题。
具体解决方案
步骤1:修改累加器数组定义,增加偏移量
将累加器的Rho维度扩展为2 * max_rho + 1,偏移量固定为max_rho,计算得到的原始Rho值加上偏移量后,即可转换为0到2*max_rho的非负索引。
步骤2:角度转弧度后再传入三角函数计算
遍历角度时先将角度值转换为弧度,再代入Rho计算公式。
步骤3:调整Rho计算逻辑,避免类型溢出
先用浮点类型存储计算得到的原始Rho值,四舍五入后再加偏移得到最终的数组索引。
修正后的核心代码片段
#include <math.h> // 需引入数学库,编译时添加-lm参数 void hough(SDL_Surface* image_surface) { unsigned int width = image_surface->w; unsigned int height = image_surface->h; double max_rho = sqrt(width * width + height * height); int rho_offset = (int)max_rho; int rho_size = 2 * rho_offset + 1; // 覆盖[-max_rho, max_rho]范围 int theta_size = 180; // 建议用动态分配避免栈溢出,原可变长度数组兼容性差且栈空间有限 unsigned int** acc_array = (unsigned int**)malloc(rho_size * sizeof(unsigned int*)); for (int i = 0; i < rho_size; i++) { acc_array[i] = (unsigned int*)calloc(theta_size, sizeof(unsigned int)); } Uint32 pixel; Uint8 r, g, b; //遍历所有像素 for (size_t x = 0; x < width; x++) { for (size_t y = 0; y < height; y++) { pixel = get_pixel(image_surface, x, y); SDL_GetRGB(pixel, image_surface->format, &r, &g, &b); //判断为白色像素 if (r+g+b == 765) { //遍历所有角度,转弧度后计算 for (int t = 0; t < theta_size;t++) { double rad = t * M_PI / 180.0; double raw_rho = x * cos(rad) + y * sin(rad); int rho_idx = (int)round(raw_rho) + rho_offset; // 做边界校验避免极端情况越界 if (rho_idx >=0 && rho_idx < rho_size) { acc_array[rho_idx][t]++; } } } } } // 后续逻辑处理完后记得释放动态分配的内存 for (int i = 0; i < rho_size; i++) { free(acc_array[i]); } free(acc_array); //后续代码省略... }
额外注意点
- 编译时需要添加
-lm参数链接数学库,否则会找不到cos、sin、M_PI等定义。 - 如果追求更高的检测精度,可以将角度步长缩小(比如0.5度一步),对应调整theta_size即可。
内容的提问来源于stack exchange,提问作者Hungry
相关产品推荐
相关产品推荐

