7

I'm currently trying to detect whether a level crossing barrier has been deployed on an image using HoughLines in OpenCV. I thought my code would draw a line on my image, so long as the barrier appears in it - but instead I get an error message saying "Mat data type is not compatible". Can show me how to detect lines in Java with OpenCV?

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);

}

}
Zetland
  • 569
  • 2
  • 11
  • 25

3 Answers3

9

The lines are returned in the lines matrix, which has two columns in which each line returns the rho and theta parameters of the polar coordinates. These coordinates refer to the distance between the top-left corner of the image and the line rotation in radians, respectively. So, in order to use the show method you must create a Mat that will represent the lines using the line coordinates.

  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;
}

And this is a easier way to do it. It involve the Imgproc.HoughLinesP method.

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;
}
Iordache Laur
  • 103
  • 1
  • 8
  • 2
    lines are returned in rows not columns - therefore use `lines.cols()` in loop and `lines.get(i, 0)` – coyer May 31 '19 at 14:42
1

in Android or Java its the same idia.you must to do it in for (); to get the theta and row after you get start point and the end point ,you can core the line.(core.line) but dont forget to transfer the mat that you get the values from her to other. after this>>release the mat. hope thats its help u. r.i enjoy

reffael i
  • 11
  • 3
-1

Edit: See lordache's answer which is Java specific.

Useful reading: How are two-element vector represented in a OpenCV Mat in Java?


Check this tutorial and look for the section "Standard Hough Line Transform".

lines should not be a cv::Mat, but a std::vector<cv::Vec2f> lines; that later on you can visualize with a code like the one showed in the link:

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);
}
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 3
    Thanks for this. Is there any chance you could write it in Java though? That's the trouble I'm having - almost all the tutorials are for C++ or Python... – Zetland Apr 08 '15 at 13:35
  • @Zetland Interesting. Where's the Java interface defined? In fact it's not documented at all on OpenCV guide. Besides, I haven't written in Java for ages, I won't be able to support you in the translation. – Antonio Apr 08 '15 at 13:40
  • I don't know if it's defined anywhere. It's very annoying. I'm having to use it for my course... – Zetland Apr 08 '15 at 13:48
  • @Zetland You have something here: http://docs.opencv.org/java/. You can search it in google by using ` site:http://docs.opencv.org/java/`. For example I can get to [this function description](http://docs.opencv.org/java/2.4.2/org/opencv/imgproc/Imgproc.html#HoughLines%28org.opencv.core.Mat,%20org.opencv.core.Mat,%20double,%20double,%20int%29). You are right, `lines` are returned as a `Mat` (not something you can draw though), but the documentation on the parameter is stubbornly the same of the C++ interface. You should inform your teacher about how poor is the documentation. – Antonio Apr 08 '15 at 14:00
  • 1
    @Zetland I have posted [this question](http://stackoverflow.com/questions/29517069/how-are-two-element-vector-represented-in-a-mat-in-java) – Antonio Apr 08 '15 at 14:13
  • 1
    @Zetland I got an answer to [the question](http://stackoverflow.com/questions/29517069/how-are-two-element-vector-represented-in-a-mat-in-java), can you let me/him know if it works? – Antonio Apr 10 '15 at 13:13
  • @Octopus Sure, at the time there was nobody able to support OP in Java, then (years after) lordache's answer came. – Antonio Dec 14 '18 at 23:14