我试图将固定帧的图像序列(最好是30帧)保存在具有完全camera2 (GalaxyS7)功能的安卓设备上,但我无法( a)获得稳定的帧,b)甚至达到20 for (使用jpeg编码)。我已经包含了安卓camera2捕获突发太慢了的建议。
JPEG的最小帧持续时间为33.33毫秒(对于1920x1080以下的分辨率)
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputMinFrameDuration(ImageFormat.JPEG, size);每个尺寸的持续时间为0ms (与YUV_420_888相似)。
我的捕获生成器看起来如下:
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
captureBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, _exp_time);
captureBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
captureBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, _iso_value);
captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, _foc_dist);
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CONTROL_AF_MODE_OFF);
captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, _wb_value);
// https://stackoverflow.com/questions/29265126/android-camera2-capture-burst-is-too-slow
captureBuilder.set(CaptureRequest.EDGE_MODE,CaptureRequest.EDGE_MODE_OFF);
captureBuilder.set(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE, CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE_OFF);
captureBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
// Orientation
int rotation = getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));聚焦距离设置为0.0 (inf),iso设置为100,曝光时间为5ms。Whitebalance可以设置为OFF/AUTO/任何值,它不会影响下面的时间。
我使用以下命令启动捕获会话:
session.setRepeatingRequest(_capReq.build(), captureListener, mBackgroundHandler);注意:如果我请求RepeatingRequest或RepeatingBurst,这并没有什么区别。
在预览(只有纹理表面附加),一切都在30 the。但是,一旦我附加了一个图像阅读器(在HandlerThread上运行的侦听器),然后实例化如下(不节省,只测量帧之间的时间):
reader = ImageReader.newInstance(_img_width, _img_height, ImageFormat.JPEG, 2);
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);时间测量代码:
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader myreader) {
Image image = null;
image = myreader.acquireNextImage();
if (image == null) {
return;
}
long curr = image.getTimestamp();
Log.d("curr- _last_ts", "" + ((curr - last_ts) / 1000000) + " ms");
last_ts = curr;
image.close();
}
}我会周期性地重复这样的时差:
99 ms - 66 ms - 66 ms - 99 ms - 66 ms - 66 ms .
我不明白为什么要花两倍或三倍的时间来宣传jpeg的流配置图?曝光时间远低于33毫秒的帧持续时间。是否还有其他我不知道的内部处理在发生?
我尝试了同样的YUV_420_888格式,这导致了恒定的时间差为33 of。我在这里遇到的问题是,手机缺乏足够快地存储图像的带宽(我尝试了用888图像?描述的方法)。如果你知道有任何方法来压缩或编码这些图像足够快,请让我知道。
编辑:从getOutputStallDuration的文档中:“换句话说,使用重复的YUV请求将导致稳定的帧速率(假设它是30 FPS)。如果一个JPEG请求定期提交,帧速率将保持在30 FPS (只要我们每次等待上一个JPEG返回)。如果我们尝试提交一个重复的YUV + JPEG请求,那么帧速率将从30个FPS下降。”这是否意味着我需要定期请求单个捕获()?
Edit2: From https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html:“给定上述模型,应用程序的必要信息是通过使用getOutputMinFrameDuration(int,Size)的android.scaler.streamConfigurationMap字段提供的,这些信息用于确定给定流配置可能的最大帧速率/最小帧持续时间。
具体来说,应用程序可以使用以下规则来确定它可以从相机设备请求的最小帧持续时间:
让当前配置的输入/输出流集被称为S。通过使用android.scaler.streamConfigurationMap (int,Size) (及其各自的大小/格式)在getOutputMinFrameDuration中查找每个流的最小帧持续时间。让这组帧持续时间被称为F。对于任何给定的请求R,允许R的最小帧持续时间是F中所有值中的最大值。让R中使用的流被称为S_r。如果S_r中的任何流都没有一个失速时间(使用其各自的大小/格式在getOutputStallDuration(int,Size)中列出),那么F中的帧持续时间决定应用程序使用R作为重复请求时将获得的稳定帧速率。“
发布于 2017-01-17 09:02:31
JPEG输出并不是获取帧的最快方式。通过使用OpenGL将框架直接绘制到Quad上,您可以更快地完成这一任务。
对于突发捕获,一个更快的解决方案是将映像捕获到RAM,而不对它们进行编码,然后异步编码和保存它们。
在这个网站上,你可以找到很多优秀的代码相关的安卓多媒体一般。
这个特定的程序使用OpenGL从MPEG视频中获取像素数据。用相机代替视频输入并不难。您基本上可以使用上述程序中的CodecOutputSurface类中使用的纹理作为捕获请求的输出纹理。
发布于 2017-01-18 00:22:13
我发现的一个可能的解决方案是使用和转储YUV,而不将其编码为JPEG,再加上一个能够每秒保存高达95 up的微型Sd卡。(我错误地认为,YUV的图像会更大,因此,如果手机完全支持摄像头的2-流水线,写速度应该是限制因素。
通过这种设置,我能够实现以下稳定的速率:
然后,我使用python脚本对从YUV到PNG的图像进行脱机编码。
https://stackoverflow.com/questions/41522701
复制相似问题