Android OpenCV 绘制霍夫线

Posted

技术标签:

【中文标题】Android OpenCV 绘制霍夫线【英文标题】:Android OpenCV Drawing Hough Lines 【发布时间】:2011-12-17 01:31:08 【问题描述】:

我正在尝试在安卓手机上使用 OpenCV 来检测线路。我修改了'Tutorial 1 Basic - 2. Use OpenCV Camera'示例。我也以Hough Line Transform 为例。 然而,我得到了奇怪的数字(至少我认为是奇怪的数字)。 b 在 1000 到 -1000 的范围内。

我不完全理解代码(主要是关于加/减 1000 *(a 或 -b)的部分)。

最后我根本看不到线条。

谁能帮帮我?如果您需要更多信息,也请告诉我。

capture.retrieve(mGray, Highgui.CV_CAP_android_GREY_FRAME);
Imgproc.Canny(mGray, mIntermediateMat, 80, 100);
Imgproc.HoughLines(mIntermediateMat, mLines, 1, Math.PI/180, 100);

Scalar color = new Scalar(0, 0, 255);

double[] data;
double rho, theta;
Point pt1 = new Point();
Point pt2 = new Point();
double a, b;
double x0, y0;
for (int i = 0; i < mLines.cols(); i++)

    data = mLines.get(0, i);
    rho = data[0];
    theta = data[1];
    a = Math.cos(theta);
    b = Math.sin(theta);
    x0 = a*rho;
    y0 = b*rho;
    pt1.x = Math.round(x0 + 1000*(-b));
    pt1.y = Math.round(y0 + 1000*a);
    pt2.x = Math.round(x0 - 1000*(-b));
    pt2.y = Math.round(y0 - 1000 *a);
    Core.line(mIntermediateMat, pt1, pt2, color, 3);


Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2BGRA, 4);

Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);

if (Utils.matToBitmap(mRgba, bmp))
    return bmp;

bmp.recycle();
return null;

【问题讨论】:

你能把完整的代码贴出来吗,谢谢 Giuseppe 【参考方案1】:

我正在使用HoughLineP 在我的框架中查找线条并将它们拉回。

这是我的代码...希望对您有所帮助。

    Mat mYuv = new Mat();
    Mat mRgba = new Mat();
    Mat thresholdImage = new Mat(getFrameHeight() + getFrameHeight() / 2, getFrameWidth(), CvType.CV_8UC1);
    mYuv.put(0, 0, data);
    Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGB, 4);
    Imgproc.cvtColor(mRgba, thresholdImage, Imgproc.COLOR_RGB2GRAY, 4);
    Imgproc.Canny(thresholdImage, thresholdImage, 80, 100, 3);
    Mat lines = new Mat();
    int threshold = 50;
    int minLineSize = 20;
    int lineGap = 20;

    Imgproc.HoughLinesP(thresholdImage, lines, 1, Math.PI/180, threshold, minLineSize, lineGap);

    for (int x = 0; x < lines.cols(); x++) 
    
          double[] vec = lines.get(0, x);
          double x1 = vec[0], 
                 y1 = vec[1],
                 x2 = vec[2],
                 y2 = vec[3];
          Point start = new Point(x1, y1);
          Point end = new Point(x2, y2);

          Core.line(mRgba, start, end, new Scalar(255,0,0), 3);

    

    Bitmap bmp = Bitmap.createBitmap(getFrameWidth(), getFrameHeight(), Bitmap.Config.ARGB_8888);

    if (Utils.matToBitmap(mRgba, bmp))
         return bmp;

【讨论】:

嘿,我想在图像中突出显示的部分添加一个矩阵,你能指导我吗? @Brian ONeil 你能告诉我什么是 getFramHeight() 和 getFramWidth() 方法指的是什么? 在Opencv SDK v3中,你应该使用Imgproc.line而不是Core.line,Core.line已经不存在了。 同样在 OpenCV 3.2(我不确定旧版本)中,您应该迭代 .rows()(而不是 .cols()),然后执行 .get(x,0)(而不是 .get(0,x)) .否则你只会得到第一行。【参考方案2】:

您在mIntermediateMat 图像上画线,但返回mRgba 图像。这就是你看不到线条的原因。

b 的 -1000..1000 范围是正确的。 HoughLines 返回直线角度和距零的距离(又名 rhotheta)。要绘制它们,您需要将它们转换为两个点。 1000 是图像尺寸,如果您要绘制 2000x2000 的图像,请将它们增加到 2000,否则线条将不会穿过整个图像。

HoughLinesHoughLinesP 的算法不同。 HoughLines 只找到穿过整个图像的线条。 HoughLinesP 返回较短的线段。

【讨论】:

【参考方案3】:

这是我的 Visual Studio 代码,希望对您有所帮助。

void drawLines(Mat &input, const std::vector<Vec2f> &lines) 
for (int i = 0; i < lines.size(); i++) 
    float alpha = CV_PI/2-atan(input.rows/input.cols);
    float r_max;
    float r_min;
    float r = lines[i][0];
    float theta = lines[i][1];
    if (theta<alpha || theta>CV_PI-alpha) 
        r_max = input.cols*cos(theta);
        r_min = input.rows*sin(theta);
        if (r > r_max) 
            Point pt1(input.cols, (r - input.cols*cos(theta)) / sin(theta));
            Point pt2((r - input.rows*sin(theta)) / cos(theta), input.rows);
            line(input, pt1, pt2, Scalar(255, 0, 0), 1);
        
        else if (r < r_max && r > r_min) 
            Point pt1(r / cos(theta), 0);
            Point pt2((r - input.rows*sin(theta)) / cos(theta), input.rows);
            line(input, pt1, pt2, Scalar(255, 0, 0), 1);
        
        else 
            Point pt1(r / cos(theta), 0);
            Point pt2(0, r / sin(theta));
            line(input, pt1, pt2, Scalar(255, 0, 0), 1);
        

    
    else 
            r_min = input.cols*cos(theta);
            r_max = input.rows*sin(theta);
            if (r > r_max) 
                Point pt1(input.cols, (r - input.cols*cos(theta)) / sin(theta));
                Point pt2((r - input.rows*sin(theta)) / cos(theta), input.rows);
                line(input, pt1, pt2, Scalar(0, 0, 255), 1);
            
            else if (r < r_max && r > r_min) 
                Point pt1(input.cols, (r - input.cols*cos(theta)) / sin(theta));
                Point pt2(0, r / sin(theta));
                line(input, pt1, pt2, Scalar(0, 0, 255), 1);
            
            else 
                Point pt1(r / cos(theta), 0);
                Point pt2(0, r / sin(theta));
                line(input, pt1, pt2, Scalar(0, 0, 255), 1);
            
    


这是关于我发布的代码的逻辑的 2 个图表。

alpha的解释

r_max && r_min的解释

【讨论】:

尝试更清楚地解释为什么这是问题的答案。

以上是关于Android OpenCV 绘制霍夫线的主要内容,如果未能解决你的问题,请参考以下文章

利用OpenCV的霍夫变换线检测函数HoughLines()得到直线的ρ和θ值后绘制直线的原理详解

OpenCV中的霍夫线变换概率霍夫线变换

OpenCV探索之路:霍夫变换

学习 opencv---(13)opencv霍夫变换:霍夫线变换,霍夫圆变换

opencv识别车道线(霍夫线变换)

opencv —— HoughLinesHoughLinesP 霍夫线变换(标准霍夫线变换多尺度霍夫线变换累积概率霍夫线变换)