前言
新的项目用了百度的人脸识别,然后开开心心的集成了百度的人脸识别sdk,非常perfect,so easy.然而项目的应用场景需要横屏使用,但是百度这个坑爹的货,只给了一个竖屏demo,去百度提工单,然而说你们自己适配,我去你大爷的。骂归骂,可咱也得解决不是,好在我们的平板是固定的,只需要适配一个就行,下面我来放大招了。先看效果图,
image.png image.png正文
其实呢,想适配横屏也非常简单,只需要修改一下几个方向参数即可,这几个方向含义,我也不细说了,主要就是1,相机的预览方向,Camera.DisplayOrientation,2 图像的预览方向,Camera.getParameters.setRotation, 3,相机的传感器方向,这个咱不能修改,因为这是固件安装固定的,前面两个,我们可以自由修改,只要能跟相机传感器方向匹配,就能获得完美的效果,我修改的地方,我做了注释,看代码吧
//1,修改这个类的这个方法
CameraImageSource.java
//TODO--输入源
public CameraImageSource(Context context) {
this.context = context;
// Log.e("camera","orientation:="+context.getResources().getConfiguration().orientation);
cameraControl = new Camera1Control(getContext());
cameraControl.setCameraFacing(cameraFaceType);
//TODO---横屏90,竖屏0
cameraControl.setDisplayOrientation((context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) ? CameraView.ORIENTATION_HORIZONTAL : CameraView.ORIENTATION_PORTRAIT);
cameraControl.setOnFrameListener(new ICameraControl.OnFrameListener<byte[]>() {
@Override
public void onPreviewFrame(byte[] data, int rotation, int width, int height) {
Log.e("camera", "setOnFrameListener onPreviewFrame: rotation:" + rotation + ",width:" + width + ",height:" + height);
int[] argb = argbPool.acquire(width, height);
if (argb == null || argb.length != width * height) {
argb = new int[width * height];
}
rotation = rotation < 0 ? 360 + rotation : rotation;
FaceDetector.yuvToARGB(data, width, height, argb, rotation, 0);
// liujinhui modify
// TODO--旋转了90或270度。高宽需要替换
if (rotation % 180 == 90) {
int temp = width;
width = height;
height = temp;
}
ImageFrame frame = new ImageFrame();
frame.setArgb(argb);
frame.setWidth(width);
frame.setHeight(height);
frame.setPool(argbPool);
ArrayList<OnFrameAvailableListener> listeners = getListeners();
for (OnFrameAvailableListener listener : listeners) {
listener.onFrameAvailable(frame);
}
}
});
}
// TODO---2,修改这个类
/**
* 5.0以下相机API的封装。
*/
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class Camera1Control implements ICameraControl {
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final int MAX_PREVIEW_SIZE = 2048;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
private int displayOrientation = CameraView.ORIENTATION_HORIZONTAL;//TODO--这里修改为90,原来是0
private int cameraId = 0;
private int flashMode;
private AtomicBoolean takingPicture = new AtomicBoolean(false);
private Context context;
private Camera camera;
private Camera.Parameters parameters;
private PermissionCallback permissionCallback;
private Rect previewFrame = new Rect();
private int preferredWidth = 1280;
private int preferredHeight = 720;
@ICameraControl.CameraFacing
private int cameraFacing = CAMERA_FACING_FRONT;
private boolean usbCamera = false;
@Override
public void setDisplayOrientation(int displayOrientation) {
this.displayOrientation = displayOrientation;
Log.e("camera","setDisplayOrientation:"+displayOrientation);
}
/**
* {@inheritDoc}
*/
@Override
public void refreshPermission() {
startPreview(true);
}
/**
* {@inheritDoc}
*/
@Override
public void setFlashMode(@FlashMode int flashMode) {
if (this.flashMode == flashMode) {
return;
}
this.flashMode = flashMode;
updateFlashMode(flashMode);
}
@Override
public int getFlashMode() {
return flashMode;
}
@Override
public void setCameraFacing(@CameraFacing int cameraFacing) {
this.cameraFacing = cameraFacing;
}
@Override
public void setUsbCamera(boolean usbCamera) {
this.usbCamera = usbCamera;
}
@Override
public void start() {
startCamera();
}
public void isUsbCamera() {
}
private SurfaceTexture surfaceTexture;
private void startCamera() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
if (permissionCallback != null) {
permissionCallback.onRequestPermission();
}
return;
}
if (camera == null) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == cameraFacing) {
cameraId = i;
}
}
camera = Camera.open(cameraId);
}
if (parameters == null) {
parameters = camera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
surfaceTexture = new SurfaceTexture(11);
parameters.setRotation((displayOrientation == CameraView.ORIENTATION_HORIZONTAL) ? 0 : 90); // TODO--图片的预览方向,原来是90,我设置为0
int rotation = ORIENTATIONS.get(displayOrientation);
Log.e("camera", "camera rotation:" + rotation+",displayOrientation:"+displayOrientation);
camera.setDisplayOrientation(rotation);//TODO---相机的预览反向
//TODO---设备方向,
try {
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {//TODO--相机预览回调
// Log.e("onPreviewFrame", "onPreviewFrame");
Camera.Size size = camera.getParameters().getPreviewSize();
Log.e("camera", "camera.getParameters().getPreviewSize() :height:" + size.height + ",width:" + size.width);
int rotation = getSurfaceOrientation();//TODO--这里原来是{# getSurfaceOrientation()},改成0
Log.e("camera", "getSurfaceOrientation :" + rotation + ",displayorientation:" + displayOrientation);
if (cameraFacing == ICameraControl.CAMERA_FACING_FRONT) {
//TODO--镜像--180旋转 android自带的摄像头和接usb摄像头,图片有180旋转,用usb摄像头注释下面的代码,
if (!usbCamera) {
if (rotation == 90 || rotation == 270) {
rotation = (rotation + 180) % 360;
}
}
}
Log.e("camera", "getSurfaceOrientation :" + rotation + ",rotation % 180 == 90:" + (rotation % 180 == 90));
if (rotation % 180 == 90) {
previewView.setPreviewSize(size.height, size.width);//,TODO--这里回调的是旋转的图片
} else {
previewView.setPreviewSize(size.width, size.height);
}
onFrameListener.onPreviewFrame(data, rotation, size.width, size.height);
}
});
camera.setPreviewTexture(surfaceTexture);
if (textureView != null) {
surfaceTexture.detachFromGLContext();
textureView.setSurfaceTexture(surfaceTexture);
}
} catch (IOException e) {
e.printStackTrace();
}
opPreviewSize(preferredWidth, preferredHeight);
}
private TextureView textureView;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void setTextureView(TextureView textureView) {
this.textureView = textureView;
if (surfaceTexture != null) {
surfaceTexture.detachFromGLContext();
textureView.setSurfaceTexture(surfaceTexture);
}
}
@Override
public void stop() {
if (camera != null) {
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
@Override
public void pause() {
if (camera != null) {
camera.stopPreview();
}
setFlashMode(FLASH_MODE_OFF);
}
@Override
public void resume() {
takingPicture.set(false);
if (camera == null) {
startCamera();
}
}
private OnFrameListener onFrameListener;
@Override
public void setOnFrameListener(OnFrameListener listener) {
this.onFrameListener = listener;
}
@Override
public void setPreferredPreviewSize(int width, int height) {
this.preferredWidth = Math.max(width, height);
this.preferredHeight = Math.min(width, height);
}
@Override
public View getDisplayView() {
return null;
}
private PreviewView previewView;
@Override
public void setPreviewView(PreviewView previewView) {
this.previewView = previewView;
setTextureView(previewView.getTextureView());
}
@Override
public PreviewView getPreviewView() {
return previewView;
}
@Override
public void takePicture(final OnTakePictureCallback onTakePictureCallback) {
if (takingPicture.get()) {
return;
}
switch (displayOrientation) {
case CameraView.ORIENTATION_PORTRAIT:
parameters.setRotation(90);
break;
case CameraView.ORIENTATION_HORIZONTAL:
parameters.setRotation(0);
break;
case CameraView.ORIENTATION_INVERT:
parameters.setRotation(180);
break;
default:
parameters.setRotation(90);
break;
}
Camera.Size picSize =
getOptimalSize(preferredWidth, preferredHeight, camera.getParameters().getSupportedPictureSizes());
parameters.setPictureSize(picSize.width, picSize.height);
camera.setParameters(parameters);
takingPicture.set(true);
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
camera.cancelAutoFocus();
try {
camera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
camera.startPreview();
takingPicture.set(false);
if (onTakePictureCallback != null) {
onTakePictureCallback.onPictureTaken(data);
}
}
});
} catch (RuntimeException e) {
e.printStackTrace();
camera.startPreview();
takingPicture.set(false);
}
}
});
}
@Override
public void setPermissionCallback(PermissionCallback callback) {
this.permissionCallback = callback;
}
public Camera1Control(Context context) {
this.context = context;
Log.e("camera", "Camera1Control------------");
}
// 开启预览
private void startPreview(boolean checkPermission) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
if (checkPermission && permissionCallback != null) {
permissionCallback.onRequestPermission();
}
return;
}
camera.startPreview();
}
private void opPreviewSize(int width, @SuppressWarnings("unused") int height) {
Camera.Size optSize;
if (parameters != null && camera != null && width > 0) {
optSize = getOptimalSize(width, height, camera.getParameters().getSupportedPreviewSizes());
Log.e("camera", "getOptimalSize:width:" + optSize.width + ",height:" + optSize.height);//TODO--设置最佳预览尺寸
parameters.setPreviewSize(optSize.width, optSize.height);
// camera.setDisplayOrientation(getSurfaceOrientation());
// camera.stopPreview();
try {
camera.setParameters(parameters);
} catch (RuntimeException e) {
e.printStackTrace();
}
camera.startPreview();
}
}
private Camera.Size getOptimalSize(int width, int height, List<Camera.Size> sizes) {
Camera.Size pictureSize = sizes.get(0);
List<Camera.Size> candidates = new ArrayList<>();
for (Camera.Size size : sizes) {
if (size.width >= width && size.height >= height && size.width * height == size.height * width) {
// 比例相同
candidates.add(size);
} else if (size.height >= width && size.width >= height && size.width * width == size.height * height) {
// 反比例
candidates.add(size);
}
}
if (!candidates.isEmpty()) {
return Collections.min(candidates, sizeComparator);
}
for (Camera.Size size : sizes) {
if (size.width > width && size.height > height) {
return size;
}
}
return pictureSize;
}
private Comparator<Camera.Size> sizeComparator = new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
return Long.signum((long) lhs.width * lhs.height - (long) rhs.width * rhs.height);
}
};
private void updateFlashMode(int flashMode) {
switch (flashMode) {
case FLASH_MODE_TORCH:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
break;
case FLASH_MODE_OFF:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
break;
case ICameraControl.FLASH_MODE_AUTO:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
break;
default:
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
break;
}
camera.setParameters(parameters);
}
protected int getSurfaceOrientation() {
switch (displayOrientation) {
case CameraView.ORIENTATION_HORIZONTAL:
return 0;
case CameraView.ORIENTATION_INVERT:
return 180;
default:
return 90;
}
}
@Override
public Rect getPreviewFrame() {
return previewFrame;
}
}
结尾
好了,很简单就能改好了,为了方便大家测试,我把我申请的测试 FaceLogin-Sample-Android-demo上传上来,给大家用,不用谢我。让人无语的百度,连个人工客服都没有,差评
网友评论