I have problem with face detection. When I change the orientation of my device from landscape to portrait, face detection fails.
I am unable to find a solution. This is what I tried:
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
mCamera = Camera.open(camIdx);
Camera.Parameters params = mCamera.getParameters();
params.set("orientation", "portrait");
//params.set("rotation", 90);
mCamera.setDisplayOrientation(90);
//params.setRotation(90);
//params.setPictureSize(640, 480);
mCamera.setParameters(params);
mCamera.startPreview();
}
Whenever I change the orientation of my device, I did'nt got face detect .
please anybody help me, i did try all thinks but not able detect face.
I don't know if your are doing live detection or still images, but this might help if you are trying to detect faces for still portraits. Take the image you have from the camera in portrait mode and put them in to a imageview that you define in java. The imageview should be set to be wider than it is tall. Now that you have the imageView with the correct dimensions and a portrait loaded on it, save the view as a bitmap using this:
view.setDrawingCacheEnabled(true);
Bitmap b = view.getDrawingCache();
Use face detection on the resulting bitmap. This should work because faceDetection is technically looking at a landscape image with a black background.
Also face detection doesn't work for portraits mode, period.
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
Related
I am trying to capture video in a custom view. I can display video in correct orientation via Camera.setDisplayOrientation(rotation), but recorded video is still in landscape mode. I cannot capture video correctly in portrait mode.
I tested https://github.com/googlesamples/android-Camera2Video and it has the same problem too.
I am calling setCameraOrientation() method after Camera.open(currentCameraId) after checking for permissions.
private void setCameraOrientation()
{
int rotation = getRotation();
mCamera.setDisplayOrientation(rotation);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(rotation);
mCamera.setParameters(parameters);
}
private int getRotation()
{
Display display = getWindowManager().getDefaultDisplay();
int rotation = 0;
switch (display.getRotation())
{
case Surface.ROTATION_0:
rotation = 90;
break;
case Surface.ROTATION_90:
rotation = 0;
break;
case Surface.ROTATION_180:
rotation = 270;
break;
case Surface.ROTATION_270:
rotation = 180;
break;
}
return rotation;
}
This lets me display video in correct orientation. But when after I stop MediaRecorder and check for saved file, I see 90 degrees rotated video with bad aspect ratio. I checked this via pulling to my computer and in another fragment which has VideoView element. My prepareRecorder method is:
private boolean prepareRecorder()
{
mCamera.lock();
mCamera.unlock();
recorder = new MediaRecorder();
recorder.setCamera(mCamera);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
if (!mIsMute)
{
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setProfile(profile);
}
else
{
recorder.setOutputFormat(profile.fileFormat);
recorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
recorder.setVideoFrameRate(profile.videoFrameRate);
recorder.setVideoEncoder(profile.videoCodec);
recorder.setVideoEncodingBitRate(profile.videoBitRate);
}
recorder.setMaxDuration(maxVideoDuration - videoProgress);
String fileName = StorageUtil.sharedUtil().getExternalStorageDir() + File.separator + String.format(
fileNameFormat, videoCount);
recorder.setOutputFile(fileName);
recorder.setPreviewDisplay(surfaceHolder.getSurface());
try
{
recorder.prepare();
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
and then I just call recorder.start();
By the way I tried recorder.setOrientationHint(90); just before recoreder.prepare(); but it does not do anything. I can display correct orientation but cannot save.
I have a similar need. Portrait mode worked for me. The only difference in my code vs. yours is that I don't set rotation in the CameraParameters, just setDisplayOrientation on the camera and mediaRecorder.setOrientationHint(90);
// Camera.Parameters parameters = mCamera.getParameters();
// parameters.setRotation(rotation);
// mCamera.setParameters(parameters);
I have the right orientation now, but somehow, the recorded video has a strange meta-data, a square aspect ratio. So, some more work to do there. Will post update.
I ran into a similar issue. Here is the code that I have for handling the rotation on recording. This is using the camera api and not the camera2 api:
private void setCameraDisplayOrientation() {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(mCameraId, info);
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
Log.d(TAG, "Orientation: " + String.valueOf(result));
mCamera.setDisplayOrientation(result);
}
I know there are already questions like this, but none solved it. I took some help and figured out basic code that I need to change the camera with respect to the display.
cameraInfo=new Camera.CameraInfo();
camera.getCameraInfo(camId,cameraInfo);
int angle=0;
int rotation = getActivity().getWindowManager().getDefaultDisplay()
.getRotation();
switch(rotation)
{
case Surface.ROTATION_0:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 0");
camera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 90");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_180:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 180");
camera.setDisplayOrientation(0);
break;
case Surface.ROTATION_270:
parameters.setPreviewSize(s.width, s.height);
Log.i(TAGR, "THE ROATTION IS 270");
camera.setDisplayOrientation(180);
break;
default:
camera.setDisplayOrientation(0);
break;
}
}
However, I am unable to get the correct display preview with respect to the rotation of the device. I have tried several different combination of angles. However, none gave me the correct output. I am attaching the images of my preview. Please explain the solution to the problem. Moreover, I want to know what position of my device corresponds to angles 0,90,180, and 270. In other words, is 0 corresponds to portrait or landscape orientation?.
Images :
The landscape is inverted in this one. I tried setting the rotation by 180 when ROTATION_180. Doing so did not work out, as the other orientation (in landscape) became inverted
The upside down orientation does not do anything. The desired result is to bring the click button down with correct preview. I don't have any idea why this is not working. I have tried several values in each rotation, but none solved this issue.
I am a beginner, so please explain in detail. Thanks.
You should check CameraInfo.orientation for the device. Note that this property gives rotation from the natural display orientation, given for the device by Display.getRotation().
If your custom camera app uses android.hardware.camera2 API, this compensation will happen automatically.
If your custom camera activity does not lock the screen orientation, then it will be subject to "reverse landscape" glitch, and needs special treatment which involves OrientationEventListener.
You can rotate the image like this before preview:
public static Bitmap rotateImage(Bitmap bitmapSrc) {
Matrix matrix = new Matrix();
matrix.postRotate(previewRotation);
return Bitmap.createBitmap(bitmapSrc, 0, 0,
bitmapSrc.getWidth(), bitmapSrc.getHeight(), matrix, true);
}
"previewRotation" can be got from:
private static void setCameraDisplayOrientation(Context mContext, android.hardware.Camera.CameraInfo info) {
int rotation = ((CameraActivity) mContext).getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
previewRotation = (info.orientation + degrees) % 360;
previewRotation = (360 - previewRotation) % 360; // compensate the mirror
} else { // back-facing
previewRotation = (info.orientation - degrees + 360) % 360;
}
mCameraInstance.setDisplayOrientation(previewRotation);
}
Im trying to rotate my camera when the device rotates, iv tried several methods, but none of them seem to work on all devices.
//This Works on my nexus 5 but not on my Samsung galaxy tab
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (mHolder.getSurface() == null)
{
return;
}
try
{
mCamera.stopPreview();
Camera.Parameters parameters = mCamera.getParameters();
parameters.set("orientation", "landscape");
int rotation = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int orientation = getContext().getResources().getConfiguration().orientation;
if (rotation == Surface.ROTATION_0) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(0);
} else {
mCamera.setDisplayOrientation(90);
}
}
else if (rotation == Surface.ROTATION_90) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mCamera.setDisplayOrientation(270);
}
}
else if (rotation == Surface.ROTATION_180) {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mCamera.setDisplayOrientation(180);
}
}
else if (rotation == Surface.ROTATION_270) {
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mCamera.setDisplayOrientation(90);
}
}
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
}
catch (Exception e) {
}
}
// and i tried this, which is part of the documentation and it doesnt work on my nexus 5:
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
Does someone have a working solution for all devices?
Although I'm not exactly sure what's your issue from the code you provided, here are few things one has to got right when using Camera API and image rotation on Android (the old one - on API <21)
1. You have to take in account the orientation of the image sensor.
The orientation of the sensor means its angle to the device native use-mode. (that's what actually does the google snippet you are using) For phones this is usually being set to portrait, on tablets to landscape.
Here is an excerpt from the documentation, it can make pain in head for a while, but that's just how things work.
For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270.
2. Frontfacing camera preview is being mirrored
If you use frontfacing camera, you have to take in account the implicit mirroring.
3. These rules are only meant for rotating the Camera preview
This is important. All this is only meant to allow you to display correctly rotated preview frames on the device screen. Once you take an actual picture, you have to rotate it once again to suit your needs. For front-facing images this might mean mirroring it yourself,...You can see the result of this "weirdness" among all apps on Android. Just take picture in hangouts and share it right away. On various phones you gotta get somewhat weirdly rotated image as the result.
4. OEMs does not adhere to specs all the time
All I can say, is that probably no solution will be hasslefree, we got some issues with some particular devices. (as usual on Android:)
5. Use the CWAC Camera library
We found this library to be a superior wrapper around the official Camera APIs. Solving practically all of the issues I did mention.
I'm trying to make a custom camera app. I'm taking pictures from the front facing camera without preview, but the resulting images are rotated according to the front camera orientation.
I searched through a lot of post here at stack, also the one described here in the android docs.
This is the solution that I came up with:
private void prepareCamera(Activity a){
//Rotation
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT,info);
int rotation = a.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
Log.d("TEST","rotation: "+rotation);
switch(rotation){
case Surface.ROTATION_0: degrees = 0; break; //Natural orientation
case Surface.ROTATION_90: degrees = 90; break; //Landscape left
case Surface.ROTATION_180: degrees = 180; break; //Upside down
case Surface.ROTATION_270: degrees = 270; break; //Landscape right
}
Log.d("TEST","degrees: "+degrees);
int result = (info.orientation + degrees) % 360;
Log.d("TEST","result: "+result);
result = (360 - result) % 360; //Compensate the mirror
Log.d("TEST","result: "+result);
//camera.setDisplayOrientation(result);
//Parameters
Camera.Parameters params = camera.getParameters();
params.setRotation(result);
params.setJpegQuality(100);
camera.setParameters(params);
//Preview
SurfaceView view = new SurfaceView(context);
try{
camera.setPreviewDisplay(view.getHolder());
}catch(IOException e){
throw new RuntimeException(e);
}
camera.startPreview();
}
It works, but I have two problems
1) I have the line, wich I took from the android docs, that "compensates the mirror". If I don't delete that line the pictures are well rotated according to the camera orientation, but they are overpassed by 180ยบ. If I delete it the pictures are fine. I want to understand the why, if someone can please explain me.
I think its because that example code that I took from the docs its made for the SurfaceView, and it calls setDisplayOrientation(result);, when I'm using the results in .setRotation(result);. Maybe it has something to do with it?
2) When I'm testing I can rotate my phone to all directions but Upside down and get the pictures well rotated. But when I put the phone upside down, they are rotate 90, but upside down. As they were processed like Natural orientation. Maybe android wont track upside down rotation? If so, why would they with a case in the example provided by them.
Please look at setRotation() sample:
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
mParameters.setRotation(rotation);
}
Display.getRotation(), unlike orientation sensor, is limited to orientations that your current Activity supports. On some devices, the portrait upside-down orientation is not supported by system.
I'm using the camera to show preview only (not to take pictures or record videos).
The app is always in portrait mode (landscape mode is disabled).
The camera preview is always rotated 90 degrees ccw and I can't change it
(neither with setDisplayOrientation nor with p.set("orientation", "portrait" ) and p.set("rotation", 90) ).
Is the preview ALWAYS rotated like this or is it device dependent? If it was always like this in portrait mode, I could just rotate the image afterwards.
Or is there a way to set up the camera correctly? I've read a lot of threads about this but no answer worked for me (Galaxy s2, Android v2.3)
To force portrait orientation:
set android:screenOrientation="portrait" in your AndroidManifest.xml and call camera.setDisplayOrientation(90); before calling camera.startPreview();
I have not tested on the GS2 but it works on every phone I have tested on.
Note: setDisplayOrientation was added in API Level 8
I have coded the app for only Portrait Mode.
camera.setDisplayOrientation(90);
Will make the Camera to rotate to 90 degree and This may result in not suitable Orientation for some devices in android
In order to get the Correct Preview for all android devices use the following code which is refereed in developers site.
Below you have to send your activity, cameraId = back is 0 and for Front camera is 1
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
//int currentapiVersion = android.os.Build.VERSION.SDK_INT;
// do something for phones running an SDK before lollipop
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
This is how to set the setDisplayOrientation for camera which will perfectly for all android devices.