내 카메라 앱이 화면에 카메라 미리보기를 표시하고 백그라운드에서 처리합니다. 모든 장치, 제대로 카메라 미리보기 표시에Android 카메라 미리보기 데이터를 가져 오는 방법은 무엇입니까?
public final class CameraView extends SurfaceView implements
SurfaceHolder.Callback, Runnable, PreviewCallback {
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
void openCamera() {
// Called from parent activity after setting content view to CameraView
mCamera = Camera.open();
mCamera.setPreviewCallbackWithBuffer(this);
}
public void surfaceCreated(SurfaceHolder holder) {
new Thread(this).start();
// Set CameraView to the optimal camera preview size
final Camera.Parameters params = mCamera.getParameters();
final List<Camera.Size> sizes = params.getSupportedPreviewSizes();
final int screenWidth = ((View) getParent()).getWidth();
int minDiff = Integer.MAX_VALUE;
Camera.Size bestSize = null;
if (getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE) {
// Find the camera preview width that best matches the
// width of the surface.
for (Camera.Size size : sizes) {
final int diff = Math.abs(size.width - screenWidth);
if (diff < minDiff) {
minDiff = diff;
bestSize = size;
}
}
} else {
// Find the camera preview HEIGHT that best matches the
// width of the surface, since the camera preview is rotated.
mCamera.setDisplayOrientation(90);
for (Camera.Size size : sizes) {
final int diff = Math.abs(size.height - screenWidth);
if (Math.abs(size.height - screenWidth) < minDiff) {
minDiff = diff;
bestSize = size;
}
}
}
final int previewWidth = bestSize.width;
final int previewHeight = bestSize.height;
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = previewHeight;
layoutParams.width = previewWidth;
setLayoutParams(layoutParams);
params.setPreviewFormat(ImageFormat.NV21);
mCamera.setParameters(params);
int size = previewWidth * previewHeight *
ImageFormat.getBitsPerPixel(params.getPreviewFormat())/8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
public void onPreviewFrame(byte[] data, Camera camera) {
CameraView.this.notify();
}
public void run() {
mThreadRun = true;
while (mThreadRun) {
synchronized (this) {
this.wait();
processFrame(mBuffer); // convert to RGB and rotate - not shown
}
// Request a new frame from the camera by putting
// the buffer back into the queue
mCamera.addCallbackBuffer(mBuffer);
}
mHolder.removeCallback(this);
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
public void surfaceDestroyed(SurfaceHolder holder) {
mThreadRun = false;
}
}
, 그리고 (대부분의 에뮬레이터, 삼성 갤럭시 S3 등에 : 여기에 관련 코드, 응축은 (예를 들어, 오류 처리 또는 필드 선언이 표시되지 않습니다) 가능한 한 많이 .) mBuffer
에 저장된 데이터도 정확합니다 (NV21에서 RGB 로의 변환 및 회전 이후). 그러나 수 많은 장치가 onPreviewFrame에 올바른 데이터를 제공하지 않습니다. 데이터가 수신 된 후 올바르게 RGB로 변환되고 있으므로 mBuffer
에 제공된 원시 데이터에 문제가있는 것으로 보입니다. YV12 (별칭 YUV420p) 카메라 미리보기 형식과 관련된 this bug report을 보았지만 compatibility standard에 따라 지원해야하는 이전 기본 NV21 (별칭 YUV420sp)을 사용하고 있습니다 (7.5.3.2, 29 페이지 아래 참조).). 예를 들어
는이 장면을 위해 (삼성 갤럭시 탭 2에 카메라 미리보기 여기에 표시) : 탭 2에 mBuffer
에 전달
데이터를 다음과 같습니다
및 Motorola Droid 4의 모양은 다음과 같습니다.
모든 기기에서 Android 카메라 미리보기 데이터를 가져 오는 올바른 방법은 무엇입니까?
편집 :processFrame()
에 대해 OpenCV를 사용하여 RGB로 변환하고 회전합니다. this answer 및 this answer을 참조하십시오.
어떻게 표시 할 이미지를 시도 할 수 있습니다? – EJTH
@EJTH OpenCV ('COLOR_YUV420sp2RGBA' 플래그를 가진'cvtColor' 메소드)를 사용합니다. –
그래서 당신은 안드로이드 장치가 아닌 무언가에 RGB 변환을 실행하고 있다고 생각하십니까? 호기심 때문에'YuvImage.compressToJpeg()'도 비슷한 왜곡 된 이미지를 생성합니까? – EJTH