Track fast moving fiducial using BoofCV - java

I am trying to track a person's head with a binary fiducial printed. It can track fine when the person is moving slowly, but when they move their head quickly, it loses the track and then regains it when they stop moving. What can I do to track the person while they are moving quickly?
For reference, here is a screenshot and code:
camera = UtilWebcamCapture.openDefault(1920, 1080);
intrinsicParameters = new IntrinsicParameters();
intrinsicParameters.setCx(camera.getViewSize().getWidth()/2f);
intrinsicParameters.setCy(camera.getViewSize().getHeight()/2f);
intrinsicParameters.setFx(1);
intrinsicParameters.setFy(1);
intrinsicParameters.setWidth((int)camera.getViewSize().getWidth());
intrinsicParameters.setHeight((int)camera.getViewSize().getHeight());
detector = FactoryFiducial.squareBinary(
new ConfigFiducialBinary(1),
ConfigThreshold.local(ThresholdType.LOCAL_SQUARE, 10),
//ConfigThreshold.fixed(100),
GrayU8.class);
detector.setIntrinsic(intrinsicParameters);
...
while (true) {
BufferedImage image = camera.getImage();
GrayU8 input = ConvertBufferedImage.convertFrom(image, (GrayU8) null);
WorldToCameraToPixel transform;
try {
detector.detect(input);
Se3_F64 targetToSensor = new Se3_F64();
for (int i = 0; i < detector.totalFound(); i++) {
detector.getFiducialToCamera(i, targetToSensor);
transform = PerspectiveOps.createWorldToPixel(intrinsicParameters, targetToSensor);
Point2D_F64 centre = transform.transform(
new Point3D_F64(0, 0, 0));
System.out.println(centre);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks!

I solved this issue by creating an object tracker using the initial location of the fiducial, and using that when the user moves quickly.

Related

take picture when face detected using FaceDetector google-vision

I found the demo code here: https://github.com/googlesamples/android-vision/blob/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/FaceTrackerActivity.java
and my question is how to take picture when face detected and save it to device, and when we take 1st picture next picture will be take after 5s when face detected because we can't save to many picture to device.
You have to add FaceDetectionListener in camera API then call startFaceDetection() method,
CameraFaceDetectionListener fDListener = new CameraFaceDetectionListener();
mCamera.setFaceDetectionListener(fDetectionListener);
mCamera.startFaceDetection();
Implement Camera.FaceDetectionListener, you receive the detected face in onFaceDetection override method,
private class MyFaceDetectionListener
implements Camera.FaceDetectionListener {
#Override
public void onFaceDetection(Face[] faces, Camera camera) {
if (faces.length == 0) {
Log.i(TAG, "No faces detected");
} else if (faces.length > 0) {
Log.i(TAG, "Faces Detected = " +
String.valueOf(faces.length));
public List<Rect> faceRects;
faceRects = new ArrayList<Rect>();
for (int i=0; i<faces.length; i++) {
int left = faces[i].rect.left;
int right = faces[i].rect.right;
int top = faces[i].rect.top;
int bottom = faces[i].rect.bottom;
Rect uRect = new Rect(left0, top0, right0, bottom0);
faceRects.add(uRect);
}
// add function to draw rects on view/surface/canvas
}
}
As per your case, new Handler().postDelayed(new Runnable,long seconds) take 2nd picture inside runnable after 5 seconds.
Please let me know if you have any queries.

How to convert an image from 8-Bit to RGB in ImageJ2 using Java

I'm trying to use ImageJ2 directly from Java to create a binarised image coming from an input image.
A somewhat working version of my code looks like this:
final File file = new File("input.png");
try {
DefaultDataTypeService dataTypeService = new DefaultDataTypeService();
Dataset dataset = imageJ.dataset().open(file.getAbsolutePath());
Img inputImg = dataset.getImgPlus();
PluginInfo pluginInfo = imageJ.plugin().getPlugin(Binarize.class);
Binarize binarizeOp = (Binarize) pluginInfo.createInstance();
binarizeOp.setContext(imageJ.getContext());
binarizeOp.setChangeInput(true);
binarizeOp.setFillMaskBackground(true);
binarizeOp.setFillMaskForeground(true);
binarizeOp.setInputData(dataset);
binarizeOp.setInputMask(null);
binarizeOp.setMaskColor(Binarize.WHITE);
binarizeOp.setMaskPixels(Binarize.INSIDE);
binarizeOp.setThresholdEachPlane(false);
binarizeOp.setDefaultThresholdMethod();
binarizeOp.run();
dataset.rgbChange();
DefaultDatasetService defaultDatasetService = new DefaultDatasetService();
Img outputImg = dataset.getImgPlus();
outputImg = outputImg.factory().imgFactory(new UnsignedByteType()).create(outputImg,new UnsignedByteType());
Dataset outputDataset = defaultDatasetService.create(outputImg);
imageJ.dataset().save(outputDataset,"input_binary.png");
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiableException e) {
e.printStackTrace();
} catch (IncompatibleTypeException e) {
e.printStackTrace();
}
Running this code I have the problem that "input_binary.png" will be completely black, a behaviour I can reproduce using the ImageJ client application.
What I need to do in the client is to change the image type from "8-bit Color" to "RGB-Color". But I can not figure out how to reproduce that in Java using the current version of the net.imagej library.
I know that it would be possible using the 1.x library but I would like to to it using the 2.x.
Any help would be greatly appreciated.
You're getting black images because of this:
outputImg = outputImg.factory().imgFactory(new UnsignedByteType()).create(outputImg,new UnsignedByteType());
Which is just copying the dimensionality of your source image, not its values.
A few other key points:
It's best practice to have your Contextual objects (e.g. Services) derived from the Context instead of manually constructed.
The Binarize command has a Dataset output so it's not necessary to go Dataset > ImgPlus > Dataset
If you do want to write the dataset out you need to convert from the BitType output by Binarize to one that's supported.
See below for an example of running Binarize, getting the output, converting it and writing it out. Hope that helps!
public static void main(String... args) {
final File file = new File("inpath.png");
final File out = new File("outpath.png");
// This is just sugar for the point of illustration.
// The purpose here is just to have access to a Context
ImageJ imagej = new ImageJ();
// Cache the context for future use.
Context context = imagej.getContext();
try {
// Use the context to get the services we want to ensure they are all
// properly initialized.
// If this was a Command these could all be #Parameters to be populated
// automatically.
DatasetService datasetService = context.getService(DatasetService.class);
CommandService commandService = context.getService(CommandService.class);
DatasetIOService datasetIOService =
context.getService(DatasetIOService.class);
Dataset input = datasetIOService.open(file.getAbsolutePath());
// Start the command
Future<CommandModule> future =
commandService.run(Binarize.class, true, "inputData", input);
// Get the command output
Dataset binarized = (Dataset) future.get().getOutput("outputMask");
// The output type is a binary image which, at the moment, needs to be
// explicitly converted to something that can be written out.
// Adapted from:
// http://fiji.sc/ImgLib2_Examples#Example_2c_-_Generic_copying_of_image_data
Img inputImg = input.getImgPlus().getImg();
Img outputImg = binarized.getImgPlus().getImg();
Img typedImg =
inputImg.factory().create(inputImg, inputImg.firstElement());
scale(outputImg, typedImg);
Dataset output = datasetService.create(typedImg);
// Save the output dataset
datasetIOService.save(output, out.getAbsolutePath());
}
catch (IOException exc) {
exc.printStackTrace();
}
catch (InterruptedException exc) {
exc.printStackTrace();
}
catch (ExecutionException exc) {
exc.printStackTrace();
}
finally {
// Dispose of the context to shut down
context.dispose();
}
}
public static <T extends IntegerType<T>> void scale(
final RandomAccessible<BitType> source, final IterableInterval<T> target)
{
// create a cursor that automatically localizes itself on every move
Cursor<T> targetCursor = target.localizingCursor();
RandomAccess<BitType> sourceRandomAccess = source.randomAccess();
// iterate over the input cursor
while (targetCursor.hasNext()) {\
// move input cursor forward
targetCursor.fwd();
// set the output cursor to the position of the input cursor
sourceRandomAccess.setPosition(targetCursor);
// set the value of this pixel of the output image
BitType b = sourceRandomAccess.get();
if (b.get()) {
targetCursor.get().setOne();
}
else {
targetCursor.get().setZero();
}
}
}

Unable to get terrain loaded with PhysicsEditor-Extension to collide

For my android game, based around AndEngine, I am currently working on loading levels.
I came across AndEngine-PhysicsEditor-Extension, which loads an XML and graphics exported by PhysicsEditor.
I am now working on creating a class, conveniently named MapLoader, which takes a map name and calls the PhysicsEditor Extension to load the appropriate files and register them. The problem is that while the graphics are displayed as intended, anything else in the scene pass right through it without colliding.
Here's how the MapLoader is invoked:
MapLoader loader = new MapLoader(this, engine, world); // (Context, PhysicsWorld, Scene)
loader.loadMap("testmap1");
And here's the important bits of the MapLoader class:
// Constructor
public void loadMap(String mapName) {
this.atlas = new BitmapTextureAtlas(game.getTextureManager(), 2048, 1024, TextureOptions.BILINEAR);
atlas.load();
PhysicsEditorLoader loader = new PhysicsEditorLoader();
this.tMap = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.atlas, game, "maps/" + mapName + ".png", 0, 0);
this.sMap = new Sprite(0, 500, this.tMap, game.getVertexBufferObjectManager());
this.world.attachChild(sMap);
try {
loader.load(game, engine, "maps/" + mapName + ".xml", sMap, true, true);
} catch (IOException e) {
e.printStackTrace();
System.out.println("XML load failure");
}
this.sMap = new Sprite(0, 0, this.tMap, game.getVertexBufferObjectManager());
world.attachChild(sMap);
world.registerUpdateHandler(engine);
}
// .......Snip...........
// loadMap method
public void loadMap(String mapName) {
this.atlas = new BitmapTextureAtlas(game.getTextureManager(), 2048, 1024, TextureOptions.BILINEAR);
atlas.load();
final PhysicsEditorLoader loader = new PhysicsEditorLoader();
this.tMap = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.atlas, game, "maps/" + mapName + ".png", 0, 0);
this.sMap = new Sprite(0, 500, this.tMap, game.getVertexBufferObjectManager());
this.world.attachChild(sMap);
try {
loader.load(game, engine, "maps/" + mapName + ".xml", sMap, true, true);
} catch (IOException e) {
e.printStackTrace();
}
this.sMap = new Sprite(0, 0, this.tMap, game.getVertexBufferObjectManager());
world.attachChild(sMap);
world.registerUpdateHandler(engine);
}
Did i miss something? I based the above code on the example.
I've tried editing the source to point to a non-existing directory for the XML loading, after which it started complaining, indicating that the XML is found.
Edit: In case something inherently wrong with the XML is suspected, I've uploaded it for inspection here. It was created in PhysicsEditor by adding sprite, using the shape tracer to get the outline, and export as AndEngine exporter. The XML is stored in assets/maps/ with the associated sprite stored in assets/gfx/maps/
PS: Until i get this test working I'm using the trial version of PhysicsEditor. I do not believe it affects the outcome.

Compare image to actual screen

I'd like to make my Java program compare the actual screen with a picture (screenshot).
I don't know if it's possible, but I have seen it in Jitbit (a macro recorder) and I would like to implement it myself. (Maybe with that example you understand what I mean).
Thanks
----edit-----
In other words, is it possible to check if an image is showing in? To find and compare that pixels in the screen?
You may try aShot: documentation link
1) aShot can ignore areas you mark with special color.
2) aShot can provide image which display difference between images.
private void compareTowImages(BufferedImage expectedImage, BufferedImage actualImage) {
ImageDiffer imageDiffer = new ImageDiffer();
ImageDiff diff = imageDiffer
.withDiffMarkupPolicy(new PointsMarkupPolicy()
.withDiffColor(Color.YELLOW))
.withIgnoredColor(Color.MAGENTA)
.makeDiff(expectedImage, actualImage);
// areImagesDifferent will be true if images are different, false - images the same
boolean areImagesDifferent = diff.hasDiff();
if (areImagesDifferent) {
// code in case of failure
} else {
// Code in case of success
}
}
To save image with differences:
private void saveImage(BufferedImage image, String imageName) {
// Path where you are going to save image
String outputFilePath = String.format("target/%s.png", imageName);
File outputFile = new File(outputFilePath);
try {
ImageIO.write(image, "png", outputFile);
} catch (IOException e) {
// Some code in case of failure
}
}
You can do this in two steps:
Create a screenshot using awt.Robot
BufferedImage image = new Robot().createScreenCapture(new Rctangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "png", new File("/screenshot.png"));
Compare the screenshots using something like that: How to check if two images are similar or not using openCV in java?
Have a look at Sikuli project. Their automation engine is based on image comparison.
I guess, internally they are still using OpenCV for calculating image similarity, but there are plenty of OpenCV Java bindings like this, which allow to do so from Java.
Project source code is located here: https://github.com/sikuli/sikuli
Ok then, so I found an answer after a few days.
This method takes the screenshot:
public static void takeScreenshot() {
try {
BufferedImage image = new Robot().createScreenCapture(new Rectangle(490,490,30,30));
/* this two first parameters are the initial X and Y coordinates. And the last ones are the increment of each axis*/
ImageIO.write(image, "png", new File("C:\\Example\\Folder\\capture.png"));
} catch (IOException e) {
e.printStackTrace();
} catch (HeadlessException e) {
e.printStackTrace();
} catch (AWTException e) {
e.printStackTrace();
}
}
And this other one will compare the images
public static String compareImage() throws Exception {
// savedImage is the image we want to look for in the new screenshot.
// Both must have the same width and height
String c1 = "savedImage";
String c2 = "capture";
BufferedInputStream in = new BufferedInputStream(new FileInputStream(c1
+ ".png"));
BufferedInputStream in1 = new BufferedInputStream(new FileInputStream(
c2 + ".png"));
int i, j;
int k = 1;
while (((i = in.read()) != -1) && ((j = in1.read()) != -1)) {
if (i != j) {
k = 0;
break;
}
}
in.close();
in1.close();
if (k == 1) {
System.out.println("Ok...");
return "Ok";
} else {
System.out.println("Fail ...");
return "Fail";
}
}

I cant get any output from the Sample Code of Face Detection and recognition code using JavaCV on Eclipse(Juno).

I was practicing on some face recognition and detection codes using Java on JavaCv on Eclpise Juno. The Thing is i was trying to run the sample code below but i cant get the expected result or output. The sample code is as follows
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.*;
public class Demo {
public static void main(String[] args) throws Exception {
String classifierName = null;
if (args.length > 0) {
classifierName = args[0];
} else {
System.err.println("C://opencv/data/haarcascades\"haarcascade_frontalface_alt.xml\".");
System.exit(1);
}
// Preload the opencv_objdetect module to work around a known bug.
Loader.load(opencv_objdetect.class);
// We can "cast" Pointer objects by instantiating a new object of the desired class.
CvHaarClassifierCascade classifier = new CvHaarClassifierCascade(cvLoad(classifierName));
if (classifier.isNull()) {
System.err.println("Error loading classifier file \"" + classifierName + "\".");
System.exit(1);
}
// CanvasFrame is a JFrame containing a Canvas component, which is hardware accelerated.
// It can also switch into full-screen mode when called with a screenNumber.
CanvasFrame frame = new CanvasFrame("Some Title");
// OpenCVFrameGrabber uses opencv_highgui, but other more versatile FrameGrabbers
// include DC1394FrameGrabber, FlyCaptureFrameGrabber, OpenKinectFrameGrabber,
// PS3EyeFrameGrabber, VideoInputFrameGrabber, and FFmpegFrameGrabber.
FrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start();
// FAQ about IplImage:
// - For custom raw processing of data, getByteBuffer() returns an NIO direct
// buffer wrapped around the memory pointed by imageData.
// - To get a BufferedImage from an IplImage, you may call getBufferedImage().
// - The createFrom() factory method can construct an IplImage from a BufferedImage.
// - There are also a few copy*() methods for BufferedImage<->IplImage data transfers.
IplImage grabbedImage = grabber.grab();
int width = grabbedImage.width();
int height = grabbedImage.height();
IplImage grayImage = IplImage.create(width, height, IPL_DEPTH_8U, 1);
IplImage rotatedImage = grabbedImage.clone();
// Let's create some random 3D rotation...
CvMat randomR = CvMat.create(3, 3), randomAxis = CvMat.create(3, 1);
// We can easily and efficiently access the elements of CvMat objects
// with the set of get() and put() methods.
randomAxis.put((Math.random()-0.5)/4, (Math.random()-0.5)/4, (Math.random()-0.5)/4);
cvRodrigues2(randomAxis, randomR, null);
double f = (width + height)/2.0; randomR.put(0, 2, randomR.get(0, 2)*f);
randomR.put(1, 2, randomR.get(1, 2)*f);
randomR.put(2, 0, randomR.get(2, 0)/f); randomR.put(2, 1, randomR.get(2, 1)/f);
System.out.println(randomR);
// Objects allocated with a create*() or clone() factory method are automatically released
// by the garbage collector, but may still be explicitly released by calling release().
// You shall NOT call cvReleaseImage(), cvReleaseMemStorage(), etc.
//on objects allocated this way.
CvMemStorage storage = CvMemStorage.create();
// We can allocate native arrays using constructors taking an integer as argument.
CvPoint hatPoints = new CvPoint(3);
// Again, FFmpegFrameRecorder also exists as a more versatile alternative.
FrameRecorder recorder = new OpenCVFrameRecorder("output.avi", width, height);
recorder.start();
while (frame.isVisible() && (grabbedImage = grabber.grab()) != null) {
cvClearMemStorage(storage);
// Let's try to detect some faces! but we need a grayscale image...
cvCvtColor(grabbedImage, grayImage, CV_BGR2GRAY);
CvSeq faces = cvHaarDetectObjects(grayImage, classifier, storage,
1.1, 3, CV_HAAR_DO_CANNY_PRUNING);
int total = faces.total();
for (int i = 0; i < total; i++) {
CvRect r = new CvRect(cvGetSeqElem(faces, i));
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
cvRectangle(grabbedImage, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0);
// To access the elements of a native array, use the position() method.
hatPoints.position(0).x(x-w/10) .y(y-h/10);
hatPoints.position(1).x(x+w*11/10).y(y-h/10);
hatPoints.position(2).x(x+w/2) .y(y-h/2);
cvFillConvexPoly(grabbedImage, hatPoints.position(0), 3, CvScalar.GREEN, CV_AA, 0);
}
// Let's find some contours! but first some thresholding...
cvThreshold(grayImage, grayImage, 64, 255, CV_THRESH_BINARY);
// To check if an output argument is null we may call either isNull() or equals(null).
CvSeq contour = new CvSeq(null);
cvFindContours(grayImage, storage, contour, Loader.sizeof(CvContour.class),
CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
while (contour != null && !contour.isNull()) {
if (contour.elem_size() > 0) {
CvSeq points = cvApproxPoly(contour, Loader.sizeof(CvContour.class),
storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
cvDrawContours(grabbedImage, points, CvScalar.BLUE, CvScalar.BLUE, -1, 1, CV_AA);
}
contour = contour.h_next();
}
cvWarpPerspective(grabbedImage, rotatedImage, randomR);
frame.showImage(rotatedImage);
recorder.record(rotatedImage);
}
recorder.stop();
grabber.stop();
frame.dispose();
}
}
The Output i am getting is a line printed in red and its like.
C://opencv/data/haarcascades"haarcascade_frontalface_alt.xml".
Can anybody show what i missed?
I am new to image processing and so please can anyone indicate me where i could get good tutorials and sample source codes that could teach me how to master all the in-built functions in JavaCv and their functionalities? I was working on my final year project and really need your hand on this one.
With lots of respect
Sisay
haarcascade_frontalface_alt.xml is trained classifier for detecting frontal face. It is usually present in opencv_installation_folder/opencv/data/haarcascade folder. you can give the direct path of your classifier instead of taking it from command line as
classifierName = opencv_installation_folder/opencv/data/harcascade/haarcascade_frontalface_alt.xml
that demo expects you to give it the cascade-file as an argument. it just stops, if it does not get one.
maybe you want to change the beginning like this:
public class Demo {
public static void main(String[] args) throws Exception {
String classifierName = "C:/opencv/data/haarcascades/haarcascade_frontalface_alt.xml";
if (args.length > 0) {
classifierName = args[0];
}
like that, it takes an arg from cmdline if present, else it takes the default-value

Categories

Resources