OpenCV - Java: VideoCapture read frame hangs with usb camera - java

I'm quite new to OpenCV - Java programming, and I'm trying to setup an application to read video frames from USB WebCam, to start with something.
This is the document I followed up to now: https://opencv-java-tutorials.readthedocs.io/en/latest/03-first-javafx-application-with-opencv.html#video-capturing
The setup is the following:
Java version: 10.0.1
OpenCV Version: 3.3.4 and 3.2.0, same error with both versions
OS: Windows 10 x64
The .dll is placed under C:\Windows, that is included in my java.library.path
I have some additional frameworks involved in the application, but I prepared an isolated test case to better check the issue:
import org.junit.Test;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.videoio.VideoCapture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CVCaptureTest {
private static final Logger LOG = LoggerFactory.getLogger(CVCaptureTest.class);
#Test
public void testFrameRead() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture capture = new VideoCapture();
capture.open(0);
for (int i = 0; i < 100; i ++) {
if (capture.isOpened()) {
Mat frame = new Mat();
LOG.info("Capture open. Reading frame...");
capture.retrieve(frame);
LOG.info("Captured: {}", frame.dump());
}
}
}
}
Output:
[INFO] Running i.m.r.b.r.c.CVCaptureTest
20:15:57.757 [main] INFO i.m.r.b.r.c.CVCaptureTest - Capture open. Reading frame...
After this log line the program just hangs, without throwing any exception.
Any help on understanding the cause of the freeze is welcome.
Thanks & Regards,
Mattia!

Try to use the capture.read(frame);.

Related

What is ImageIO doing when reading a file?

I am a bit confused by ImageIO.read(file). When I try to read a .png file into a BufferedImage, at least on macOS, the focus moves to a new application named after my main class. It appears in the Menu bar. It does so even when I run java from the command line.
The annoying thing is that it moves the focus out of my IDE and I have to return to it manually.
I looked at the source of ImageIO.read(file). I discovered that it is calling ImageIO.createImageInputStream(file) and that is what triggers this behaviour.
My question is: what is ImageIO doing actually, why is my main class showing in the Menu bar when it is just loading information in memory. And most important, how can I avoid it?
Below the code to show the problem. Use any .png to test it.
package misc;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.io.IOException;
public class ReadImageTest {
public static void main(String[] args) {
try {
File file = new File("out/production/resources/picture.png");
long time = System.currentTimeMillis();
ImageInputStream stream = ImageIO.createImageInputStream(file);
long delay = System.currentTimeMillis() - time;
System.out.println("stream: " + stream.length());
System.out.println("time: " + delay/1000.0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using Headless Mode in the Java SE Platform describes what is headless mode and how to use it properly.
Headless mode is a system configuration in which the display device,
keyboard, or mouse is lacking. Sounds unexpected, but actually you can
perform different operations in this mode, even with graphic data.
You can enable it by adding below option to your program:
-Djava.awt.headless=true
See also:
What is the benefit of setting java.awt.headless=true?
How can I prevent command line java processes from stealing focus in OSX?
Setting java.awt.headless=true programmatically

Unable to open DISPLAY with JavaFX on ubuntu server

I have a simple Application which generates a png of a chart which is based on JavaFX. The app fails to run on displayless machine with the following exception, I don't need to render or display content on the console, just need to create the image.
"main" java.lang.UnsupportedOperationException: Unable to open DISPLAY
at com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:68)
at com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
at com.sun.glass.ui.Application.run(Application.java:146)
at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:257)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:211)
at javafx.embed.swing.JFXPanel.initFx(JFXPanel.java:215)
at javafx.embed.swing.JFXPanel.<init>(JFXPanel.java:230)
I'm trying to run this on a AWS instance. Is there a way to overcome this issue? Following is my sample code.
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
public class Test {
public static void main(String[] args) {
String chartGenLocation = "/Users/tmp";
new JFXPanel();
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Failed", 10),
new PieChart.Data("Skipped", 20));
final PieChart chart = new PieChart(pieChartData);
chart.setAnimated(false);
Platform.runLater(() -> {
Stage stage = new Stage();
Scene scene = new Scene(chart, 500, 500);
stage.setScene(scene);
WritableImage img = new WritableImage(500, 500);
scene.snapshot(img);
File file = new File(Paths.get(chartGenLocation, "a.png").toString());
try {
ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", file);
} catch (IOException e) {
//logger.error("Error occurred while writing the chart image
}
});
}
}
I have seen few SO answers which mostly talk about monocle and testfx, here I'm unable to add external dependencies. So adding testfx is not a option. I have also tried the following with xvbf, which hangs the system,
Xvfb :95 -screen 0 1024x768x16 &> xvfb.log &
export DISPLAY=:95.0
When I execute I see the following output and system hangs there.
(process:13112): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.
Fontconfig warning: ignoring UTF-8: not a valid region tag
Update
Execution Sequence
Xvfb :92 -screen 0 1024x768x16 &> xvfb.log &
export DISPLAY=:92.0
No errors in xvbf.log, seems to start properly.
java Test
I see following in console out
(process:13356): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.
Fontconfig warning: ignoring UTF-8: not a valid region tag
I do not see any log in xvbf.log, the execution doesn't proceed after the above log. My image is not getting generated.
Update 2
I would like to know if there is a way to bypass this validation since I really don't need a display rendering.
I hit the same JavaFX issue on Ubuntu server using xvfb as the display manager for my UI tests, the root cause for me was my forwarded DISPLAY wasn't injected into dbus's activation environment, so anything that dbus activates that tries to present a UI failed to connect to a display and resulted in the "Unable to open DISPLAY" exception.
Running dbus-update-activation-environment --systemd DISPLAY XAUTHORITY in that shell before launching the UI tests fixed this issue for me.

Can the package "org.opencv.core.Mat" be used for a simple Java program?

I'm trying to do some operations with a Matrix in Java using opencv. I'm using Eclipse Kepler IDE.
The problem happens when I try to declare a new matrix with the constructor, then I get the following error in the console:
Exception in thread "main" java.lang.UnsatisfiedLinkError:
org.opencv.core.Mat.n_Mat(III)J
at org.opencv.core.Mat.n_Mat(Native Method)
at org.opencv.core.Mat.<init>(Mat.java:477)
I'm using OpenCV 2.4.8 for OSX, OSX 10.9.1 and Eclipse Kepler.
Here is my Code:
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
public class FisherFaces {
public static void main(String[] args) {
Size s = new Size(new double[] {3,3});
Mat g= new Mat(3,3,CvType.CV_8UC1);
}
Is there anything I am doing wrong to cause this error?
I found the problem, I wasn't loading the native libraries, adding the line below fixes it.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

How to open and process a video file like .mpeg or .avi using openCV's VideoCapture method in Java

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
import org.opencv.imgproc.Imgproc;
public class Video
{
public static void main(String[] args)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture cap = new VideoCapture(0);
cap.open(1);
if(!cap.isOpened())
{
System.out.println("No camera");
}
else
{
System.out.println("Yes. Camera");
}
Mat frame = new Mat();
cap.retrieve(frame);
Highgui.imwrite("me1.jpg", frame);
Mat frameBlur = new Mat();
Imgproc.blur(frame, frameBlur, new Size(5,5));
Highgui.imwrite("me2-blurred.jpg", frameBlur);
Imgproc.GaussianBlur(frame, frameBlur, new Size(25, 25), 20);
Highgui.imwrite("me3-blurred.jpg", frameBlur);
cap.release();
}
}
I have used this code to open my Camera device and capture 3 different frames and made some operations on it. But, I couldn't open a file like .avi/.mpg/.mp4 etc., using {n_open} method of VideoCapture. There is a method in the VideoCapture implementation here. But because its a private and native method, that method can't be accesses using VideoCapture's object.
Could some one help how to do that using pure OpenCV 2.4.6 and Java
(Please dont suggest solution using Processing libraries)
Take a look on OpenCV 2.4.8. The VideoCapture API has been extended of public VideoCapture(String filename) method.
The question remains why this feature has been implemented so late.
If using of recent version of OpenCV isn't acceptable for you for some reason, you have several options:
Rebuild OpenCV by yourself with this method marked as public
HACKY ONE: Make your copy of VideoCapture class (or extend original one and play with reflection) with public VideoCapture(String) constructor. Then give support for native method private static native long n_VideoCapture(java.lang.String filename) by creating your own DLL using C++ OpenCV API. (Tested!)
I run into the same problem and this worked for me:
load the ffmpeg library
System.loadLibrary("opencv_ffmpeg300_64");
Open the file:
VideoCapture vC = new VideoCapture("res/video.mp4");
Copy opencv_ffmpeg300_64.dll from opencv\build\x64\vc11\bin to
opencv\build\java\x64
Please note that 64 and .dll may differ from an OS to another, those are for Windows x64

Java Code Compile Error

I am trying to compile a 4KB Java game called "Left 4K Dead".. anyways, It will compile successfully with the javac G.java command, but when you go to run it using java G it spits back this error at me:
Exception in thread "main" java.lang.NoSuchMethodError: main
Anyone know how to make this work? Thanks :)
Beginning of code:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
public class G extends Applet implements Runnable
{
private boolean[] k = new boolean[32767];
private int m;
public void start()
{
enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
new Thread(this).start();
}
public void run()
{
BufferedImage image = new BufferedImage(240, 240, BufferedImage.TYPE_INT_RGB);
Graphics ogr = image.getGraphics();
Exception in thread "main" java.lang.NoSuchMethodError: main
This exception indicates exactly what it states, there is no main method, so the program cannot start.
The issue with the Left 4k Dead code is it is an applet. It expects to be compiled and then run from a webpage, not run from command line (i.e. you can't run it with the command java). If you wish to run it from the command line, you should look into a standalone applet viewer.
After compilation of the class, use
appletviewer <class-name>
to run it through the commandline since it is an applet.
OR ELSE
you can embed it in a browser as CodeMaker suggests.

Categories