I custom a camera app:
I set camera display portrait as:
mCamera.setDisplayOrientation(90);
Camera display portrait Ok, But file result (Video) not display portrait .
I try code:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setRotation(90);
mCamera.setParameters(parameters);
But it not ok.
Why ?
How fix this problem? Thanks.
Manual for setDisplayOrientation() says:
Set the clockwise rotation of preview display in degrees
and then
This does not affect the order of byte array passed in onPreviewFrame(byte[], Camera), JPEG pictures, or recorded videos.
You cannot rotate saved video stream, only preview.
here is a demo which work with both portrait and landscape see here
source
https://github.com/pikanji/CameraPreviewSample
demo
https://play.google.com/store/apps/details?id=net.pikanji.camerapreviewsample&hl=en
I know your issue,
Video use Media Recorder from Camera, so you need rotate Media Recorder. use below codes should be fixed your issue.
/**
*
* #param mMediaRecorder
* #return
*/
public static MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {
/**
* Define Orientation of video in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
switch (CustomCamera.current_orientation) {
case 0:
mMediaRecorder.setOrientationHint(90);
break;
case 90:
mMediaRecorder.setOrientationHint(180);
break;
case 180:
mMediaRecorder.setOrientationHint(270);
break;
case 270:
mMediaRecorder.setOrientationHint(0);
break;
}
return mMediaRecorder;
}
Should add before prepare() method :
// Step 5: Set the preview output
/**
* Define Orientation of image in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
CustomCamera.mMediaRecorder = Utils.rotateBackVideo(CustomCamera.mMediaRecorder);
CustomCamera.mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
Thank you
Related
When we will trying to record the video using MediaRecorder video is recorded properly in android and in device it will display as like recording, but when we can play video in VLC or other player in Desktop that time it will rotate the video and it will not display properly.
and i can set the MediaRecorder setOrientationHint to 90 degree.
what's the problem for changing the orientation and Why?
we Can not directly apply fix orientation while capturing video. I mean to say that you used fix 90 degree orientation in MediaRecorder setOrientationHint. you need to set setOrientationHint(dynamic degree);
First of all you need to get display rotation and get angle using display rotation. after then set That Degree to setOrientationHint method. That will work for all. Here is code.
Display display = getWindowManager().getDefaultDisplay();
int mDisplayRotation = display.getRotation();
public int getDisplayOrientationAngle() {
Log.e("", "setDisplayOrientationAngle is call");
int angle;
// switch (MeasurementNativeActivity.DisplayRotation) {
switch (mDisplayRotation) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v("", "media recorder displayRotation: " + mDisplayRotation);
Log.v("", "media recorder angle: " + angle);
return angle;
}
mMediaRecorder.setOrientationHint(getDisplayOrientationAngle());
Extracted from the Android Documentation for MediaRecorder's setOrientationHint(int degrees) function:
This method will not trigger the source video frame to rotate during video recording, but to add a composition matrix containing the rotation angle in the output video if the output format is OutputFormat.THREE_GPP or OutputFormat.MPEG_4 so that a video player can choose the proper orientation for playback.
To sum it up, setOrientationHint just adds some sort of header to the video file that "tells" video players that they should rotate the video when playing it. In my experience, VLC player ignores this header and plays the video as it was recorded.
The only workaround I can think of would be to post-process the video by rotating it to your needs, although it seems quite a bad decision resource-wise.
I tried to modify the FacePreview.java sample provided for Android and since that code always open your camera in landscape mode, I added orientation logic in Preview.java, once we opens the camera:
mCamera.setDisplayOrientation(90);
When I ran the program I found always the Object detection i.e. cvHaarDetectObjects only works if the phone is in landscape mode, in other modes mainly in portrait, it's not at all detecting any face.
What is the reason behind this?
faces = cvHaarDetectObjects(
grayImage,
classifier,
storage,
1.1,
3,
CV_HAAR_FEATURE_MAX
| CV_HAAR_SCALE_IMAGE
| CV_HAAR_FIND_BIGGEST_OBJECT
| CV_HAAR_DO_ROUGH_SEARCH
| CV_HAAR_DO_CANNY_PRUNING);
faces.total always returns 0 when the phone is in portrait mode or orientation is different that landscape.
I tried modifying places but didn't find the expected.
It seems that in OpenCV/JavaCV Haar classifier (xml file) was trained using landscape images. You can rotate your Mat object before face detection:
public static opencv_core.Mat rotate(opencv_core.Mat src, int angle) {
opencv_core.IplImage iplSrc = src.asIplImage();
opencv_core.IplImage iplRes = opencv_core.IplImage.create(
iplSrc.height(),
iplSrc.width(),
iplSrc.depth(),
iplSrc.nChannels()
);
cvTranspose(iplSrc, iplRes);
cvFlip(iplRes, iplRes, angle);
return new opencv_core.Mat(iplRes);
So if you are loading your Mat from some image file, you can do something like that:
opencv_core.Mat mat = imread(imagePath, CV_LOAD_IMAGE_GRAYSCALE);
int orientation = ExifInterface.ORIENTATION_UNDEFINED;
try {
ExifInterface exif = new ExifInterface(imagePath);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
} catch (IOException e) {
e.printStackTrace();
}
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
mat = MatUtils.rotate(mat, 90);
break;
}
My camera app processes raw camera frames from onPreviewFrame() with OpenCV and then displays them on the screen. However, the raw frames are oriented the way the camera is mounted on the phone, which is usually not right-side up. To fix this, I rotate them manually with OpenCV, which is time-consuming.
I've looked into using setDisplayOrientation, but the documentation states that
This does not affect the order of byte array passed in onPreviewFrame
and I need the data to actually be right-side up, not just display right-side up. How can I correctly orient the raw camera data? If this is impossible, can I efficiently rotate the byte array passed to me in onPreviewFrame(), say by using OpenGL?
No, there's no way to get the API to do this for you, but to figure out how you need to rotate the data, take a look at the sample code at Camera.Parameters.setRotation. While setRotation() only affects JPEGs, you want to apply the exact same amount of rotation to the data you get in onPreviewFrame() as you would to the JPEGs.
Reproducing the sample code here, with minor changes:
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;
}
mCameraOrientation = rotation; // Store rotation for later use
}
...
void onPreviewFrame(byte[] data, Camera camera) {
switch(mCameraOrientation) {
case 0:
// data is correctly rotated
break;
case 90:
// rotate data by 90 degrees clockwise
case 180:
// rotate data upside down
case 270:
// rotate data by 90 degrees counterclockwise
}
}
So you need to inherit from OrientationEventListener and override onOrientationChanged as above, and then use the calculated orientation value from there to rotate the preview frames when they come in.
setDisplayOrientation only rotates the camera vs. surface you are drawing into, if I recall correctly.
I believe you want to rotate the camera interpretation, what you may could achieve with setRotation
I am Doing a program in which we are taking photos using camera a storing it in a private folder.From that it fetching images and displaying it in a grid view.on Clicking the grid view it showing the fullscreen image.
The trouble i am facing is when the camera is in portrait mode the image quality is perfect.But If the camera is in landscape mode it showing streched image How can i overcome this.
Hi have a look at this below code. before saving your captured image do the following process. it will save the images in portrait mode. hope this will help you.
int rotation = -1;
rotation = ((WindowManager)getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getOrientation();
Matrix rotator = new Matrix();
switch (rotation) {
case (Surface.ROTATION_0):
break;
case (Surface.ROTATION_90):
rotator.postRotate(270);
break;
case (Surface.ROTATION_180):
rotator.postRotate(180);
break;
case (Surface.ROTATION_270):
rotator.postRotate(90);
break;
// screen_{width,height} are applied before the rotate, so we don't
// need to change them based on rotation.
bmp_ss = Bitmap.createBitmap(bmp_ss, 0, 0, screen_width, screen_height, rotator, false);
I'm attempting to stream video using MediaRecorder on Android with the screen fixed to portrait mode (android:screenOrientation="portrait"). The camera hardware is naturally aligned to landscape mode. I can rotate the preview video display 90 degrees so the local preview displays correctly in portrait mode. However the captured video is still 90 degrees out:
Camera mCamera;
MediaRecorder mMediaRecorder;
...
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
Parameters params = mCamera.getParameters();
params.setRotation(90);
mCamera.setParameters(params);
mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
The params.setRotation seems to have no effect whatsoever on the captured video. My target API is Android 2.2. My test hardware is Android 3.1.
Any ideas on how to rotate the captured video? Or is it not even possible?
Try using this:
mediaRecorder.setOrientationHint(rotation); // eg rotation=270
I know your issue,
Video use Media Recorder from Camera, so you need rotate Media Recorder. use below codes should be fixed your issue.
/**
*
* #param mMediaRecorder
* #return
*/
public static MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) {
/**
* Define Orientation of video in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
switch (CustomCamera.current_orientation) {
case 0:
mMediaRecorder.setOrientationHint(90);
break;
case 90:
mMediaRecorder.setOrientationHint(180);
break;
case 180:
mMediaRecorder.setOrientationHint(270);
break;
case 270:
mMediaRecorder.setOrientationHint(0);
break;
}
return mMediaRecorder;
}
Should add before prepare() method :
// Step 5: Set the preview output
/**
* Define Orientation of image in here,
* if in portrait mode, use value = 90,
* if in landscape mode, use value = 0
*/
CustomCamera.mMediaRecorder = Utils.rotateBackVideo(CustomCamera.mMediaRecorder);
CustomCamera.mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface());
Thank you