bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.56k stars 1.58k forks source link

How can I draw a rotated Rectangle? #1556

Open abuech2s opened 3 years ago

abuech2s commented 3 years ago

Hello,

Sorry for my question: How can I draw a rotated Rectangle?

Thanks Alex

saudet commented 3 years ago

https://docs.opencv.org/master/db/dd6/classcv_1_1RotatedRect.html

abuech2s commented 3 years ago

Hi,

Yes, I found the example as well. But for me there is a difference:

In this example there is an array of Point2f instantiated and the input parameter of the points-method is this array. So we store 4 points within this array and draw the lines. While using org.bytedeco.opencv.opencv_core.RotatedRect there is the points-method with just a single Point2f instance as the input parameter. How can I draw here a RotatedRect?

Thanks a lot for your fast support. Alex

saudet commented 3 years ago

Point2f is a pointer, so it can be used for native arrays, that's fine.

abuech2s commented 3 years ago

I am sorry, I am completely not familiar with all this "pointer-stuff". This is approach so far:

Point2f rectPoints = new Point2f(4);
rotRect.points(rectPoints);
for (int j = 0; j < 4; j++) {
    line(roi, rectPoints.get(j), rectPoints.get((j+1) % 4), color);
}

The get(idx) will just return a "float". Maybe the solution is too simple, but I really dont see the clue here of how to address the 4 points to draw them ...

PS: Do I have to replace the get() with position() ?

abuech2s commented 3 years ago

Found your answer here a while ago. I think this addresses my question: https://groups.google.com/g/javacv/c/uN1gB85yTlk?pli=1

But in my opinion, that's not pretty intuitive...

saudet commented 3 years ago

This works and is pretty "intuitive" I find:

Point2f rectPoints = new Point2f(4);
rotRect.points(rectPoints);
for (int j = 0; j < 4; j++) {
    line(roi, rectPoints.getPointer(j), rectPoints.getPointer((j+1) % 4), color);
}

How else would you expect this to be mapped?

abuech2s commented 3 years ago

Based on the example of groups.google-link (over float[]-coordinates-array).

Your exmaple looks much better here.

Last question for today: Is there a simple way to cast a Point2f to a Point?

Thanks a lot Alex

saudet commented 3 years ago

Not at the moment. There are conversion cast operators that could be mapped to Point2f.asPoint(), etc, but we'd need someone to work on this...

abuech2s commented 3 years ago

So, in other words: to be able to transfer it, i have to use something, like:

Point p = new Point( (int)rectPoints.getPointer(j).x(), (int)rectPoints.getPointer(j).y() );

Would this be correct?

abuech2s commented 3 years ago

I have compared these two different kind of ways: The values, which are printed out are different. There must be something i am doing wrong:

Point2f rectPoints = new Point2f(4);
rotRect.points(rectPoints);
float[] coordinates = new float[8];
rectPoints.get(coordinates);

If I log the coordinates[idx] with idx from 0 to 7, i will receive my correct 8 coordinates: { 315.5, 219.5, 262.0, 166.0, 313.5, 114.5, 367.0, 168.0 }

If I log it this way here:

log.info(rectPoints.getPointer(0).x());
log.info(rectPoints.getPointer(0).y());
log.info(rectPoints.getPointer(1).x());
log.info(rectPoints.getPointer(1).y());
log.info(rectPoints.getPointer(2).x());
log.info(rectPoints.getPointer(2).y());
log.info(rectPoints.getPointer(3).x());
log.info(rectPoints.getPointer(3).y());

I will receive: {315.5, 219.5, 7.36E-32, -3.7E-34, 3169.7, 1.01E-42, 5.9E-32, -8.9E-42} So, the first two coordinates are correct, the other six are more or less random.

Is there something I did not mention?

Thanks a again, for your help

saudet commented 3 years ago

You're right, there's a problem with Point2f.getPointer(). It's calling Point2f(Point2f) instead of Point2f(Pointer). I've fixed that in commit https://github.com/bytedeco/javacpp/commit/20f677c33e78be6de5885fbc4a8db95c73a9b08b. Please give it a try with opencv-4.5.1-1.5.5-SNAPSHOT: http://bytedeco.org/builds/ Thanks for reporting!

abuech2s commented 3 years ago

I have added these two repositories based on the snapshot page and changed the version of opencv-platform to:

<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.5-SNAPSHOT</version>
</dependency>

After building the project on this version, everything is completly slowed down (compared to 1.5.4). The initialization of the library at the beginning needs ~2min (instead of ~10s based on 1.5.4).

Furthermore the Pointer problem still exists. I am not sure if thats a difference, but i am using getPointer(long idx) instead of getPointer().

PS: If I replaced the version to 1.5.4 everything works fine again (except of the getPointer()-Problem)

saudet commented 3 years ago

Sorry, I had not updated the dependencies of JavaCV itself. Please try again and make sure it's downloading OpenCV 4.5.1! Thanks

After building the project on this version, everything is completly slowed down (compared to 1.5.4). The initialization of the library at the beginning needs ~2min (instead of ~10s based on 1.5.4).

Make sure you're not trying to use GPU versions of algorithms. That will JIT compile kernels, which can take a few minutes.

abuech2s commented 3 years ago

(1) The coordinates are returned correctly, now. Thanks for bug-fixing this. (2) I am very sure, that I don't do anything on GPU or with GPU algorithms. The only change was to switch between 1.5.4 and 1.5.5-SNAPSHOT in pom.xml. The difference of the init time takes a few minutes now. In this unit test i am just doing standard operations on images (stored in Mat-Objects).

saudet commented 3 years ago

Set the "org.bytedeco.javacpp.logger.debug" system property to "true". It's going to show you everything it's loading. If there's nothing that gets loaded in this 2 minutes by JavaCPP, then it's something OpenCV is doing, and it's probably compiling kernels for your GPU. Make sure to disable GPU support explicitly in OpenCV.

abuech2s commented 3 years ago

Is the correct way of disabling the GPU this here? (found it at some posts)

System.setProperty("org.bytedeco.javacpp.logger.debug", "true");
System.setProperty("OPENCV_OPENCL_DEVICE", "disabled");
System.setProperty("OPENCV_OPENCL_RUNTIME", "null");

Or are there any further env variables for disabling GPU?

Based on the new debug level, i see hundreds of the following lines, like this:

Debug: Loading library cudnn_cnn_train64_8 Debug: Failed to load for cudnn_cnn_train64_8: java.lang.UnsatisfiedLinkError: no cudnn_cnn_train64_8 in java.library.path: [C:\Program Files\AdoptOpenJDK\jdk-11.0.9.101-hotspot\bin, C:\WINDOWS\Sun\Java\bin, C:\WINDOWS\system32, C:\WINDOWS, C:\Program Files\AdoptOpenJDK\jdk-11.0.9.101-hotspot\bin, C:\Windows\system32, "AndSoOn", .]

Compared to 1.5.4: Version 1.5.4 shows the same messages, but it will go to the execution of the unit test much faster ... I have attached the logfiles of a comparison of the two versions. V1.5.4 needed ~1min for initialisation & executing unit test. For the same unit test V1.5.5-SNAPSHOT needed 7 minutes (incl. the init process). comparison.zip

saudet commented 3 years ago

You're right, it did get slower. It's not that slow on my installation of Windows though. Loading OpenCV used to take ~1300 ms, and that increased to ~16 seconds. I've cleaned that up and optimized a bit more in commit https://github.com/bytedeco/javacpp/commit/2ee94b8317ec8e5009950384e3114f546ab094b5. On Windows, this brings it back down to ~1000 ms for me. Please let me know if you end up having other problems with those changes! Thanks

abuech2s commented 3 years ago

Thanks a lot ! Now, with 1.5.5-SNAPSHOT I need ~7s.

I let the ticket open for the enhancement "Point2f -> Point"-Cast. I think all other questions here are resolved.

saudet commented 3 years ago

Work for the conversion cast operators hasn't started, but fixes for the bugs have been released with JavaCV 1.5.5. Enjoy!