【问题标题】:HoughLinesP not detecting lines OpenCV androidHoughLinesP没有检测线OpenCV android
【发布时间】:2015-07-30 17:47:08
【问题描述】:

我正在使用适用于 Android 的 OpenCV 3.0。我有一张图像,我想在其中检测圆形表盘内的手的角度。为此,我正在使用HoughLinesP 来检测手部。 这是代码。

Mat imgSource = new Mat(), imgCirclesOut = new Mat(),imgLinesOut=new Mat();
//grey opencv
Imgproc.cvtColor(Image, imgSource, Imgproc.COLOR_BGR2GRAY);
Imgproc.GaussianBlur( imgSource, imgSource, new Size(9, 9), 2, 2 );

int threshold = 0;
int minLineSize = 0;
int lineGap = 0;

Imgproc.HoughLinesP(imgSource, imgLinesOut, 1, Math.PI/180, threshold, minLineSize, lineGap);
for( int j = 0; i < imgLinesOut.cols(); i++ )
{
    double[] vec=imgLinesOut.get(0,j);
    Point pt1, pt2;
    pt1=new Point(vec[0],vec[1]);
    pt2=new Point(vec[2],vec[3]);
    Imgproc.line( Image, pt1, pt2, new Scalar(0,0,255), 3, Core.LINE_AA,0);
}

但结果是

我需要的是这些圆圈中手的角度。非常感谢有关此问题的任何帮助。提前致谢

编辑 我已经用这个更新了我的代码

 Mat imgSource = new Mat(), imgCirclesOut = new Mat(),imgLinesOut=new Mat();

 Imgproc.GaussianBlur( Image, imgSource, new Size(5, 5), 2, 2 );      
 int threshold = 20;
 int minLineSize = 0;
 int lineGap = 10;
 Imgproc.Canny(imgSource, imgSource, 70, 100);
 Imgproc.HoughLinesP(imgSource, imgLinesOut, 1, Math.PI/180, threshold, minLineSize, lineGap);
for( int j = 0; j < imgLinesOut.cols(); j++ )
{
    double[] vec=imgLinesOut.get(0,j);

    Point pt1, pt2;
    pt1=new Point(vec[0],vec[1]);
    pt2=new Point(vec[2],vec[3]);

    Imgproc.line( imgSource, pt1, pt2, new Scalar(0,0,255), 3, Core.LINE_AA,0);
}

正如@Micka 所建议的,不需要灰度图像(我删除了cvtcolor)。我还将GuassianBlur Size 的值减小到5。我也在图像上添加了 Canny 作为边缘。

生成的模糊图像是

【问题讨论】:

  • 你试过Math.PI/1800吗?
  • @Micka math.PI/1800 将行从最后一圈移到第二圈...
  • 你的问题可能是这一行:for( int j = 0; i &lt; imgLinesOut.cols(); i++ ) 应该改为for( int j = 0; j &lt; imgLinesOut.cols(); j++ )
  • 感谢@Micka 指出这个愚蠢的错误,但这并没有解决问题。蓝线现在在第四圈...
  • 您不应该向函数提供灰度图像,而是提供二进制边缘图像(边缘 = 白色,非边缘 = 黑色)。请尝试计算canny 并将结果作为输入发送到 HoughLinesP。如果您的图像是真实尺寸,那么尺寸为 9 的高斯模糊似乎也有点太大了。您可以将模糊图像添加到您的帖子中吗?计算canny时,也请发布canny图片。

标签: java android opencv


【解决方案1】:

在如此小的图像中检测线可能是个问题,因为您需要很少的点才能正确填充 Hough 累加器。

我建议使用不同的方法:

  1. 分割每个圆圈(表盘)
  2. 提取最大的黑色斑点(手)

下面是这个想法的简单实现。代码是用 C++ 编写的,但您可以轻松地移植到 Java,或者至少用作参考。

#include "opencv2/opencv.hpp"
using namespace cv;

int main(int, char**)
{
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    Mat3b res;
    cvtColor(img, res, COLOR_GRAY2BGR);

    // Find dials
    vector<Vec3f> circles;
    HoughCircles(img, circles, CV_HOUGH_GRADIENT, 1, img.cols/10, 400, 40);

    // For each dial
    for (int i = 0; i < circles.size(); ++i)
    {

        // Segment the dial
        Mat1b dial(img.size(), uchar(255));
        Mat1b mask(img.size(), uchar(0));
        circle(mask, Point(circles[i][0], circles[i][1]), circles[i][2], Scalar(255), CV_FILLED);
        img.copyTo(dial, mask);

        // Apply threshold and open
        Mat1b bin;
        threshold(dial, bin, 127, 255, THRESH_BINARY_INV);
        Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5,5));
        morphologyEx(bin, bin, MORPH_OPEN, kernel);

        // Get min area rect
        vector<Point> points;
        findNonZero(bin, points);
        RotatedRect r = minAreaRect(points);

        // Draw min area rect
        Point2f pts[4];
        r.points(pts);
        for (int j = 0; j < 4; ++j) {
            line(res, pts[j], pts[(j + 1) % 4], Scalar(0, 255, 0), 1);
        }       
    }

    imshow("Result", res);
    waitKey();

    return 0;
}

从这张图片开始:

我在这里找到

【讨论】:

  • 感谢@Miki,您的解决方案有效。我不得不删除CircleHough 和遮蔽部分。应用阈值并在图像上打开,获取轮廓并围绕该对象循环就可以了。再次感谢:)
  • 这是阅读我的项目stackoverflow.com/questions/45215212/… 的仪表的良好开端,但只是一个问题:我如何读取仪表的“值”?谢谢!
【解决方案2】:
for( int j = 0; j < imgLinesOut.size(); j++ )

这将给出向量的大小。遍历该向量

【讨论】:

    猜你喜欢
    • 2020-01-17
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 2016-06-07
    相关资源
    最近更新 更多