0

I want to use getPerspectiveTransform function, but it only accepts Mat as arguments and I have coordinate data in an array. So I convert them into points and then to Mat as follows:

List<Point> l = new ArrayList<Point>();
for (int i = 0; i < pts_1.length; i++) {
    Point pt = new Point(pts_1[0][i], pts_1[1][i]);
    l.add(i,pt);
}
Mat mat1 = Converters.vector_Point2f_to_Mat(l);
for (int i = 0; i < pts_2.length; i++) {
    Point pt = new Point(pts_2[0][i], pts_2[1][i]);
    l.add(i,pt);
    }
Mat mat2 = Converters.vector_Point2f_to_Mat(l);
Mat perspectiveTransform = Imgproc.getPerspectiveTransform(mat1,mat2);

But when I run my app, then it gives me error 'Something went wrong', and in logcat I am getting the following error:

E/cv::error(): OpenCV Error: Assertion failed (src.checkVector(2, CV_32F) == 4 && dst.checkVector(2, CV_32F) == 4) in cv::Mat cv::getPerspectiveTransform(cv::InputArray, cv::InputArray), file /build/master_pack-android/opencv/modules/imgproc/src/imgwarp.cpp, line 6748
E/org.opencv.imgproc: imgproc::getPerspectiveTransform_10() caught cv::Exception: /build/master_pack-android/opencv/modules/imgproc/src/imgwarp.cpp:6748: error: (-215) src.checkVector(2, CV_32F) == 4 && dst.checkVector(2, CV_32F) == 4 in function cv::Mat cv::getPerspectiveTransform(cv::InputArray, cv::InputArray)

I am new to OpenCV4Android so I don't understand why this is happening. How to fix it? Is there any other better way to do this?

Thanks for help!

Note: I know that a similar procedure is followed here: Can't get OpenCV's warpPerspective to work on Android but he is not getting this error, so I am posting it here.

Ank
  • 1,864
  • 4
  • 31
  • 51
  • @AlexanderReynolds I didn't get you, but my Android studio is telling me that 'Imgproc.getPerspectiveTransform(Mat src, Mat dst)' is the format – Ank Jun 20 '17 at 03:55
  • Sorry---not used to the Java implementation. I see. You have exactly four points? `getPerspectiveTransform` uses exactly four points. If you have more than four points you should use `findHomography()`. – alkasm Jun 20 '17 at 04:10
  • @AlexanderReynolds yup exactly four points – Ank Jun 20 '17 at 04:25
  • 1
    I think the problem then is somehow your `Mat` isn't the correct type (one would assume `vector_Point2f_to_Mat` would do this for you, and examples I can seem to do this fine). Try creating the `Mat` explicitly with the correct type `Mat mat1 = new Mat(4, 1, CvType.CV_32FC2);` and then go on to fill it with `vector_Point2f_to_Mat`. The only thing I see different in others' code is skipping the indexing for `add`, though I don't see how that would affect this at all. – alkasm Jun 20 '17 at 04:56
  • @AlexanderReynolds well i just tried what you suggested, but for mat1 and mat2 android studio is telling me that it is reduntant `Variable 'mat1' initializer 'new Mat(4, 1, CvType.CV_64F)' is redundant. This inspection points out the cases where a variable value is never used after its assignment, i.e.:  - the variable never gets read after assignment OR  - the value is always overwritten with another assignment before the next variable read OR  - the variable initializer is redundant (for one of the above two reasons) OR  - the variable is never used.` – Ank Jun 20 '17 at 05:07
  • @AlexanderReynolds Although it is fine to do this with perspectiveTransform mat. But it still doesn't help as I am still getting the same error. – Ank Jun 20 '17 at 05:08
  • @AlexanderReynolds hey, so I tried to print mat1 and I got this `Mat [ 8*1*CV_32FC2, isCont=true, isSubmat=false, nativeObj=0xffffffffde7ffe40, dataAddr=0xffffffffe0c4b520 ]` Why is it 8*1? shouldn't it be 4*2? – Ank Jun 20 '17 at 05:44
  • Yep that's absolutely the problem. Did you try skipping the add index? I'm wondering if it's putting your points end to end instead of on top of each other. – alkasm Jun 20 '17 at 05:46
  • @AlexanderReynolds I just tried skipping it, but unfortunately it didn't had any effect. mat1 is still 8*1 – Ank Jun 20 '17 at 05:57
  • @AlexanderReynolds finally got the solution! problem was we can't use the same 'l' variable for both mat1 and mat2. As it will just append points for mat2 at the end if we don't use index, and if we do use the index then it will just push points for mat1 at the end and add points for mat2 in the beginning. Either way mat1 will be 4*1 and mat2 will be 8*1. And this can be avoided simply by using some other variable for mat2. – Ank Jun 20 '17 at 06:10
  • @AlexanderReynolds please post the answer as you will write better than me. Thanks! – Ank Jun 20 '17 at 06:43
  • 1
    Ah brilliant, that was such an obvious but hard to find catch. I'll go for it, but you did the work! – alkasm Jun 20 '17 at 07:09

1 Answers1

1

As mentioned in the comment discussion on OP's post (all credit to them), the problem lies with the list l:

List<Point> l = new ArrayList<Point>();
for (int i = 0; i < pts_1.length; i++) {
    Point pt = new Point(pts_1[0][i], pts_1[1][i]);
    l.add(i,pt);
}
Mat mat1 = Converters.vector_Point2f_to_Mat(l);

If we take a look at the contents of the List<Point> l:

for (Point pt : l)
    System.out.println("(" + pt.x + ", " + p.ty + ")");

(x0, y0)
(x1, y1)
(x2, y2)
(x3, y3)

And moving onto the next matrix:

for (int i = 0; i < pts_2.length; i++) {
    Point pt = new Point(pts_2[0][i], pts_2[1][i]);
    l.add(i,pt);
    }
Mat mat2 = Converters.vector_Point2f_to_Mat(l);

Taking another look at the contents of the List<Point> l:

for (Point pt : l)
    System.out.println("(" + pt.x + ", " + p.ty + ")");

(x4, y4)
(x5, y5)
(x6, y6)
(x7, y7)
(x0, y0)
(x1, y1)
(x2, y2)
(x3, y3)

So this is the culprit; your second matrix will have 8 points in it.

From the Java docs for ArrayList:

Parameters: index - index at which the specified element is to be inserted

Using l.add will insert and not overwrite the old list. So the solution would be to make a new list for each transformation matrix.

alkasm
  • 22,094
  • 5
  • 78
  • 94