I am making a cross platform Java application that uses Computer Vision (OpenCV). I need to receive video from a webcam. Currently using standard OpenCV methods:
VideoCapture videoCapture = new VideoCapture();
videoCapture.open(cameraIndex);
...
videoCapture.read(frame);
Of course, the native OpenCV library is loaded before accessing the camera:
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
The library was built with these arguments:
-D WITH_IPP=OFF \
-D BUILD_opencv_java=ON \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=../../opencv-4.5.3/build/install \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.5.3/modules \
-D BUILD_opencv_python2=OFF \
-D BUILD_opencv_python3=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D BUILD_EXAMPLES=OFF \
-D OPENCV_JAVA_SOURCE_VERSION=1.8 \
-D OPENCV_JAVA_TARGET_VERSION=1.8 \
-D BUILD_SHARED_LIBS=OFF \
-D BUILD_FAT_JAVA_LIB=ON \
-D WITH_MATLAB=OFF \
-D BUILD_ZLIB=OFF \
-D BUILD_TIFF=OFF \
-D BUILD_JASPER=OFF \
-D BUILD_JPEG=OFF \
-D BUILD_PNG=OFF \
-D WITH_JPEG=OFF \
-D WITH_PNG=OFF \
-D WITH_OPENEXR=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_TESTS=OFF \
The camera works on Windows 10 (x64) and Kali Linux (amd64). But but not on macOS.
After videoCapture.open(cameraIndex)
function, an error message appears in the console and the application is closed:
OpenCV: not authorized to capture video (status 0), requesting...
OpenCV: can not spin main run loop from other thread, set OPENCV_AVFOUNDATION_SKIP_AUTH=1 to disable authorization request and perform it in your application.
OpenCV: camera failed to properly initialize!
I tried a lot of things such as export OPENCV_AVFOUNDATION_SKIP_AUTH=0
or Thread.sleep(1000)
after videoCapture.open()
or opening camera in another thread. Also i added Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>Application needs permission to access the camera to capture images</string>
</dict>
</plist>
into src folder of my .jar. But nothing helped.
I have read these:
- https://github.com/opencv/opencv/issues/16255
- https://developer.apple.com/forums/thread/109057
- OpenCV command line app can't access camera under macOS Mojave
- https://answers.opencv.org/question/225281/videocapture-0-does-not-work-in-mac-catalina-the-program-crashed/
and many many other resources but there is still no answer.
I even tried using the OpenPVP-capture-java (https://github.com/openpnp/openpnp-capture-java) library, but that didn't help.
objc[2116]: Class PlatformAVCaptureDelegate is implemented in both /private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/jna-3506402/jna6724263821710587077.tmp (0x14fac7cd8) and /private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/jna-3506402/jna1573965830287255196.tmp (0x14faf9cd8). One of the two will be used. Which one is undefined.
2021-10-09 20:44:39.093 java[2116:99975] Requesting permission, bundle path for Info.plist: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/bin
zsh: abort java -Djava.library.path=. -jar CamTest.jar
In the system settings, the terminal has access to the camera. Also, there is a problem with the camera on Ubuntu (after videoCapture.open()
, the program freezes). But this is a topic for another question.
Is there a way to access the camera for OpenCV (Java) on macOS? Perhaps using some kind of third party cross platform library ...
CodePudding user response:
Again I answer my own question...
Thanks @ChristophRackwitz! After your question whether the camera works in python, I checked it (I don't know why I didn't do it before). And so, the camera in python (with opencv-contrib-python) works without problems, so I realized that the problem was with Java (JDK) itself.
I have JDK 8 installed with this commands:
brew tap adoptopenjdk/openjdk
brew install --cask adoptopenjdk8
So, my JAVA_HOME was /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
I don’t know if it’s broken Java or something else, but when I installed Java11 with: brew install java11
and set JAVA_HOME
to /usr/local/Cellar/openjdk@11/11.0.12/
It's finally working!
I spent so much time on this and the solution is just in the wrong Java version... This is strange, because my application (and .jar file) was compiled with JDK 8. And on other operating systems (Windows, Linux) everything works without problems with Java 8. Anyway, now when I start the application from the terminal, it requests access to the camera and everything works fine!