I'm trying to draw a text on a face using android face detection API.
Right now, I did this
for(Landmark landmark : face.getLandmarks()){
if(landmark.getType() == Landmark.NOSE_BASE){
Bitmap moustache = BitmapFactory.decodeResource(resources, R.drawable.moustache);
canvas.drawText("=====", landmark.getPosition().x, landmark.getPosition().y, mIdPaint);
}
}
but turns out the text ===== is draw on top of the head, and I don't know why.
If someone need more code, just let me know
If you are drawing graphics over a live camera preview, you need to take a few things into account:
the device's rotation
the scale of the view relative to the size of the preview image
whether you are using the front facing camera (which will mirror the image)
The sample code for the face tracker demo has utility methods (translateX, translateY, scaleX, scaleY) to help with this:
https://github.com/googlesamples/android-vision/blob/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/FaceGraphic.java#L99
https://github.com/googlesamples/android-vision/blob/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/ui/camera/GraphicOverlay.java#L100
Related
I'm trying build a camera app in android using camera API.
I follow the instructions: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/ and I have built one camera app
Now i need to display preview camera inside a frame and take picture include the frame
Please see the two pictures below:
Frame in resource folder : https://i.stack.imgur.com/AaNIQ.png
The photo I want to achieve: https://i.stack.imgur.com/UWXcq.jpg
Anyone can give me suggestions or if possible give me a simple example?
I searched about this but didn't get proper example.
Thank you so much.
Half of the answer can be found here: https://stackoverflow.com/a/47240902/192373.
As for keeping the same layout for full-res picture capture, first of all make sure that you keep preview- and picture- sizes in sync. This does not mean that they must be the same, but the aspect ratios should. Some devices have weird effects when the aspect ratio changes to capture a photo.
Next, you capture the jpeg as usual, unpack it to bitmap, overlay with the frame bitmap (you may need a hi-res version of your frame here) and combine the two (based on https://stackoverflow.com/a/4863551/192373):
public Bitmap combineImages(Bitmap picture, Bitmap frame) {
Bitmap bmp = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(bmp);
comboImage.drawBitmap(picture, 0f, 0f, null);
comboImage.drawBitmap(frame, 0f, 0f, null);
return bmp;
}
I'm using Google Vision for face detection on Android. Currently my code:
public void onPreviewFrame(byte[] data, Camera camera) {
// creating Google Vision frame from a camera frame for face recognition
com.google.android.gms.vision.Frame frame = new com.google.android.gms.vision.Frame.Builder()
.setImageData(ByteBuffer.wrap(data), previewWidth,
previewHeight, ImageFormat.NV21)
.setId(frameId++)
.setRotation(com.google.android.gms.vision.Frame.ROTATION_270)
.setTimestampMillis(lastTimestamp).build();
// recognize the face in the frame
SparseArray<Face> faces = detector.detect(frame);
// wrong coordinates
float x = faces.valueAt(0).getPosition().x;
float y = faces.valueAt(0).getPosition().y;
}
The problem is that x and y are not correct and even negative sometimes. I know that to get correct coordinates it should be rotated somehow, but how exactly?
These coordinates can be negative if the face extends beyond the top and/or the left edges of the image. Even though the head may not be entirely within the photo, the face detector will estimate the bounding box of the face beyond the image bounds based upon what is visible.
The coordinates should be correct relative to the image. However, if you are drawing on a preview from the front-facing camera, note that this preview is displayed reversed (like a mirror image). In this case, you'd need to reverse the coordinates on order to draw on the preview. See an example of how this is done here:
https://github.com/googlesamples/android-vision/blob/master/visionSamples/FaceTracker/app/src/main/java/com/google/android/gms/samples/vision/face/facetracker/ui/camera/GraphicOverlay.java#L101
I want to make the area of camera preview be half of SurfaceView, so I modify the code of ContinuousCaptureActivity.
The detail is as follows:
Use GLES20.glViewport(0, 0, viewWidth / 2, viewHeight / 2); to replace https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java#L436
But the result is strange, see the picture below.
I really can not understand it and what is the right way to do it?
Who can give me some advices?
My first thought would be that you need a glClear() in there (with the viewport set to cover the entire surface) since you're no longer filling the entire surface with the blit. Otherwise you get uninitialized data, and on a tile-based architecture things can get strange.
Fiddling with the viewport isn't really the right way to go. Just draw a smaller rectangle. Use Sprite2d and change the X/Y scale factors. See TextureFromCameraActivity for an example -- you can scale the rect, zoom in, rotate, etc.
Good day,
I have weird problem with drawing image. Code and pictures say more then words.
mCamera.save();
mCamera.rotateX(rotateX);
mCamera.getMatrix(mMatrix);
mCamera.restore();
canvas.save();
canvas.setMatrix(mMatrix);
// here I draw images
...
canvas.restore();
and results are at images below. First picture have angle 0, second around 45 degree and last something more. It depend on size of area (number of bitmaps) I want to draw. I notice that when I draw bitmaps that whole fits canvas bounds, it works fine. But problem is mainly when I draw images with something like (so with part outside of canvas)
canvas.drawBitmap(image, -100, -100, null)
and images (hmm, because I'm new here, I cannot post images directly ...)
ttp://locus.asamm.cz/data/_temp/1311873666794.png
http://locus.asamm.cz/data/_temp/1311873695945.png
http://locus.asamm.cz/data/_temp/1311873782054.png
So question is, if there is any working solution or at least any tip. Also if anyone experienced can tell if drawing with OpenGL can help with this and if so, please point me to any information source that can help me with drawing bitmaps that change a lot (it's map application so user move with map), because I still cannot find any simple and clear source of info.
Thanks to all very much
It's a limitation of the 2D drawing API. To do true 3D you should use OpenGL.
I expect you are trying to produce a google maps tilt/rotate effect which I have successfull done for google maps since they don't think we need an update ;-) and I needed it for my application, even if you are using your own tiles it's basically the same thing.
One thing that helps is realize that the rotations for the Camera Matrix are performed in the upper left corner.
So you should transform to the appropriate location (dependent on axis of rotation and your expected results) and then back, something like ... the effects you are getting were very similar to mine before I read the docs and figured that out.
camera.save();
camera.rotateX(tilt); // tilt forward or backward
camera.rotateY(0);
camera.rotateZ(angle); // Rotate around Z access (similar to canvas.rotate)
camera.getMatrix(cameraMatrix);
// This moves the center of the view into the upper left corner (0,0)
// which is necessary because Matrix always uses 0,0, as it's transform point
// use the center of the canvas, or the bottom center dependent on your results
cameraMatrix.preTranslate(-centerX, -centerY);
// NOTE: Camera Rotations logically happen here when the canvas has the matrix applied
// This happens after the camera rotations are applied, moving the view back to
// where it belongs, allowing us to rotate around the center or any point we choose
// Move it back after the rotations are applied
cameraMatrix.postTranslate(centerX, centerY);
camera.restore();
canvas.concat(cameraMatrix);
The other thing to do is to oversize the container so you don't have empty space (or at least limit it) after your tilt/rotate operations, you can do that by calculating the needed oversize, the diagonal of your display works for basic rotation, + a percentage based on tilt if you are using that.
Playing around with the pre/postTranslate can can give you some interesting results.
As to moving the bitmap I am not really sure why you are doing this, probably panning, but as long as the canvas is getting filled it shouldn't matter
Update
Here is how I oversize the canvas, I tried to use the LayoutParams to do this but didn't have much luck with it so on Measure was the way to go for me.
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
if (!isInEditMode())
super.onMeasure(View.MeasureSpec.makeMeasureSpec(scaledDimensionsW,
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(scaledDimensionsH,
View.MeasureSpec.EXACTLY));
else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
I'm developing a Android board game and have a question regarding creating a board that is zoomable and scrollable. The board contains a static background, characters (players) and the actual "level" which is drawn using tiles.
My solutions is to have a collection of elements (tiles, figures, all game elements - all have x,y coordinates and width + height), a camera and a renderer that draws the collection according to cameraX,cameraY, cameraWidth and cameraHeight. So if a user would scroll to the right, the camera would just set the cameraX appropriately - and the surface is scrollable. And if a user would zoom in/out the renderer would just scale every element image appropriately.
Example code for the renderer with scrollable surface and zoom in/out
protected function draw(Canvas c){
Collection elements = collection.getElements(cameraX,cameraY,cameraWidth,cameraHeight);
if(elements.size() > 0) {
for(int i = 0; i < elements.size(); i++) {
elements.get(i).drawElement(c);
}
}
}
.
.
.
// element class drawElement function
protected drawElement function(Canvas c) {
if(this.image != null) {
int w = this.width;
int h = this.height;
if(this.zoomFactor < 1) {
w*=this.zoomFactor;
h*=this.zoomFactor;
}
c.drawBitmap(this.image,this.x,this.y,w,h);
}
}
Is this the best solutions?
Could it be achived somehow else?
Could scrolling be achived using a ScrollView?
I dont wanna use any engine, because this is for a school project.
Actually you can simplify this situation somewhat. If you are indeed seeking a flat texture plane that is simply distorted by perspective, the Android Camera class can help you. Do not confuse this with the hardware camera for taking photos. This camera is a helper class wrapped around a matrix to perform transformations on 2D objects. You can read more about this very complex rendering topic by googling "fast fourier transforms". Basically you will want to create a canvas and do your drawing in a completely 2D way. Then right before you draw to the screen, you should transform this canvas using the Camera class. Let me know if you need some clarification. There is a lot of cool mathematics going on behind the scenes!
Take a look at this sample from the Android API Demos
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html
Android graphics.Camera documentation
http://developer.android.com/reference/android/graphics/Camera.html