package facerec;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import org.openimaj.feature.DoubleFVComparison;
import org.openimaj.image.FImage;
import org.openimaj.image.MBFImage;
import org.openimaj.image.colour.RGBColour;
import org.openimaj.image.processing.face.alignment.RotateScaleAligner;
import org.openimaj.image.processing.face.detection.HaarCascadeDetector;
import org.openimaj.image.processing.face.detection.keypoints.FKEFaceDetector;
import org.openimaj.image.processing.face.detection.keypoints.KEDetectedFace;
import org.openimaj.image.processing.face.recognition.EigenFaceRecogniser;
import org.openimaj.image.processing.face.recognition.FaceRecognitionEngine;
import org.openimaj.image.typography.hershey.HersheyFont;
import org.openimaj.math.geometry.point.Point2d;
import org.openimaj.ml.annotation.Annotated;
import org.openimaj.ml.annotation.AnnotatedObject;
import org.openimaj.ml.annotation.ScoredAnnotation;
import org.openimaj.util.pair.IndependentPair;
import org.openimaj.video.VideoDisplay;
import org.openimaj.video.VideoDisplayListener;
import org.openimaj.video.capture.VideoCapture;
public class NewFaceRegister extends KeyAdapter implements VideoDisplayListener<MBFImage> {
private VideoCapture capture;
private VideoDisplay<MBFImage> videoFrame;
FKEFaceDetector faceDetector = new FKEFaceDetector(new HaarCascadeDetector());
private EigenFaceRecogniser<KEDetectedFace, String> recogniser = EigenFaceRecogniser.create(20, new RotateScaleAligner(), 1, DoubleFVComparison.CORRELATION, 0.9f);
FaceRecognitionEngine<KEDetectedFace, String> engine = FaceRecognitionEngine.create(faceDetector, recogniser);
Annotated<KEDetectedFace, String> faceobj;
private FImage currentFrame;
public NewFaceRegister() throws Exception {
capture = new VideoCapture(940, 720);
//engine = new CLMFaceTracker();
//engine.fpd = 120;
videoFrame = VideoDisplay.createVideoDisplay(capture);
videoFrame.addVideoListener(this);
SwingUtilities.getRoot(videoFrame.getScreen()).addKeyListener(this);
}
#Override
public synchronized void keyPressed(KeyEvent key) {
if (key.getKeyCode() == KeyEvent.VK_SPACE) {
this.videoFrame.togglePause();
} else if (key.getKeyChar() == 'c') {
// if (!this.videoFrame.isPaused())
// this.videoFrame.togglePause();
final String person = JOptionPane.showInputDialog(this.videoFrame.getScreen(), "Name der Person eingeben", "",
JOptionPane.QUESTION_MESSAGE);
final List<KEDetectedFace> faces = detectFaces();
if (faces.size() == 1) {
engine.train(faces.get(0), person);
//TODO Datenbankmethode aufrufen, welches das AnnotatedObject (faceObj) speichert.
} else {
System.out.println("Zu viele/wenige Gesichter im Bild");
}
//this.videoFrame.close();
} else
System.out.println("Wrong key");
}
private List<KEDetectedFace> detectFaces() {
return engine.getDetector().detectFaces(currentFrame);
}
#Override
public void afterUpdate(VideoDisplay<MBFImage> display) {
// do nothing
}
#Override
public synchronized void beforeUpdate(MBFImage frame) {
this.currentFrame = frame.flatten();
/*engine.track(frame);
engine.drawModel(frame, true, true, true, true, true);*/
final List<KEDetectedFace> faces = detectFaces();
for (KEDetectedFace face : faces) {
frame.drawShape(face.getBounds(), RGBColour.RED);
}
if (recogniser != null && recogniser.listPeople().size() >= 1) {
for (KEDetectedFace face : faces) {
List<IndependentPair<KEDetectedFace, ScoredAnnotation<String>>> name = engine.recogniseBest(face.getFacePatch());
if (name.size() > 0) {
final Point2d r = face.getBounds().getTopLeft();
frame.drawText(name.get(0).getSecondObject().toString(), r, HersheyFont.ROMAN_SIMPLEX, 15, RGBColour.GREEN);
}
}
}
}
public static void main(String[] args) throws Exception {
new NewFaceRegister();
}
}
Why do I get an OutOfMemoryError? I tryed it with an other Dedector and there it works?! I also looked in some other Questions for an Answer and i found one Solution and i excactly worked with it, but it also didn't worked.
It's my first time working with Openimaj.
Exception in thread "Thread-4" java.lang.OutOfMemoryError: Java heap space
at no.uib.cipr.matrix.AbstractDenseMatrix.<init>(AbstractDenseMatrix.java:47)
at no.uib.cipr.matrix.DenseMatrix.<init>(DenseMatrix.java:167)
at no.uib.cipr.matrix.SVD.<init>(SVD.java:98)
at no.uib.cipr.matrix.SVD.<init>(SVD.java:75)
at no.uib.cipr.matrix.SVD.factorize(SVD.java:146)
at org.openimaj.math.matrix.ThinSingularValueDecomposition.<init>(ThinSingularValueDecomposition.java:84)
at org.openimaj.math.matrix.ThinSingularValueDecomposition.<init>(ThinSingularValueDecomposition.java:69)
at org.openimaj.math.matrix.algorithm.pca.ThinSvdPrincipalComponentAnalysis.learnBasisNorm(ThinSvdPrincipalComponentAnalysis.java:56)
at org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis.learnBasis(PrincipalComponentAnalysis.java:183)
at org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis.learnBasis(PrincipalComponentAnalysis.java:170)
at org.openimaj.ml.pca.FeatureVectorPCA.learnBasis(FeatureVectorPCA.java:113)
at org.openimaj.image.model.EigenImages.train(EigenImages.java:125)
at org.openimaj.image.processing.face.feature.EigenFaceFeature$Extractor.train(EigenFaceFeature.java:167)
at org.openimaj.image.processing.face.recognition.EigenFaceRecogniser.beforeBatchTrain(EigenFaceRecogniser.java:159)
at org.openimaj.image.processing.face.recognition.LazyFaceRecogniser.retrain(LazyFaceRecogniser.java:139)
at org.openimaj.image.processing.face.recognition.LazyFaceRecogniser.annotate(LazyFaceRecogniser.java:153)
at org.openimaj.image.processing.face.recognition.EigenFaceRecogniser.annotate(EigenFaceRecogniser.java:55)
at org.openimaj.image.processing.face.recognition.FaceRecogniser.annotateBest(FaceRecogniser.java:115)
at org.openimaj.image.processing.face.recognition.FaceRecognitionEngine.recogniseBest(FaceRecognitionEngine.java:260)
at facerec.NewFaceRegister.beforeUpdate(NewFaceRegister.java:97)
at facerec.NewFaceRegister.beforeUpdate(NewFaceRegister.java:1)
at org.openimaj.video.VideoDisplay.fireBeforeUpdate(VideoDisplay.java:785)
at org.openimaj.video.VideoDisplay.run(VideoDisplay.java:522)
at java.lang.Thread.run(Unknown Source)
The reason you got failed is because of image processing algorithm used. I'm not sure what openimaj uses, but there are two workarounds possible for this:
Increase heap size, so that your application has more memory available for image processing. See How can I increase the JVM memory?
Decrease image size, so that your application will use less memory for processing.
Based on my own experience with face detection on mobile devices (limited memory as well), 940x720 seems to be more than enough for face detection. Feel free to resize into 640x480 (or similar), results should not be affected.
Remember that you can copy your initial image, resize it with any aspect ratio (i.g. 1.5), detect face on new resized image and return initial image with detected face coordinates multiplied on your aspect ratio.
Related
There is a class called AnimationInfo which supposed to give animation information from Presentation. But my bad luck I could not get it.
List<XSLFShape> shapes = slide.getShapes();
for (XSLFShape shape: shapes) {
//Need to get animation of this shape here
}
Can anyone help me on this ? Thanks.
PS: I am using 3.17 version of POI.
Given the addition of only detecting an animation, a sheet can be checked for a timing information which quite likely identifies the existence of an animation, i.e. you could get a false positive in case an animation was added and then removed again. Furthermore you need to check all slides, until an animation is found.
import java.io.FileInputStream;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordContainer;
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.sl.usermodel.Slide;
import org.apache.poi.sl.usermodel.SlideShow;
import org.apache.poi.sl.usermodel.SlideShowFactory;
import org.apache.poi.xslf.usermodel.XSLFSlide;
public class AnimCheck {
private static final int timingRecordPath[] = {
RecordTypes.ProgTags.typeID,
RecordTypes.ProgBinaryTag.typeID,
RecordTypes.BinaryTagData.typeID,
0xf144
};
public static void main(String[] args) throws Exception {
SlideShow<?,?> ppt = SlideShowFactory.create(new FileInputStream("no_anim.pptx"));
Slide<?,?> slide = ppt.getSlides().get(0);
boolean hasTiming;
if (slide instanceof XSLFSlide) {
XSLFSlide xsld = (XSLFSlide)slide;
hasTiming = xsld.getXmlObject().isSetTiming();
} else {
HSLFSlide hsld = (HSLFSlide)slide;
Record lastRecord = hsld.getSheetContainer();
boolean found = true;
for (int ri : timingRecordPath) {
lastRecord = ((RecordContainer)lastRecord).findFirstOfType(ri);
if (lastRecord == null) {
found = false;
break;
}
}
hasTiming = found;
}
ppt.close();
System.out.println(hasTiming);
}
}
I'm trying to extract establishments data from GooglePlaces API. It used to work initially, but after making a specific method for extracting the places (instead of in the main method), the program crushes. When debbuged it, it gets stuck in a java method called park (under LockSupport class from java). Reading about it, it says that this happens when there is more than 1 thread and there are sync problems. I'm very new at this and I don't know how to solve this in my code. In my mind, there is only 1 thread in this code, but I'm pretty sure I'm wrong. Please help. It crashes in a "for" commented below. Thanks so much!
package laundry;
import java.util.ArrayList;
import java.util.List;
import se.walkercrou.places.GooglePlaces;
import se.walkercrou.places.Param;
import se.walkercrou.places.Place;
import java.io.FileWriter; //add to import list
import java.io.IOException;
import java.io.Writer;
import static java.lang.Math.sqrt;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.microedition.location.Coordinates;
import se.walkercrou.places.exception.GooglePlacesException;
import se.walkercrou.places.exception.RequestDeniedException;
public class Laundry {
public static void main(String[] args) throws IOException {
List<Place> detailedPlaces = new ArrayList<>();
List<double[]> circlesPoint = new ArrayList<>();
double radio = 10;
Coordinates startingPoint = new Coordinates (-38.182476,144.552079,0);//geelong south west corner of the grid
Coordinates finalPoint = new Coordinates(-37.574381,145.415879,0); //north east of melbourne
GooglePlaces cliente = new GooglePlaces("keyof googlplaces");
MyResult result1=exploreGrid(startingPoint,finalPoint, radio, detailedPlaces, circlesPoint,cliente);
writeResultsCircles(result1.getPoints(),"c:\\outputCircles.txt" );
writeResultsPlaces(result1.getPlaces(), "c:\\outputPlaces.txt");
}
private static MyResult exploreGrid(Coordinates SWpoint,Coordinates NEpoint,double rad, List<Place> lugares, List<double[]> points,GooglePlaces client){
int iterationRow=0;
Coordinates workingPoint = new Coordinates(SWpoint.getLatitude(),SWpoint.getLongitude(),(float) 0.0);
List<Place> places = new ArrayList<>();
while (workingPoint.getLatitude()<NEpoint.getLatitude()){
while (workingPoint.getLongitude()<NEpoint.getLongitude()){
try {
places = client.getNearbyPlaces(workingPoint.getLatitude(), workingPoint.getLongitude(), rad*1000,GooglePlaces.MAXIMUM_RESULTS ,Param.name("types").value("laundry"));
if (places.size()==60){//si se llega al tope de resultados de getNearbyPlaces
iterationRow=1;
}
for (Place place : places) {
lugares.add(place.getDetails());//here is where it crashes
}
}catch (GooglePlacesException ex) {
System.out.println(ex.getCause());
}
double[] prePoint = {workingPoint.getLatitude(),workingPoint.getLongitude(),rad};
points.add(prePoint);
workingPoint.setLongitude(workingPoint.getLongitude()+rad*sqrt(3)*0.01134787);
}
iterationRow++;
if (isEven(iterationRow)){
workingPoint.setLongitude(SWpoint.getLongitude());
} else {
workingPoint.setLongitude(SWpoint.getLongitude()+rad*sqrt(3)*0.01134787/2);
}
workingPoint.setLatitude(workingPoint.getLatitude()+rad*3/2*0.00899416);
}
return new MyResult(lugares,points);
}
}
i have axis m1114 ip camera
i want to display live streaming as well as record streaming using java. i tried following code but frame rate is very low
please suggest some api gives me more frame rate and recording functionality.
import java.io.File;
import java.net.URL;
import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_calib3d.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import demo.authenticator.MyAuthenticator;
import java.net.Authenticator;
import java.net.MalformedURLException;
import org.jcodec.api.SequenceEncoder;
public class Demo {
public static void main(String[] args) throws IOException {
CanvasFrame CamWindow = new CanvasFrame("Camera");
int i=0,j=0;
URL url = null ;
SequenceEncoder encoder=new SequenceEncoder(new File("video.mp4"));
try {
// Create a new URL object from the URL-string of our camera.
url = new URL("http://192.168.168.92/axis-cgi/jpg/image.cgi");
} catch (MalformedURLException m) {
m.getMessage();
}
// Check if this camera requires authentication.
// If so, then create and set the authenticator object.
MyAuthenticator authenticator = new MyAuthenticator("root",
"pass");
Authenticator.setDefault(authenticator);
Long stime=System.currentTimeMillis();
while(true){
i++;
//InputStream is = url.openStream();
BufferedImage image = ImageIO.read(url);
CamWindow.showImage(image);
// is.close();
/* if(i<100)
{
encoder.encodeImage(image);
}
else
{
if(j==0)
{
encoder.finish();
j++;
System.out.println("video saved");
System.out.println((System.currentTimeMillis()-stime)/1000+"seconds");
}
}*/
System.out.println((System.currentTimeMillis()-stime));
}
}
}
The Axis camera API is here: http://www.axis.com/files/manuals/vapix_video_streaming_52937_en_1307.pdf
You need to use this:
http:///axis-cgi/mjpg/video.cgi
instead of the image URL you have now. Getting a still image from the Axis camera will be very choppy. You need to use the Motion JPEG feed it spits out.
I have also gone through for these solutions and one of the good API i found is WEBCAM-Capture. I rate it good for some reasons
It is updated
It is open source
Many Examples
And most IMPORTANT its support from its developers is fast and accurate rather than other Camera supporting APIs.
Hope this would help you.
I want to do some image analysis on a video that's stored in .mp4 format. Therefore I need a way to just get the images of this movie in Java.
I goolged a lot and found some libraries like jcodec and jaad. BUT I wasn't able to get the things running with these libraries. And as I found out, there were examples (at least I found none) that showed my usecase.
Can you help me? Do you know any library that can do what I need and is running at least on Win7 64 bit.
Or do you know how to accomplish this with jcodec?
edit:
As I wrote, I tried it with jcodec. I found out how to get the data of a frame, but not how I can get it into something like a BufferedImage or so. I expect that these data isn't in a simple RGB format but in any compressed format or so. (Am I right with that?) I don't know to to decode this data.
You can get the data of a frame with jcodec as follows (at least as far as I understand this):
public static void main(String[] args) throws IOException, MP4DemuxerException {
String path = "videos/video-2011-09-21-20-07-21.mp4";
MP4Demuxer demuxer1 = new MP4Demuxer(new FileInput(new File(path)));
DemuxerTrack videoTrack = demuxer1.getVideoTrack();
Packet firstFrame = videoTrack.getFrames(1);
byte[] data = firstFrame.getData();
}
I also found the following:
http://code.google.com/p/jcodec/source/browse/trunk/src/test/java/org/jcodec/containers/mp4/DitherTest.java?r=70
But this isn't working (has compile errors) with the downloadable jar-package.
you could use jcodec(https://github.com/jcodec/jcodec) in the followinf program i am extracting frames from a video.
/*
* To extract frames from a mp4(avc) video
*
*/
package avc_frame;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.jcodec.api.FrameGrab;
import org.jcodec.api.JCodecException;
public class Avc_frame {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, JCodecException {
long time = System.currentTimeMillis();
for (int i = 50; i < 57; i++) {
BufferedImage frame = FrameGrab.getFrame(new File("/Users/jovi/Movies/test.mp4"), i);
ImageIO.write(frame, "bmp", new File("/Users/jovi/Desktop/frames/frame_"+i+".bmp"));
}
System.out.println("Time Used:" + (System.currentTimeMillis() - time)+" Milliseconds");
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public class Read{
public static void main(String []args) throws IOException, Exception
{
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
frameGrabber.start();
IplImage i;
try {
i = frameGrabber.grab();
BufferedImage bi = i.getBufferedImage();
ImageIO.write(bi,"png", new File("D:/Img.png"));
frameGrabber.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I'm trying to get the method data.SetValue(...) working in the asynchronous callback in method getNames. Unfortunately it doesn't work. data.setValue(...) does work in the synchronous method createColumnChartView.
What could be the cause of this problem? Please explain why setting data doesn't work in getNames. Thanks in advance!
import java.util.ArrayList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.visualizations.corechart.ColumnChart;
import com.google.gwt.visualization.client.visualizations.corechart.CoreChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
import com.practicum.client.Product;
import com.practicum.client.rpc.ProductService;
import com.practicum.client.rpc.ProductServiceAsync;
public class DataOutColumnChart {
private final DataTable data = DataTable.create();
private final Options options = CoreChart.createOptions();
private final ProductServiceAsync productService = GWT.create(ProductService.class);
public DataOutColumnChart(Runnable runnable) {
}
public Widget createColumnChartView() {
/* create a datatable */
data.addColumn(ColumnType.STRING, "Price");
data.addColumn(ColumnType.NUMBER, "EUR");
data.addRows(2);
data.setValue(0, 0, "Bar 1");
data.setValue(0, 1, 123);
getNames();
/* create column chart */
options.setWidth(400);
options.setHeight(300);
options.setBackgroundColor("#e8e8e9");
return new ColumnChart(data, options);
}
public void getNames() {
productService.getNames(new AsyncCallback<ArrayList<Product>>() {
public void onFailure(Throwable caught) {
}
public void onSuccess(ArrayList<Product> result) {
for (Product p : result) {
data.setValue(0, 0, "Bar 2"); // DONT WORK, NOTHING HAPPENS
data.setValue(0, 1, 345); // DONT WORK, NOTHING HAPPENS
System.out.println("Bla bla test"); // THIS WORKS
}
}
});
}
}
The problem is occurring because you're setting data to a DataTable that has already been rendered. Your Asynchronous call in getNames() completes too slowly to affect the DataTable in time for the rendering of the ColumnChart. Even if it did complete fast enough, it would always be a race condition. Ideally, you would not actually render that chart until after you've received all necessary data from the RPC call.
Another option is to store a reference to that ColumnChart and call columnChart.draw(...) after you get your data back from RPC.
Edit:
Here's the example you requested.
import java.util.ArrayList;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.visualizations.corechart.ColumnChart;
import com.google.gwt.visualization.client.visualizations.corechart.CoreChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
import com.practicum.client.Product;
import com.practicum.client.rpc.ProductService;
import com.practicum.client.rpc.ProductServiceAsync;
public class DataOutColumnChart {
private final DataTable data = DataTable.create();
private final Options options = CoreChart.createOptions();
private final ProductServiceAsync productService = GWT.create(ProductService.class);
private ColumnChart chart = null;
public DataOutColumnChart(Runnable runnable) {
}
public void initColumnChart() {
/* create a datatable */
data.addColumn(ColumnType.STRING, "Price");
data.addColumn(ColumnType.NUMBER, "EUR");
/* create column chart */
options.setWidth(400);
options.setHeight(300);
options.setBackgroundColor("#e8e8e9");
chart = new ColumnChart(data, options);
}
public void getNames() {
productService.getNames(new AsyncCallback<ArrayList<Product>>() {
public void onFailure(Throwable caught) {
}
public void onSuccess(ArrayList<Product> result) {
if (result != null && result.size() > 0) {
// if there is data...
data.addRows(result.size()); // add a row for each result
for (int i = 0; i < result.size(); i++) {
// loop through the results
Product product = result.get(i); // get out the product
// ...then set the column values for this row
data.setValue(i, 0, product.getSomeProperty());
data.setValue(i, 1, product.getSomeOtherProperty());
}
updateChart();
}
}
});
}
public void updateChart() {
chart.draw(data, options);
}
}