使用C实现Hough变换处理2D Raw图像时输出为0KB的问题排查
Hough变换实现问题排查与修正
我尝试用C语言实现Hough算法处理2D Raw图像,代码可分别输出边缘检测和Hough变换结果。边缘检测输出正常,但Hough变换的raw图像大小为0KB,不清楚错误所在,恳请帮忙修正,并给出基于Hough空间绘制直线的思路。
原始代码
#include <stdio.h> #include <math.h> #define PI 3.14159265 void hough_transform(unsigned char out[256][256], unsigned char h_out[][256], int w, int h) { int i, j; int thetaDeg; float thetaRad; int rho; int distMax; int thetamax; distMax = sqrt((h * h) + (w * w)); thetamax = 360; int Acc[180][180]; for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { if (out[i][j] > 0) { for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) { thetaRad = thetaDeg * (PI / 180); rho = i * cos(thetaRad) + j * sin(thetaRad); // find rho value that is closest to this if (distMax < rho) { int min = abs(rho - distMax); } if (distMax <= 1) { // Increment a value in an accumulator array Acc[rho][thetaDeg] += 1; } } } } } for (rho = 0; rho < distMax; rho++) { for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) { h_out[rho][thetaDeg] = Acc[rho][thetaDeg]; } } } void edge_detect(unsigned char input[256][256], unsigned char out[][256], int width, int height) { int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} }; int pixel; int i; int j; int x; int y; for (y = 1; y < height - 1; y++) { for (x = 1; x < width - 1; x++) { pixel = 0; for (j = -1; j <= 1; j++) { for (i = -1; i <= 1; i++) { pixel += in[j + 1][i + 1] * input[y + j][x + i]; } } out[y][x] = (unsigned char) abs(pixel); } } } int main() { FILE *fp; FILE *fp1; FILE *fp2; unsigned char input[256][256]; unsigned char out[256][256]; unsigned char h_out[256][256]; int width = 256; int height = 256; fp = fopen("Image.raw", "rb"); fp1 = fopen("output.raw", "wb"); fp2 = fopen("h_output.raw", "wb"); fread(input, 256 * 256, 1, fp); edge_detect(input, out, width, height); hough_transform(out, h_out, width, height); fwrite(out, 256 * 256, 1, fp1); fwrite(h_out, 256 * 256, 1, fp2); fclose(fp); fclose(fp1); fclose(fp2); return (0); }
错误排查与修正
1. 累加器初始化与大小错误
- 原代码中
int Acc[180][180];未初始化,内存值为随机垃圾数据;且尺寸远不足:distMax≈362(256×256图像的对角线长度),theta覆盖0-359度,累加器至少需要[2*distMax][360]的大小(处理rho正负值)。 - 修正:初始化累加器为0,调整尺寸为足够容纳所有rho和theta值。
2. Rho值的正负偏移处理
- 公式
rho = i*cosθ + j*sinθ计算出的rho会出现负数,无法直接作为数组下标。需添加偏移量rho_offset = distMax,将rho范围从[-distMax, distMax]转换为[0, 2*distMax]。
3. 无效条件判断导致累加器未更新
- 原代码中
if (distMax < rho)和if (distMax <= 1)都是逻辑错误:distMax≈362,distMax <=1永远不成立,导致累加器完全没有被更新,最终写入文件的数据无意义。需删除这两个无效判断,直接累加有效rho对应的计数。
4. 数组越界问题
- 原代码中
h_out是[256][256],但循环中rho遍历到distMax(≈362),超出了h_out的行下标范围,导致内存越界,引发程序异常(如写入文件失败,生成0KB文件)。需调整h_out的尺寸,或对累加器值进行缩放后适配256×256的输出。
修正后的Hough变换函数
void hough_transform(unsigned char out[256][256], unsigned char h_out[256][256], int w, int h) { int i, j; int thetaDeg; float thetaRad; int rho; int distMax = sqrt((h * h) + (w * w)); int thetamax = 360; int rho_offset = distMax; // 偏移量处理负rho // 初始化累加器,尺寸足够容纳所有rho和theta int Acc[2*363][360] = {0}; // distMax≈362,所以2*363覆盖所有可能rho for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { if (out[j][i] > 0) { // 修正i/j对应图像的x/y索引 for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) { thetaRad = thetaDeg * (PI / 180.0); rho = (int)(i * cos(thetaRad) + j * sin(thetaRad) + 0.5); // 四舍五入减少误差 int acc_rho = rho + rho_offset; // 确保下标在累加器范围内 if (acc_rho >= 0 && acc_rho < 2*distMax && thetaDeg >=0 && thetaDeg < thetamax) { Acc[acc_rho][thetaDeg]++; } } } } } // 找到累加器的最大值,用于缩放至0-255范围 int max_val = 0; for (int r = 0; r < 2*distMax; r++) { for (int t = 0; t < thetamax; t++) { if (Acc[r][t] > max_val) max_val = Acc[r][t]; } } // 将累加器值缩放到0-255,适配h_out的256×256尺寸 float scale = (max_val == 0) ? 0 : 255.0 / max_val; for (int r = 0; r < 256; r++) { for (int t = 0; t < 256; t++) { // 映射累加器的rho和theta到256×256的输出 int acc_r = (int)((r / 255.0) * 2*distMax); int acc_t = (int)((t / 255.0) * thetamax); h_out[r][t] = (unsigned char)(Acc[acc_r][acc_t] * scale); } } }
基于Hough空间绘制直线的思路
- 提取累加器峰值:遍历Hough累加器,找出值超过设定阈值的点
(rho, theta),这些点对应图像中的直线参数。阈值可根据图像实际情况调整,比如取最大值的60%-80%。 - 转换为图像空间直线方程:
- 当
theta接近0°或180°(垂直直线):直线为x = rho / cos(theta),在图像y轴范围内(0到255)绘制垂直线段。 - 当
theta接近90°或270°(水平直线):直线为y = rho / sin(theta),在图像x轴范围内(0到255)绘制水平线段。 - 一般情况:使用直线的斜截式
y = (-cos(theta)/sin(theta))*x + rho/sin(theta),遍历x从0到255,计算对应的y值(需确保y在0-255范围内),然后连接这些点形成线段。
- 当
- 在图像上绘制直线:在原始图像或边缘检测结果图像中,将计算得到的直线坐标点设置为高亮(如255),完成直线绘制。
内容的提问来源于stack exchange,提问作者Shreenidhi B k
相关产品推荐
相关产品推荐

