You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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空间绘制直线的思路

  1. 提取累加器峰值:遍历Hough累加器,找出值超过设定阈值的点(rho, theta),这些点对应图像中的直线参数。阈值可根据图像实际情况调整,比如取最大值的60%-80%。
  2. 转换为图像空间直线方程:
    • 当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范围内),然后连接这些点形成线段。
  3. 在图像上绘制直线:在原始图像或边缘检测结果图像中,将计算得到的直线坐标点设置为高亮(如255),完成直线绘制。

内容的提问来源于stack exchange,提问作者Shreenidhi B k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:45:30