I am a bit confused about the use of JavaCV FFmpegFrameRecorder. I have several byte[] or short[] arrays (depending if my images are 8 or 16 bit) were I have the data related for several images. Now, my idea is to use JavaCPP to send each image to ffmpeg so it creates me a mute video from this collection at the framerate I wish. Up to now I have:
package ffmpeg;
import java.awt.EventQueue;
import java.io.File;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.swing.JFrame;
public class rwa {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
rwa window = new rwa();
window.frame.setVisible(true);
Frame myframe = new Frame();
myframe .imageHeight = 100;
myframe .imageWidth = 200;
myframe .imageChannels = 1;
myframe .imageDepth = 8;
byte[] myimage = new byte[20000];
//all black
for (int j = 0; j<myimage.length; j++){
myimage[j]=-128;
}
File dest = new File("C:\\out.mp4");
FFmpegFrameRecorder record = new FFmpegFrameRecorder(dest, 0);
//FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(dest);
record.setFrameRate(0.04);
record.setVideoCodec(13);
record.setFormat("mp4");
record.setPixelFormat(0);
record.setImageHeight(100);
record.setImageWidth(200);
record.setVideoBitrate(1000000);
record.start();
for (int i=0; i<100; i++){
if (myimage.length*(1+i)<20000) {
//this is just for debugging it. I'm creating a different image each frame to see if it works. In practice, I will read in each step the propper image
for (int j = myimage.length*i; j<myimage.length*(i+1); j++){
myimage[j]=127;
}
}
Buffer[] buf = {ByteBuffer.wrap(myimage)};
myframe.image = buf;
record.recordImage(200, 100, 8, 1, 0, 0, ByteBuffer.wrap(myimage));
//record.record(myframe);
}
record.stop();
record.close();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public rwa() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
But I am getting errors like
A fatal error has been detected by the Java Runtime Environment:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000007fefe4511d3, pid=6432, tid=0x000000000000027c
what is wrong there? And how should I select the bitrate? My images, at maximum, will be 16bit 1 channel 2048*2048 pixels.
Thanks!
You should use Parallel.run() method in JavaCV, when you are using an event/thread.
Related
I am trying to implement Remote FrameBuffer Protocol using Java socket programming.
I have a server side program that takes screenshot of the entire screen using robot and store it in BufferedImage .Then I converted it into a byte array and sending it to the client .
Objective :
To display the entire screen of the server side machine in a Swing GUI of the client side.
Problem i am facing :
i am able to send the image in bytes from server and receive it from the server by the client (client.java) and convert it into a jpg image (output.jpg) using ImageIO and put that image in a Swing frame.
But i am able to see the first image in the Swing and whenever the image gets updated ,the image in the Swing is not updating or refreshing .
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
client.java
package remoteclient;
import java.lang.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class client {
public static void main(String args[])throws Exception{
Socket s=new Socket("localhost",5900);
DataInputStream din=new DataInputStream(s.getInputStream());
DataOutputStream dout=new DataOutputStream(s.getOutputStream());
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int width=0,height=0;
try {
width = din.readInt(); //getting width and height from server thru socket.
height = din.readInt();
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame("Client");
JLabel label = new JLabel();
f.setSize(width, height);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
boolean continueLoop = true;
while(continueLoop)
{
try {
int len = din.readInt();
byte[] imageInByte = new byte[len];
System.out.println(len);
din.readFully(imageInByte);
System.out.println(imageInByte);
ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte);
BufferedImage bImage2 = ImageIO.read(bis);
// Image im1 = bImage2.getScaledInstance(width,height, Image.SCALE_SMOOTH);
ImageIO.write(bImage2, "jpg", new File("output.jpg") );
bImage2 = ImageIO.read(new File("output.jpg"));
label.setIcon(new ImageIcon(im1));
ImageIcon icon = new ImageIcon(bImage2);
icon.getImage().flush();
label.setIcon( icon );
f.getContentPane().add(label, BorderLayout.CENTER);
f.pack();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
What I want :
I want the image to refresh and show updated image every time the server sends the image data .
Updated code with comments about demo code that should be removed from your working code:
Here's an example, using default UIManager icons, and SwingWorker, as noted in the comments to the original posting. You would instead use images from your server connection.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
public class SwingLabelWithUpdatedImage {
public static void main(String args[]) throws Exception {
final JLabel label = new JLabel("", SwingConstants.CENTER);
final JFrame frame = new JFrame("Client");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(label, BorderLayout.CENTER);
final Dimension preferredSize = new Dimension(200, 100);
frame.setPreferredSize(preferredSize);
frame.setVisible(true);
frame.pack();
final ImageUpdateWorker task = new ImageUpdateWorker(label);
task.execute();
}
public static class ImageUpdateWorker extends SwingWorker<Void, IconInfo> {
// iconInfoList is not need in your code. It's here so I can
// supply a dummy set of icons to demonstrate UI updates.
final List<IconInfo> iconInfoList;
private JLabel label;
ImageUpdateWorker(JLabel label) {
this.label = label;
// Delete this in your code
this.iconInfoList = initIconInfoList();
}
#Override
public Void doInBackground() {
boolean isTrue = true;
while (isTrue) {
// Put your socket code to read the next icon from a server.
// You don't need to do the ImageIO.write(), ImageIO.read() dance,
// unless you must save the icon to disk. In that case, you don't need
// to read it back in.
// Here, I just rotate the iconInfoList to make it
// appear as though a new icon was received.
// Your code will not have any need to do this.
Collections.rotate(iconInfoList, -1);
// Just publish the icon you create from the image
// you receive from your remote server.
publish(iconInfoList.get(0));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void process(List<IconInfo> icons) {
// You might check for an empty list.
// #kleopatra's suggestion to get the last icon is correct.
// See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/interim.html
IconInfo iconInfo = icons.get(icons.size() - 1);
label.setIcon(iconInfo.icon);
// Your code will not do this
label.setText(iconInfo.name);
// You can get the icon dimensions just from the icon,
// so you don't really need the IconInfo class.
label.setSize(iconInfo.dimension);
}
/** Demo code only. It doesn't belong in your working code.
*/
protected List<IconInfo> initIconInfoList() {
// Just a quick way to get some icons; don't need to
// fetch from a server just to demonstrate how to
// refresh the UI.
List<IconInfo> iconInfoList = UIManager.getDefaults().keySet().stream()
.filter(this::isIconKey)
.map(IconInfo::new)
.filter(iconInfo -> iconInfo.icon != null)
.collect(Collectors.toList());
return iconInfoList;
}
/** Demo code only. It doesn't belong in your working code.
*/
protected boolean isIconKey(Object key) {
return String.class.isAssignableFrom(key.getClass())
&& ((String) key).toLowerCase().contains("icon");
}
}
/** This is just a convenience to convey
* the icon and its UIManager key (i.e., name).
* Your remote server doesn't supply a name,
* so you don't really need this class.
* It's just to make the demo more expressive.
*/
public static class IconInfo {
final private String name;
final private Icon icon;
final private Dimension dimension;
IconInfo(Object name) {
this.name = name.toString();
icon = UIManager.getIcon(name);
dimension = icon == null
? new Dimension(32, 32)
: new Dimension(icon.getIconWidth(), icon.getIconHeight());
}
}
}
I just want to run two frames concurrently, one contains drag and drop feature which i am using to write file to ftp server and other one to display the progress bar to show how much file is written(uploaded you can say).
But the problem is my progress bar frame remains white i.e, GUI is not done on it.why???
please give me a solution.
here is my first class which is a homePage frame which calls another class called ProgressSample which writes data to the output stream and also updates the progress bar simultaneously.
FTPConnect.java
SwingWorker<Void , Integer> worker = new SwingWorker<Void , Integer>(){
#Override
protected Void doInBackground() throws Exception {
ProgressSample.main(secondLocalFile , bytesIn , inputStream , outputStream);
return null;
}
protected void done(){
ProgressSample.frame.dispose();
}
};
worker.execute();
this is the second class ...
when i call its main(......) method just a frame with white color on it appears nothing is added on it plz plz plz help me with ur suggestions as soon as possible...
ProgressSample.java
package encdec;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
public class ProgressSample
{
static JFrame frame;
JProgressBar progressBar;
public static void main(File file , byte[] bytesIn, InputStream inputStream , OutputStream outputStream)throws IOException
{
ProgressSample obj=new ProgressSample();
obj.redfile(file , bytesIn , inputStream , outputStream);
}
public ProgressSample()
{
frame = new JFrame();
frame.setBounds(100, 100, 400, 200);
frame.getContentPane().setLayout(null);
progressBar = new JProgressBar();
progressBar.setBounds(102, 40, 150, 16);
frame.getContentPane().add(progressBar);
progressBar.setStringPainted(true);
frame.setVisible(true);
}
public void redfile(File f , byte[] bytesIn, InputStream inputStream , OutputStream outputStream)
{
try {
long totalLength = f.length();
double lengthPerPercent = 100.0 / totalLength;
long readLength = 0;
int read;
System.out.println(totalLength);
while ((read = inputStream.read(bytesIn)) != -1) {
readLength += read;
progressBar.setValue((int) Math.round(lengthPerPercent * readLength));
outputStream.write(bytesIn, 0, read);
}
progressBar.setValue(100);
frame.dispose();
JOptionPane.showMessageDialog(null, "Upload Successful");
} catch (Exception e) {
}
}
}
i am showing simple code sample. I showed an gif image in a Jlabel. When run the programme, TASK manager shows that memory is increasing continuously. Why it happens?
Edited:
try this code please... on show glass button, glass panel is shown with gif image and a hide glass button in it and with that memory will be started increasing. On clicking hide glass button, glass panel will be hidden and memory increasing will b stopped.
#mKorbel : I had debugged it, the constructor will be called once, so no re-initializing of JFrame and also included : setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
public class circle extends JFrame {
public ImageIcon pic;
final JPanel glass;
public JButton glass_show;
public JButton hide_glass;
public circle() {
super("Hi shamansdsdsd");
setSize(500, 300);
// Image icon initialize once :
pic = new ImageIcon("images/loadinag.gif");
glass_show = new JButton("Show Glass panel");
this.add(glass_show);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
glass = (JPanel) this.getGlassPane();
hide_glass = new JButton("Hide Glass panel");
glass.add(hide_glass);
glass.add(new JLabel(pic));
glass.setOpaque(false);
}
public void initialize_listeners(){
glass_show.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent A) {
glass.setVisible(true);
}
});
hide_glass.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent A) {
glass.setVisible(false);
}
});
}
public static void main(String[] args) {
circle mFrame = new circle();
mFrame.initialize_listeners();
mFrame.setVisible(true);
}
}
There is a bug in Java with animated GIF images. There is no memory increase with other images.
Edit;
Below example runs without memory leak; but you need Eclipse SWT library from Eclipse's site
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
public class GIFExample {
static Display display;
static Shell shell;
static GC shellGC;
static Color shellBackground;
static ImageLoader loader;
static ImageData[] imageDataArray;
static Thread animateThread;
static Image image;
static final boolean useGIFBackground = false;
public static void main(String[] args) {
display = new Display();
shell = new Shell(display);
shell.setSize(300, 300);
shell.open();
shellGC = new GC(shell);
shellBackground = shell.getBackground();
FileDialog dialog = new FileDialog(shell);
dialog.setFilterExtensions(new String[] {"*.gif"});
String fileName = dialog.open();
if (fileName != null) {
loader = new ImageLoader();
try {
imageDataArray = loader.load(fileName);
if (imageDataArray.length > 1) {
animateThread = new Thread("Animation") {
#Override
public void run() {
/* Create an off-screen image to draw on, and fill it with the shell background. */
Image offScreenImage = new Image(display, loader.logicalScreenWidth, loader.logicalScreenHeight);
GC offScreenImageGC = new GC(offScreenImage);
offScreenImageGC.setBackground(shellBackground);
offScreenImageGC.fillRectangle(0, 0, loader.logicalScreenWidth, loader.logicalScreenHeight);
try {
/* Create the first image and draw it on the off-screen image. */
int imageDataIndex = 0;
ImageData imageData = imageDataArray[imageDataIndex];
if (image != null && !image.isDisposed()) image.dispose();
image = new Image(display, imageData);
offScreenImageGC.drawImage(
image,
0,
0,
imageData.width,
imageData.height,
imageData.x,
imageData.y,
imageData.width,
imageData.height);
/* Now loop through the images, creating and drawing each one
* on the off-screen image before drawing it on the shell. */
int repeatCount = loader.repeatCount;
while (loader.repeatCount == 0 || repeatCount > 0) {
switch (imageData.disposalMethod) {
case SWT.DM_FILL_BACKGROUND:
/* Fill with the background color before drawing. */
Color bgColor = null;
if (useGIFBackground && loader.backgroundPixel != -1) {
bgColor = new Color(display, imageData.palette.getRGB(loader.backgroundPixel));
}
offScreenImageGC.setBackground(bgColor != null ? bgColor : shellBackground);
offScreenImageGC.fillRectangle(imageData.x, imageData.y, imageData.width, imageData.height);
if (bgColor != null) bgColor.dispose();
break;
case SWT.DM_FILL_PREVIOUS:
/* Restore the previous image before drawing. */
offScreenImageGC.drawImage(
image,
0,
0,
imageData.width,
imageData.height,
imageData.x,
imageData.y,
imageData.width,
imageData.height);
break;
}
imageDataIndex = (imageDataIndex + 1) % imageDataArray.length;
imageData = imageDataArray[imageDataIndex];
image.dispose();
image = new Image(display, imageData);
offScreenImageGC.drawImage(
image,
0,
0,
imageData.width,
imageData.height,
imageData.x,
imageData.y,
imageData.width,
imageData.height);
/* Draw the off-screen image to the shell. */
shellGC.drawImage(offScreenImage, 0, 0);
/* Sleep for the specified delay time (adding commonly-used slow-down fudge factors). */
try {
int ms = imageData.delayTime * 10;
if (ms < 20) ms += 30;
if (ms < 30) ms += 10;
Thread.sleep(ms);
} catch (InterruptedException e) {
}
/* If we have just drawn the last image, decrement the repeat count and start again. */
if (imageDataIndex == imageDataArray.length - 1) repeatCount--;
}
} catch (SWTException ex) {
System.out.println("There was an error animating the GIF");
} finally {
if (offScreenImage != null && !offScreenImage.isDisposed()) offScreenImage.dispose();
if (offScreenImageGC != null && !offScreenImageGC.isDisposed()) offScreenImageGC.dispose();
if (image != null && !image.isDisposed()) image.dispose();
}
}
};
animateThread.setDaemon(true);
animateThread.start();
}
} catch (SWTException ex) {
System.out.println("There was an error loading the GIF");
}
}
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}
Code Source
there are two areas
1) you forgot to declare setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); then current JVM instance is still in (the Native OS) RAM, until PC restart or power-off
2) maybe you are create a new JFrame for every Images on the fly
Is there a way for me to get the X and Y values of a window in java? I read that I'll have to use runtime, since java can't mess directly, however I am not so sure of how to do this. Can anyone point me some links/tips on how to get this?
To get the x and y position of "any other unrelated application" you're going to have to query the OS and that means likely using either JNI, JNA or some other scripting utility such as AutoIt (if Windows). I recommend either JNA or the scripting utility since both are much easier to use than JNI (in my limited experience), but to use them you'll need to download some code and integrate it with your Java application.
EDIT 1
I'm no JNA expert, but I do fiddle around with it some, and this is what I got to get the window coordinates for some named window:
import java.util.Arrays;
import com.sun.jna.*;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.win32.*;
public class GetWindowRect {
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class,
W32APIOptions.DEFAULT_OPTIONS);
HWND FindWindow(String lpClassName, String lpWindowName);
int GetWindowRect(HWND handle, int[] rect);
}
public static int[] getRect(String windowName) throws WindowNotFoundException,
GetWindowRectException {
HWND hwnd = User32.INSTANCE.FindWindow(null, windowName);
if (hwnd == null) {
throw new WindowNotFoundException("", windowName);
}
int[] rect = {0, 0, 0, 0};
int result = User32.INSTANCE.GetWindowRect(hwnd, rect);
if (result == 0) {
throw new GetWindowRectException(windowName);
}
return rect;
}
#SuppressWarnings("serial")
public static class WindowNotFoundException extends Exception {
public WindowNotFoundException(String className, String windowName) {
super(String.format("Window null for className: %s; windowName: %s",
className, windowName));
}
}
#SuppressWarnings("serial")
public static class GetWindowRectException extends Exception {
public GetWindowRectException(String windowName) {
super("Window Rect not found for " + windowName);
}
}
public static void main(String[] args) {
String windowName = "Document - WordPad";
int[] rect;
try {
rect = GetWindowRect.getRect(windowName);
System.out.printf("The corner locations for the window \"%s\" are %s",
windowName, Arrays.toString(rect));
} catch (GetWindowRect.WindowNotFoundException e) {
e.printStackTrace();
} catch (GetWindowRect.GetWindowRectException e) {
e.printStackTrace();
}
}
}
Of course for this to work, the JNA libraries would need to be downloaded and placed on the Java classpath or in your IDE's build path.
This is easy to do with the help of the end user. Just get them to click on a point in a screen shot.
E.G.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
/** Getting a point of interest on the screen.
Requires the MotivatedEndUser API - sold separately. */
class GetScreenPoint {
public static void main(String[] args) throws Exception {
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JLabel screenLabel = new JLabel(new ImageIcon(screen));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(screenSize.getWidth()/2),
(int)(screenSize.getHeight()/2)));
final Point pointOfInterest = new Point();
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel pointLabel = new JLabel(
"Click on any point in the screen shot!");
panel.add(pointLabel, BorderLayout.SOUTH);
screenLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
pointOfInterest.setLocation(me.getPoint());
pointLabel.setText(
"Point: " +
pointOfInterest.getX() +
"x" +
pointOfInterest.getY());
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Point of interest: " + pointOfInterest);
}
});
}
}
Typical output
Point of interest: java.awt.Point[x=342,y=43]
Press any key to continue . . .
A little late to the party here but will add this to potentially save others a little time. If you are using a more recent version of JNA then WindowUtils.getAllWindows() will make this much easier to accomplish.
I am using the most recent stable versions as of this post from the following maven locations:
JNA Platform - net.java.dev.jna:jna-platform:5.2.0
JNA Core - net.java.dev.jna:jna:5.2.0
Java 8 Lambda (Edit: rect is a placeholder and will need to be final or effectively final to work in a lambda)
//Find IntelliJ IDEA Window
//import java.awt.Rectangle;
final Rectangle rect = new Rectangle(0, 0, 0, 0); //needs to be final or effectively final for lambda
WindowUtils.getAllWindows(true).forEach(desktopWindow -> {
if (desktopWindow.getTitle().contains("IDEA")) {
rect.setRect(desktopWindow.getLocAndSize());
}
});
Other Java
//Find IntelliJ IDEA Window
Rectangle rect = null;
for (DesktopWindow desktopWindow : WindowUtils.getAllWindows(true)) {
if (desktopWindow.getTitle().contains("IDEA")) {
rect = desktopWindow.getLocAndSize();
}
}
Then within a JPanel you can draw a captured image to fit (Will stretch image if different aspect ratios).
//import java.awt.Robot;
g2d.drawImage(new Robot().createScreenCapture(rect), 0, 0, getWidth(), getHeight(), this);
How can I continuously capture images from a webcam?
I want to experiment with object recognition (by maybe using java media framework).
I was thinking of creating two threads
one thread:
Node 1: capture live image
Node 2: save image as "1.jpg"
Node 3: wait 5 seconds
Node 4: repeat...
other thread:
Node 1: wait until image is captured
Node 2: using the "1.jpg" get colors
from every pixle
Node 3: save data in arrays
Node 4: repeat...
This JavaCV implementation works fine.
Code:
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;
import java.io.File;
import static org.bytedeco.opencv.global.opencv_core.cvFlip;
import static org.bytedeco.opencv.helper.opencv_imgcodecs.cvSaveImage;
public class Test implements Runnable {
final int INTERVAL = 100;///you may use interval
CanvasFrame canvas = new CanvasFrame("Web Cam");
public Test() {
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
public void run() {
new File("images").mkdir();
FrameGrabber grabber = new OpenCVFrameGrabber(0); // 1 for next camera
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
IplImage img;
int i = 0;
try {
grabber.start();
while (true) {
Frame frame = grabber.grab();
img = converter.convert(frame);
//the grabbed frame will be flipped, re-flip to make it right
cvFlip(img, img, 1);// l-r = 90_degrees_steps_anti_clockwise
//save
cvSaveImage("images" + File.separator + (i++) + "-aa.jpg", img);
canvas.showImage(converter.convert(img));
Thread.sleep(INTERVAL);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Test gs = new Test();
Thread th = new Thread(gs);
th.start();
}
}
There is also post on configuration for JavaCV
You can modify the code and be able to save the images in regular interval and do rest of the processing you want.
Some time ago I've created generic Java library which can be used to take pictures with a PC webcam. The API is very simple, not overfeatured, can work standalone, but also supports additional webcam drivers like OpenIMAJ, JMF, FMJ, LTI-CIVIL, etc, and some IP cameras.
Link to the project is https://github.com/sarxos/webcam-capture
Example code (take picture and save in test.jpg):
Webcam webcam = Webcam.getDefault();
webcam.open();
BufferedImage image = webcam.getImage();
ImageIO.write(image, "JPG", new File("test.jpg"));
It is also available in Maven Central Repository or as a separate ZIP which includes all required dependencies and 3rd party JARs.
JMyron is very simple for use.
http://webcamxtra.sourceforge.net/
myron = new JMyron();
myron.start(imgw, imgh);
myron.update();
int[] img = myron.image();
Here is a similar question with some - yet unaccepted - answers. One of them mentions FMJ as a java alternative to JMF.
This kind of goes off of gt_ebuddy's answer using JavaCV, but my video output is at a much higher quality then his answer. I've also added some other random improvements (such as closing down the program when ESC and CTRL+C are pressed, and making sure to close down the resources the program uses properly).
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
public class HighRes extends JComponent implements Runnable {
private static final long serialVersionUID = 1L;
private static CanvasFrame frame = new CanvasFrame("Web Cam");
private static boolean running = false;
private static int frameWidth = 800;
private static int frameHeight = 600;
private static OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
private static BufferedImage bufImg;
public HighRes()
{
// setup key bindings
ActionMap actionMap = frame.getRootPane().getActionMap();
InputMap inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
for (Keys direction : Keys.values())
{
actionMap.put(direction.getText(), new KeyBinding(direction.getText()));
inputMap.put(direction.getKeyStroke(), direction.getText());
}
frame.getRootPane().setActionMap(actionMap);
frame.getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
// setup window listener for close action
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
stop();
}
});
}
public static void main(String... args)
{
HighRes webcam = new HighRes();
webcam.start();
}
#Override
public void run()
{
try
{
grabber.setImageWidth(frameWidth);
grabber.setImageHeight(frameHeight);
grabber.start();
while (running)
{
final IplImage cvimg = grabber.grab();
if (cvimg != null)
{
// cvFlip(cvimg, cvimg, 1); // mirror
// show image on window
bufImg = cvimg.getBufferedImage();
frame.showImage(bufImg);
}
}
grabber.stop();
grabber.release();
frame.dispose();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void start()
{
new Thread(this).start();
running = true;
}
public void stop()
{
running = false;
}
private class KeyBinding extends AbstractAction {
private static final long serialVersionUID = 1L;
public KeyBinding(String text)
{
super(text);
putValue(ACTION_COMMAND_KEY, text);
}
#Override
public void actionPerformed(ActionEvent e)
{
String action = e.getActionCommand();
if (action.equals(Keys.ESCAPE.toString()) || action.equals(Keys.CTRLC.toString())) stop();
else System.out.println("Key Binding: " + action);
}
}
}
enum Keys
{
ESCAPE("Escape", KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)),
CTRLC("Control-C", KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)),
UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
private String text;
private KeyStroke keyStroke;
Keys(String text, KeyStroke keyStroke)
{
this.text = text;
this.keyStroke = keyStroke;
}
public String getText()
{
return text;
}
public KeyStroke getKeyStroke()
{
return keyStroke;
}
#Override
public String toString()
{
return text;
}
}
You can try Java Webcam SDK library also.
SDK demo applet is available at link.
I have used JMF on a videoconference application and it worked well on two laptops: one with integrated webcam and another with an old USB webcam. It requires JMF being installed and configured before-hand, but once you're done you can access the hardware via Java code fairly easily.
You can try Marvin Framework. It provides an interface to work with cameras. Moreover, it also provides a set of real-time video processing features, like object tracking and filtering.
Take a look!
Real-time Video Processing Demo:
http://www.youtube.com/watch?v=D5mBt0kRYvk
You can use the source below. Just save a frame using MarvinImageIO.saveImage() every 5 second.
Webcam video demo:
public class SimpleVideoTest extends JFrame implements Runnable{
private MarvinVideoInterface videoAdapter;
private MarvinImage image;
private MarvinImagePanel videoPanel;
public SimpleVideoTest(){
super("Simple Video Test");
videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.connect(0);
videoPanel = new MarvinImagePanel();
add(videoPanel);
new Thread(this).start();
setSize(800,600);
setVisible(true);
}
#Override
public void run() {
while(true){
// Request a video frame and set into the VideoPanel
image = videoAdapter.getFrame();
videoPanel.setImage(image);
}
}
public static void main(String[] args) {
SimpleVideoTest t = new SimpleVideoTest();
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
For those who just want to take a single picture:
WebcamPicture.java
public class WebcamPicture {
public static void main(String[] args) {
try{
MarvinVideoInterface videoAdapter = new MarvinJavaCVAdapter();
videoAdapter.connect(0);
MarvinImage image = videoAdapter.getFrame();
MarvinImageIO.saveImage(image, "./res/webcam_picture.jpg");
} catch(MarvinVideoInterfaceException e){
e.printStackTrace();
}
}
}
I used Webcam Capture API. You can download it from here
webcam = Webcam.getDefault();
webcam.open();
if (webcam.isOpen()) { //if web cam open
BufferedImage image = webcam.getImage();
JLabel imageLbl = new JLabel();
imageLbl.setSize(640, 480); //show captured image
imageLbl.setIcon(new ImageIcon(image));
int showConfirmDialog = JOptionPane.showConfirmDialog(null, imageLbl, "Image Viewer", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, new ImageIcon(""));
if (showConfirmDialog == JOptionPane.YES_OPTION) {
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Save Image");
chooser.setFileFilter(new FileNameExtensionFilter("IMAGES ONLY", "png", "jpeg", "jpg")); //this file extentions are shown
int showSaveDialog = chooser.showSaveDialog(this);
if (showSaveDialog == 0) { //if pressed 'Save' button
String filePath = chooser.getCurrentDirectory().toString().replace("\\", "/");
String fileName = chooser.getSelectedFile().getName(); //get user entered file name to save
ImageIO.write(image, "PNG", new File(filePath + "/" + fileName + ".png"));
}
}
}
http://grack.com/downloads/school/enel619.10/report/java_media_framework.html
Using the Player with Swing
The Player can be easily used in a Swing application as well. The following code creates a Swing-based TV capture program with the video output displayed in the entire window:
import javax.media.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.event.*;
public class JMFTest extends JFrame {
Player _player;
JMFTest() {
addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
_player.stop();
_player.deallocate();
_player.close();
System.exit( 0 );
}
});
setExtent( 0, 0, 320, 260 );
JPanel panel = (JPanel)getContentPane();
panel.setLayout( new BorderLayout() );
String mediaFile = "vfw://1";
try {
MediaLocator mlr = new MediaLocator( mediaFile );
_player = Manager.createRealizedPlayer( mlr );
if (_player.getVisualComponent() != null)
panel.add("Center", _player.getVisualComponent());
if (_player.getControlPanelComponent() != null)
panel.add("South", _player.getControlPanelComponent());
}
catch (Exception e) {
System.err.println( "Got exception " + e );
}
}
public static void main(String[] args) {
JMFTest jmfTest = new JMFTest();
jmfTest.show();
}
}
Java usually doesn't like accessing hardware, so you will need a driver program of some sort, as goldenmean said. I've done this on my laptop by finding a command line program that snaps a picture. Then it's the same as goldenmean explained; you run the command line program from your java program in the takepicture() routine, and the rest of your code runs the same.
Except for the part about reading pixel values into an array, you might be better served by saving the file to BMP, which is nearly that format already, then using the standard java image libraries on it.
Using a command line program adds a dependency to your program and makes it less portable, but so was the webcam, right?
I believe the web-cam application software which comes along with the web-cam, or you native windows webcam software can be run in a batch script(windows/dos script) after turning the web cam on(i.e. if it needs an external power supply). In the bacth script , u can add appropriate delay to capture after certain time period. And keep executing the capture command in loop.
I guess this should be possible
-AD
There's a pretty nice interface for this in processing, which is kind of a pidgin java designed for graphics. It gets used in some image recognition work, such as that link.
Depending on what you need out of it, you might be able to load the video library that's used there in java, or if you're just playing around with it you might be able to get by using processing itself.
FMJ can do this, as can the supporting library it uses, LTI-CIVIL. Both are on sourceforge.
Recommand using FMJ for multimedia relatived java app.
Try using JMyron How To Use Webcam Using Java. I think using JMyron is the easiest way to access a webcam using java. I tried to use it with a 64-bit processor, but it gave me an error. It worked just fine on a 32-bit processor, though.