我需要做的很简单,我想使用相机回调手动显示来自相机的预览,我想在真实设备上获得至少15fps.我甚至不需要颜色,我只需要预览灰度图像.来自相机的图像是YUV格式,你必须以某种方式处理它,这是主要的性能问题.我正在使用API 8.
在所有情况下,我都使用camera.setPreviewCallbackWithBuffer(),它比camera.setPreviewCallback()更快.如果我没有显示预览,我似乎无法在这里获得大约24 fps.所以没有问题.
我试过这些解决方案:
1.在SurfaceView上将相机预览显示为位图.它有效,但性能约为6fps.
baos = new ByteOutputStream();
yuvimage=new YuvImage(cameraFrame, ImageFormat.NV21, prevX, prevY, null);
yuvimage.compressToJpeg(new Rect(0, 0, prevX, prevY), 80, baos);
jdata = baos.toByteArray();
bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length); // Convert to Bitmap, this is the main issue, it takes a lot of time
canvas.drawBitmap(bmp , 0, 0, paint);
Run Code Online (Sandbox Code Playgroud)
2.在GLSurfaceView上将相机预览显示为纹理.这里我只显示亮度数据(灰度图像),这非常简单,每帧只需要一个arraycopy().我可以得到大约12fps,但我需要在预览中应用一些过滤器,看起来,它无法在OpenGL ES 1中快速完成.所以我不能使用这个解决方案.另一个问题中的一些细节.
3.使用NDK在(GL)SurfaceView上显示相机预览以处理YUV数据.我在这里找到了一个使用一些C函数和NDK 的解决方案.但我没有设法使用它,这里有更多细节.但无论如何,这个解决方案是为了返回ByteBuffer在OpenGL中将其显示为纹理,并且它不会比之前的尝试更快.所以我必须修改它以返回int []数组,可以使用canvas.drawBitmap()绘制,但我不理解C足以执行此操作.
那么,我有没有其他方法可以避免或尝试一些改进?
我正在尝试使用相机api直接拍摄照片,但这是我得到的预览:

这是调用后拍摄的图像,takePicture()它大于预览本身:

(注意:我裁剪了前两张照片的高度,以提高问题的可读性,并保持宽度不变)
我正在使用此实用程序方法在开始相机预览之前选择最佳的最佳预览尺寸:
public static Camera.Size getBestAspectPreviewSize(int displayOrientation,
int width,
int height,
Camera.Parameters parameters) {
double targetRatio = (double) width / height;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
if (displayOrientation == 90 || displayOrientation == 270) {
targetRatio = (double) height / width;
}
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Collections.sort(sizes,
Collections.reverseOrder(new SizeComparator()));
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) < minDiff) {
optimalSize = size;
minDiff …Run Code Online (Sandbox Code Playgroud) 我试图让相机框架处于预览模式.我从github运行示例项目https://github.com/googlesamples/android-Camera2Basic
我遇到的问题是在预览模式下获取帧.
这是代码:
private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
switch (mState) {
case STATE_PREVIEW: {
//HERE, HOW CAN I RETRIEVE THE CURRENT FRAME?
break;
}
case STATE_WAITING_LOCK: {
...
break;
}
case STATE_WAITING_PRECAPTURE: {
...
break;
}
case STATE_WAITING_NON_PRECAPTURE: {
...
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试获取框架的另一件事是设置mImageReader.setOnImageAvailableListener.我期望能够获得框架onImageAvailable回调,但是永远不会调用onImageAvailable.onPreviewFrame是我自己的方法,我需要将它传递给当前帧.
mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(), ImageFormat.JPEG, /*maxImages*/2);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
mTextureView.onPreviewFrame(reader.acquireNextImage().getPlanes([0].getBuffer().array());
}
};
Run Code Online (Sandbox Code Playgroud)
我做错了什么?谢谢.
我已经为此工作了好几天了.我有一个基于OpenCV/JavaCameraView的项目我试图与android.hardware.camera2.CaptureRequest我用来控制相机对光的敏感度的Android 对象集成.
该CameraBridgeViewBase.CvCameraViewListener2/JavaCameraView项目工程(我可以在屏幕上看到的图像),并在CaptureRequest项目工程(看到这一点,太),但是这两种技术在一个单一的项目组合已证明是一个很大的问题.
有没有人让这两种技术一起工作?我的目标是让摄像头处于CaptureRequest(有限的SENSOR_SENSITIVITY + SENSOR_EXPOSURE_TIME)的控制之下,但屏幕显示通过我写的OpenCV共享库过滤的流图像.
要控制相机,我可以使用这样的东西:
mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
// The camera is already closed
if (null == mCameraDevice) {
return;
}
long exposureTime = 66259688,frameDuration = 1000;
int sensitivity = 1512;
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setAutoFlash(mPreviewRequestBuilder);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, Long.valueOf(exposureTime));
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, Integer.valueOf(sensitivity));
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, Long.valueOf(frameDuration));
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest,
mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}catch (Exception e) { …Run Code Online (Sandbox Code Playgroud) 我正在使用Camera Activity来捕捉图片.我用MediaStore.EXTRA_OUTPUT额外参数调用它.图像被正确保存到提供的路径,把它保存到图库文件夹,所以我可以在"图库"应用程序中查看图像 - 我可以避免这种情况吗?
...
File file = new File(Environment.getExternalStorageDirectory(), "Test.jpg" );
iImageOutputUri = Uri.fromFile( file );
// Start camera intent to capture image
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra( MediaStore.EXTRA_OUTPUT, iImageOutputUri );
startActivityForResult( intent, CAPTURE_IMAGE );
...
Run Code Online (Sandbox Code Playgroud)
谢谢
我目前正在使用意图拍照,如下所示:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
intent.putExtra("return-data", true);
startActivityForResult(intent, CAMERA_REQUEST);
Run Code Online (Sandbox Code Playgroud)
但我真的需要将图像大小设置为尽可能接近正方形.所以在研究之后,你似乎需要做这样的事情:
Camera camera = Camera.open();
Parameters params = camera.getParameters();
List<Camera.Size> sizes = params.getSupportedPictureSizes();
// Once you will see the supported Sizes, you can define them with the method :
setPictureSize(int width, int height);
Run Code Online (Sandbox Code Playgroud)
我的问题是,这些是一起工作还是一个或两个?哪种方法最适合我的需求?
同样,我有96px到96px的盒子用于用户个人资料图片.用户拍摄照片后,我希望图像无需拉伸即可填满整个盒子.是在拍摄照片时设置尺寸的最佳方法,还是在事后改变imageView或bitmap(或......?)?或者,我应该让用户裁剪图片,我可以定义裁剪区域尺寸吗?
编辑:请参阅赏金以获取更新的问题.
我正在为Android开发相机应用程序.
一个要求是将拍摄的照片保存到设备的默认相机照片文件夹中,即Android本机相机存储的文件夹.
我怎么能弄清楚原生相机存放照片的位置 - 我的理解是,不同品牌(三星,HTC,摩托罗拉,索尼......)和型号(Galaxy Tab,Galaxy S4 ......)可能会有所不同. .)
谢谢你的关注!我想使用Android MediaCodec API对从Camera获取的视频帧进行编码,遗憾的是,我没有成功做到这一点!我仍然不熟悉MediaCodec API.以下是我的代码,我需要你的帮助来弄清楚我应该做什么.
1,相机设置:
Parameters parameters = mCamera.getParameters();
parameters.setPreviewFormat(ImageFormat.NV21);
parameters.setPreviewSize(320, 240);
mCamera.setParameters(parameters);
Run Code Online (Sandbox Code Playgroud)
2,设置编码器:
private void initCodec() {
try {
fos = new FileOutputStream(mVideoFile, false);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
mMediaCodec = MediaCodec.createEncoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",
320,
240);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mMediaCodec.configure(mediaFormat,
null,
null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
mMediaCodec.start();
inputBuffers = mMediaCodec.getInputBuffers();
outputBuffers = mMediaCodec.getOutputBuffers();
}
private void encode(byte[] data) {
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(0);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear(); …Run Code Online (Sandbox Code Playgroud) 目前我正在尝试将Camera2.Face转换为实际视图的rect,以便在Camera2 API检测到的脸部上绘制圆圈.
我可以通过以下代码获取面数及其数据到Callback中:
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
Integer mode = result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE);
Face [] faces = result.get(CaptureResult.STATISTICS_FACES);
if(faces != null && mode != null)
Log.e("tag", "faces : " + faces.length + " , mode : " + mode );
}
@Override
public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {
process(partialResult);
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
process(result);
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,我尝试使用下面的代码将Face rect转换为实际的视图坐标(似乎它不起作用):
/**
* Callback from the CameraCaptureSession.CaptureCallback …Run Code Online (Sandbox Code Playgroud) 我正在使用最新的相机插件版本拍照,我正在使用颤振示例中的代码。这是我选择相机的方式:
final cameras = await availableCameras();
final firstCamera = cameras.first;
Run Code Online (Sandbox Code Playgroud)
这是在init里面:
_cameraController = CameraController(
widget.camera,
ResolutionPreset.medium,
enableAudio: false,
);
Run Code Online (Sandbox Code Playgroud)
这是相关代码的其余部分:
Future _takePhoto(BuildContext context) async {
try {
await _initializeControllerFuture;
final path = join(
(await getTemporaryDirectory()).path,
'${DateTime.now()}.png',
);
await _cameraController.takePicture(path);
setState(() {
_imagePath = path;
});
} catch (e) {
print(e);
}
}
Run Code Online (Sandbox Code Playgroud)
之后,我将照片展示给用户,Image.file(File(_imagePath))然后将照片发送到 API。问题是有时会以错误的方向拍摄照片。(这个我很确定,因为照片在数据库中也旋转了。)例如,在3年前的小米手机上,它完美无缺,但在某些新的三星手机上,照片总是旋转。
如何确保旋转始终正确?(即使在 ios 设备上)