mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #24827 from alexlyulkov:al/java-camera-view-orientation
Added any screen orientation support for JavaCameraView
This commit is contained in:
commit
e2b2c3a35e
@ -10,9 +10,12 @@ import android.hardware.Camera.PreviewCallback;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import org.opencv.BuildConfig;
|
import org.opencv.BuildConfig;
|
||||||
|
import org.opencv.core.Core;
|
||||||
import org.opencv.core.CvType;
|
import org.opencv.core.CvType;
|
||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.core.Size;
|
import org.opencv.core.Size;
|
||||||
@ -71,28 +74,20 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
boolean result = true;
|
boolean result = true;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mCamera = null;
|
mCamera = null;
|
||||||
|
int cameraId = -1;
|
||||||
|
|
||||||
if (mCameraIndex == CAMERA_ID_ANY) {
|
if (mCameraIndex == CAMERA_ID_ANY) {
|
||||||
Log.d(TAG, "Trying to open camera with old open()");
|
boolean connected = false;
|
||||||
try {
|
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
|
||||||
mCamera = Camera.open();
|
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
|
||||||
}
|
try {
|
||||||
catch (Exception e){
|
mCamera = Camera.open(camIdx);
|
||||||
Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
|
connected = true;
|
||||||
}
|
cameraId = camIdx;
|
||||||
|
} catch (RuntimeException e) {
|
||||||
if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
|
||||||
boolean connected = false;
|
|
||||||
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
|
|
||||||
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
|
|
||||||
try {
|
|
||||||
mCamera = Camera.open(camIdx);
|
|
||||||
connected = true;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
|
|
||||||
}
|
|
||||||
if (connected) break;
|
|
||||||
}
|
}
|
||||||
|
if (connected) break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
|
||||||
@ -126,6 +121,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(localCameraIndex) + ")");
|
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(localCameraIndex) + ")");
|
||||||
try {
|
try {
|
||||||
mCamera = Camera.open(localCameraIndex);
|
mCamera = Camera.open(localCameraIndex);
|
||||||
|
cameraId = localCameraIndex;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(TAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage());
|
Log.e(TAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
@ -136,6 +132,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
if (mCamera == null)
|
if (mCamera == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int frameRotation = getFrameRotation(cameraId);
|
||||||
/* Now set camera parameters */
|
/* Now set camera parameters */
|
||||||
try {
|
try {
|
||||||
Camera.Parameters params = mCamera.getParameters();
|
Camera.Parameters params = mCamera.getParameters();
|
||||||
@ -176,8 +173,16 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
mCamera.setParameters(params);
|
mCamera.setParameters(params);
|
||||||
params = mCamera.getParameters();
|
params = mCamera.getParameters();
|
||||||
|
|
||||||
mFrameWidth = params.getPreviewSize().width;
|
int rawFrameWidth = params.getPreviewSize().width;
|
||||||
mFrameHeight = params.getPreviewSize().height;
|
int rawFrameHeight = params.getPreviewSize().height;
|
||||||
|
|
||||||
|
if (frameRotation % 180 == 0) {
|
||||||
|
mFrameWidth = params.getPreviewSize().width;
|
||||||
|
mFrameHeight = params.getPreviewSize().height;
|
||||||
|
} else {
|
||||||
|
mFrameWidth = params.getPreviewSize().height;
|
||||||
|
mFrameHeight = params.getPreviewSize().width;
|
||||||
|
}
|
||||||
|
|
||||||
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
|
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
|
||||||
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
|
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
|
||||||
@ -196,14 +201,14 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
mCamera.setPreviewCallbackWithBuffer(this);
|
mCamera.setPreviewCallbackWithBuffer(this);
|
||||||
|
|
||||||
mFrameChain = new Mat[2];
|
mFrameChain = new Mat[2];
|
||||||
mFrameChain[0] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
|
mFrameChain[0] = new Mat(rawFrameHeight + (rawFrameHeight/2), rawFrameWidth, CvType.CV_8UC1);
|
||||||
mFrameChain[1] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1);
|
mFrameChain[1] = new Mat(rawFrameHeight + (rawFrameHeight/2), rawFrameWidth, CvType.CV_8UC1);
|
||||||
|
|
||||||
AllocateCache();
|
AllocateCache();
|
||||||
|
|
||||||
mCameraFrame = new JavaCameraFrame[2];
|
mCameraFrame = new JavaCameraFrame[2];
|
||||||
mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight);
|
mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], rawFrameWidth, rawFrameHeight, frameRotation);
|
||||||
mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight);
|
mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], rawFrameWidth, rawFrameHeight, frameRotation);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
|
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
|
||||||
@ -313,7 +318,14 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
private class JavaCameraFrame implements CvCameraViewFrame {
|
private class JavaCameraFrame implements CvCameraViewFrame {
|
||||||
@Override
|
@Override
|
||||||
public Mat gray() {
|
public Mat gray() {
|
||||||
return mYuvFrameData.submat(0, mHeight, 0, mWidth);
|
mGray = mYuvFrameData.submat(0, mHeight, 0, mWidth);
|
||||||
|
|
||||||
|
if (mRotation != 0) {
|
||||||
|
Core.rotate(mGray, mGrayRotated, getCvRotationCode(mRotation));
|
||||||
|
return mGrayRotated;
|
||||||
|
} else {
|
||||||
|
return mGray;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -325,15 +337,33 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
else
|
else
|
||||||
throw new IllegalArgumentException("Preview Format can be NV21 or YV12");
|
throw new IllegalArgumentException("Preview Format can be NV21 or YV12");
|
||||||
|
|
||||||
return mRgba;
|
if (mRotation != 0) {
|
||||||
|
Core.rotate(mRgba, mRgbaRotated, getCvRotationCode(mRotation));
|
||||||
|
return mRgbaRotated;
|
||||||
|
} else {
|
||||||
|
return mRgba;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaCameraFrame(Mat Yuv420sp, int width, int height) {
|
private int getCvRotationCode(int degrees) {
|
||||||
|
if (degrees == 90) {
|
||||||
|
return Core.ROTATE_90_CLOCKWISE;
|
||||||
|
} else if (degrees == 180) {
|
||||||
|
return Core.ROTATE_180;
|
||||||
|
} else {
|
||||||
|
return Core.ROTATE_90_COUNTERCLOCKWISE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaCameraFrame(Mat Yuv420sp, int width, int height, int rotation) {
|
||||||
super();
|
super();
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
mYuvFrameData = Yuv420sp;
|
mYuvFrameData = Yuv420sp;
|
||||||
mRgba = new Mat();
|
mRgba = new Mat();
|
||||||
|
mRgbaRotated = new Mat();
|
||||||
|
mGrayRotated = new Mat();
|
||||||
|
mRotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
@ -342,10 +372,50 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb
|
|||||||
|
|
||||||
private Mat mYuvFrameData;
|
private Mat mYuvFrameData;
|
||||||
private Mat mRgba;
|
private Mat mRgba;
|
||||||
|
private Mat mRgbaRotated;
|
||||||
|
private Mat mGray;
|
||||||
|
private Mat mGrayRotated;
|
||||||
private int mWidth;
|
private int mWidth;
|
||||||
private int mHeight;
|
private int mHeight;
|
||||||
|
private int mRotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates how to rotate camera frame to match current screen orientation
|
||||||
|
*/
|
||||||
|
private int getFrameRotation(int cameraId) {
|
||||||
|
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
int screenOrientation = windowManager.getDefaultDisplay().getRotation();
|
||||||
|
int screenRotation = 0;
|
||||||
|
switch (screenOrientation) {
|
||||||
|
case Surface.ROTATION_0:
|
||||||
|
screenRotation = 0;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_90:
|
||||||
|
screenRotation = 90;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_180:
|
||||||
|
screenRotation = 180;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_270:
|
||||||
|
screenRotation = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
|
||||||
|
android.hardware.Camera.getCameraInfo(cameraId, info);
|
||||||
|
|
||||||
|
int frameRotation;
|
||||||
|
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||||
|
frameRotation = (info.orientation + screenRotation) % 360;
|
||||||
|
frameRotation = (360 - frameRotation) % 360;
|
||||||
|
} else {
|
||||||
|
frameRotation = (info.orientation - screenRotation + 360) % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frameRotation;
|
||||||
|
}
|
||||||
|
|
||||||
private class CameraWorker implements Runnable {
|
private class CameraWorker implements Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:name="FaceDetectActivity"
|
android:name="FaceDetectActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:configChanges="keyboardHidden|orientation">
|
android:configChanges="keyboardHidden|orientation">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
@ -184,8 +184,9 @@ public class FaceDetectActivity extends CameraActivity implements CvCameraViewLi
|
|||||||
|
|
||||||
mRgba = inputFrame.rgba();
|
mRgba = inputFrame.rgba();
|
||||||
|
|
||||||
if (mInputSize == null) {
|
Size inputSize = new Size(Math.round(mRgba.cols()/mScale), Math.round(mRgba.rows()/mScale));
|
||||||
mInputSize = new Size(Math.round(mRgba.cols()/mScale), Math.round(mRgba.rows()/mScale));
|
if (mInputSize == null || !mInputSize.equals(inputSize)) {
|
||||||
|
mInputSize = inputSize;
|
||||||
mFaceDetector.setInputSize(mInputSize);
|
mFaceDetector.setInputSize(mInputSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:name="Tutorial1Activity"
|
android:name="Tutorial1Activity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:screenOrientation="landscape"
|
|
||||||
android:configChanges="keyboardHidden|orientation">
|
android:configChanges="keyboardHidden|orientation">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
Loading…
Reference in New Issue
Block a user