如何在OpenCV(Java)中使用HoughLines检测行?

时间:2015-04-07 13:52:08

标签: java opencv

我目前正试图使用​​HoughLines中的OpenCV检测是否已在图像上部署了水平穿越障碍物。我认为我的代码会在我的图像上画一条线,只要屏障出现在其中 - 但我得到一条错误消息说" Mat数据类型不兼容"。可以告诉我如何使用OpenCV检测Java中的行吗?

public class DetectLines {

public static void main(String args[]) {

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

    Mat eventless = Highgui.imread("files/eventless.png");
    Mat barrier = Highgui.imread("files/barrier/lc-00201.png");
    Mat difference = new Mat();
    Mat lines = new Mat();

    Core.absdiff(eventless, barrier, difference);

    Mat grey = new Mat();
    Imgproc.cvtColor(difference, grey, Imgproc.COLOR_BGR2GRAY);

    Imgproc.HoughLines(grey, lines, 5.0, 4.0, 7);

    Imshow ims1 = new Imshow("Lines");
    ims1.showImage(lines);

}

}

3 个答案:

答案 0 :(得分:9)

这些线在行矩阵中返回,该矩阵有两列,其中每一行返回极坐标的rho和theta参数。这些坐标分别指的是图像的左上角和以弧度为单位的线旋转之间的距离。因此,为了使用show方法,您必须创建一个Mat,它将使用线坐标表示线。

  public Mat getHoughTransform(Mat image, double rho, double theta, int threshold) {
    Mat result = Image.getInstance().getImage().clone();
    Mat lines = new Mat();
    Imgproc.HoughLines(image, lines, rho, theta, threshold);

    for (int i = 0; i < lines.cols(); i++) {
        double data[] = lines.get(0, i);
        double rho1 = data[0];
        double theta1 = data[1];
        double cosTheta = Math.cos(theta1);
        double sinTheta = Math.sin(theta1);
        double x0 = cosTheta * rho1;
        double y0 = sinTheta * rho1;
        Point pt1 = new Point(x0 + 10000 * (-sinTheta), y0 + 10000 * cosTheta);
        Point pt2 = new Point(x0 - 10000 * (-sinTheta), y0 - 10000 * cosTheta);
        Imgproc.line(result, pt1, pt2, new Scalar(0, 0, 255), 2);
    }
    return result;
}

这是一种更简单的方法。它涉及Imgproc.HoughLinesP方法。

public Mat getHoughPTransform(Mat image, double rho, double theta, int threshold) {
    Mat result = Image.getInstance().getImage().clone();
    Mat lines = new Mat();
    Imgproc.HoughLinesP(image, lines, rho, theta, threshold);

    for (int i = 0; i < lines.cols(); i++) {
        double[] val = lines.get(0, i);
        Imgproc.line(result, new Point(val[0], val[1]), new Point(val[2], val[3]), new Scalar(0, 0, 255), 2);
    }
    return result;
}

答案 1 :(得分:1)

在Android或Java中它的idia.you必须在for()中执行; 获得theta和row 在得到起点和终点之后,你可以核心这条线。(core.line) 但是别忘了将你从她那里获得价值的垫子转移给其他人。 在此之后&gt;&gt;释放垫子。 希望对你有所帮助。 r.i 享受

答案 2 :(得分:-1)

编辑:请参阅特定于Java的lordache's answer

有用的阅读:How are two-element vector represented in a OpenCV Mat in Java?


检查this tutorial并查找“标准Hough Line变换”部分。

lines不应该是cv::Mat,而是std::vector<cv::Vec2f> lines;稍后您可以通过链接中显示的代码进行可视化:

for( size_t i = 0; i < lines.size(); i++ )
{
  float rho = lines[i][0], theta = lines[i][1];
  Point pt1, pt2;
  double a = cos(theta), b = sin(theta);
  double x0 = a*rho, y0 = b*rho;
  pt1.x = cvRound(x0 + 1000*(-b));
  pt1.y = cvRound(y0 + 1000*(a));
  pt2.x = cvRound(x0 - 1000*(-b));
  pt2.y = cvRound(y0 - 1000*(a));
  line( cdst, pt1, pt2, Scalar(0,0,255), 3, CV_AA);
}