设置 ImageAnalyzer 和 PreviewView 的宽高相同
Set width and height of ImageAnalyzer and PreviewView the same
我有一个简单的设置:
preview = new Preview.Builder().build();
preview.setSurfaceProvider(mPreviewView.createSurfaceProvider());
imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(mPreviewView.getWidth(),mPreviewView.getHeight())).build();
imageAnalysis.setAnalyzer(executor, new PaperImageAnalyser());
ImageAnalyzer:
@SuppressLint("UnsafeExperimentalUsageError")
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
Image mediaImage = imageProxy.getImage();
if (mediaImage != null) {
InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
Log.e("madieaimage",mediaImage.getHeight() + " and with" + mediaImage.getWidth()); //480 and with640
Log.e("inputimage", image.getHeight() + " and width" + image.getWidth()); //480 and width640
Log.e("imageproxy", image.getHeight() + " and width" + image.getWidth()); //480 and width640
Log.e("cameraimp previewview ", CameraImp.mPreviewView.getBitmap().getHeight() + " and widht" + CameraImp.mPreviewView.getBitmap().getWidth()); //2145 and widht1080
image = InputImage.fromBitmap(CameraImp.mPreviewView.getBitmap(),0); //analyzes much better cause resolution is set but its not good practise right?
}
//analyze with image...
}
问题是我从分析方法收到的图像分辨率比预览视图分辨率 (widht/height) 小得多,因此导致图像不是很好识别。
如果我使用预览视图的位图,我基本上可以获得整个屏幕的图片,这对分析来说效果更好,但我认为这是不好的做法?
所以我的问题是:是否可以设置我在上面尝试过的 ImageAnalyzer 的分辨率(例如 setTargetResolution)?
或者处理此类问题的最佳方法是什么?
If I use the bitmap of the previewview I get the entire pic of the
screen basically which works better for the analyzation, but thats bad
practice I assume?
是的,这在性能方面是不好的做法,因为缓冲区复制非常昂贵。
So my question is: Is it possible to set the resolution of the
ImageAnalyzer (eg setTargetResolution) I tried above?
在某些设备上是可能的,例如,将两个分辨率都设置为 1080p。但是,不能保证它在任何地方都能正常工作,因为相机硬件可能不支持它。此外,根据您的使用场景,高分辨率图像分析也可能是一种不好的做法,因为分析通常不需要如此高分辨率。
请问为什么要求Preview和ImageAnalysis的分辨率一样?
我刚遇到同样的问题,我想为 PreviewView 和 ImageCapture 使用更高的分辨率,为 ImageAnalysis 使用更小的分辨率,但我希望它们在纵横比和内容上看起来相同。
然而,在某些特定分辨率下,ImageAnalysis 和 ImageCapture 中的图像看起来相同,但它们比 PreviewView 上的图像更宽。
我通过将 PreviewView 的 scaleType
设置为 FIT_CENTER
来解决这个问题,因为它的默认值是 FILL_CENTER,如果相机预览纵横比不正确,这将导致预览被裁剪与其容器不匹配:
previewView.scaleType = PreviewView.ScaleType.FIT_CENTER
并且,为确保 ImageAnalysis 纵横比尽可能接近 PreviewView:
val highSize = Size(3000, 4000)
val preview = Preview.Builder().setTargetResolution(highSize).build()
val imgCaptured = ImageCapture.Builder().setTargetResolution(highSize).build()
preview.setSurfaceProvider(previewView.surfaceProvider)
// bind empty lifycycle with id to get camera
val supportSizes = getSupportedSizes(camera, 0)
val analysisSize = getNearestSize(supportSizes, 480, 640, 30f)
val analyzer = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setOutputImageRotationEnabled(true)
.setTargetResolution(analysisSize).build()
analyzer.setAnalyzer(...)
cameraProvider.unbindAll()
val camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, imgCaptured, analyzer)
fun getSupportedSizes(camera: Camera, device: Int): Array<Size!>{
val cInfo = camera.cameraInfo
val camChars = Camera2CameraInfo.extractCameraCharacteristics(cInfo)
val configs: StreamConfigurationMap? =
camChars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
if (configs == null) {
Log.i(TAG, "get camera out sizes fail, config empty")
return
}
val sensorRotate = camChars.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
return configs.getOutputSizes(ImageFormat.JPEG)
}
fun getNearestSize(sizes: Array<Size!>, inWidth: Int, inHeight: Int, aspectWeight: Float = 1f): Size? {
if (inWidth <= 0 || inHeight <= 0 || device !in cameraInfoMap) return null
val requireArea = inWidth * inHeight
val requireAspect = inHeight * 1f / inWidth
var bestSize: Size? = null
var minDiff: Float = 10000f
Log.i(TAG, "find near size for aspect: ${requireAspect}, $inWidth * $inHeight, weight: $aspectWeight")
for (size in sizes) {
val curArea = size.width * 1f * size.height
val curAspect = size.height * 1f / size.width
val curDiff = abs(curAspect - requireAspect) * aspectWeight + abs(curArea / requireArea - 1)
if (bestSize == null || minDiff > curDiff) {
Log.i(TAG, "better size: $size, diff: $curDiff")
bestSize = size
minDiff = curDiff
}
}
return bestSize
}
最后,我可以得到小分辨率的图像进行分析,高分辨率的图像用于预览和捕获,具有相同的纵横比并且看起来相同!
我有一个简单的设置:
preview = new Preview.Builder().build();
preview.setSurfaceProvider(mPreviewView.createSurfaceProvider());
imageAnalysis = new ImageAnalysis.Builder().setTargetResolution(new Size(mPreviewView.getWidth(),mPreviewView.getHeight())).build();
imageAnalysis.setAnalyzer(executor, new PaperImageAnalyser());
ImageAnalyzer:
@SuppressLint("UnsafeExperimentalUsageError")
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
Image mediaImage = imageProxy.getImage();
if (mediaImage != null) {
InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
Log.e("madieaimage",mediaImage.getHeight() + " and with" + mediaImage.getWidth()); //480 and with640
Log.e("inputimage", image.getHeight() + " and width" + image.getWidth()); //480 and width640
Log.e("imageproxy", image.getHeight() + " and width" + image.getWidth()); //480 and width640
Log.e("cameraimp previewview ", CameraImp.mPreviewView.getBitmap().getHeight() + " and widht" + CameraImp.mPreviewView.getBitmap().getWidth()); //2145 and widht1080
image = InputImage.fromBitmap(CameraImp.mPreviewView.getBitmap(),0); //analyzes much better cause resolution is set but its not good practise right?
}
//analyze with image...
}
问题是我从分析方法收到的图像分辨率比预览视图分辨率 (widht/height) 小得多,因此导致图像不是很好识别。
如果我使用预览视图的位图,我基本上可以获得整个屏幕的图片,这对分析来说效果更好,但我认为这是不好的做法?
所以我的问题是:是否可以设置我在上面尝试过的 ImageAnalyzer 的分辨率(例如 setTargetResolution)?
或者处理此类问题的最佳方法是什么?
If I use the bitmap of the previewview I get the entire pic of the screen basically which works better for the analyzation, but thats bad practice I assume?
是的,这在性能方面是不好的做法,因为缓冲区复制非常昂贵。
So my question is: Is it possible to set the resolution of the ImageAnalyzer (eg setTargetResolution) I tried above?
在某些设备上是可能的,例如,将两个分辨率都设置为 1080p。但是,不能保证它在任何地方都能正常工作,因为相机硬件可能不支持它。此外,根据您的使用场景,高分辨率图像分析也可能是一种不好的做法,因为分析通常不需要如此高分辨率。
请问为什么要求Preview和ImageAnalysis的分辨率一样?
我刚遇到同样的问题,我想为 PreviewView 和 ImageCapture 使用更高的分辨率,为 ImageAnalysis 使用更小的分辨率,但我希望它们在纵横比和内容上看起来相同。
然而,在某些特定分辨率下,ImageAnalysis 和 ImageCapture 中的图像看起来相同,但它们比 PreviewView 上的图像更宽。
我通过将 PreviewView 的 scaleType
设置为 FIT_CENTER
来解决这个问题,因为它的默认值是 FILL_CENTER,如果相机预览纵横比不正确,这将导致预览被裁剪与其容器不匹配:
previewView.scaleType = PreviewView.ScaleType.FIT_CENTER
并且,为确保 ImageAnalysis 纵横比尽可能接近 PreviewView:
val highSize = Size(3000, 4000)
val preview = Preview.Builder().setTargetResolution(highSize).build()
val imgCaptured = ImageCapture.Builder().setTargetResolution(highSize).build()
preview.setSurfaceProvider(previewView.surfaceProvider)
// bind empty lifycycle with id to get camera
val supportSizes = getSupportedSizes(camera, 0)
val analysisSize = getNearestSize(supportSizes, 480, 640, 30f)
val analyzer = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setOutputImageRotationEnabled(true)
.setTargetResolution(analysisSize).build()
analyzer.setAnalyzer(...)
cameraProvider.unbindAll()
val camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, imgCaptured, analyzer)
fun getSupportedSizes(camera: Camera, device: Int): Array<Size!>{
val cInfo = camera.cameraInfo
val camChars = Camera2CameraInfo.extractCameraCharacteristics(cInfo)
val configs: StreamConfigurationMap? =
camChars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
if (configs == null) {
Log.i(TAG, "get camera out sizes fail, config empty")
return
}
val sensorRotate = camChars.get(CameraCharacteristics.SENSOR_ORIENTATION) ?: 0
return configs.getOutputSizes(ImageFormat.JPEG)
}
fun getNearestSize(sizes: Array<Size!>, inWidth: Int, inHeight: Int, aspectWeight: Float = 1f): Size? {
if (inWidth <= 0 || inHeight <= 0 || device !in cameraInfoMap) return null
val requireArea = inWidth * inHeight
val requireAspect = inHeight * 1f / inWidth
var bestSize: Size? = null
var minDiff: Float = 10000f
Log.i(TAG, "find near size for aspect: ${requireAspect}, $inWidth * $inHeight, weight: $aspectWeight")
for (size in sizes) {
val curArea = size.width * 1f * size.height
val curAspect = size.height * 1f / size.width
val curDiff = abs(curAspect - requireAspect) * aspectWeight + abs(curArea / requireArea - 1)
if (bestSize == null || minDiff > curDiff) {
Log.i(TAG, "better size: $size, diff: $curDiff")
bestSize = size
minDiff = curDiff
}
}
return bestSize
}
最后,我可以得到小分辨率的图像进行分析,高分辨率的图像用于预览和捕获,具有相同的纵横比并且看起来相同!