ImageAnalysis 用例 CameraX 人脸检测

Posted

技术标签:

【中文标题】ImageAnalysis 用例 CameraX 人脸检测【英文标题】:ImageAnalysis usecase CameraX Facedetection 【发布时间】:2021-07-23 14:57:12 【问题描述】:

我正在尝试开发一款使用 CameraXMLKit Facedetecion API 分析相机实时帧的应用。它在预览用例中工作正常,但图像分析用例根本不起作用。

我不明白为什么,因为我正在关注最新的官方文档。我的代码:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    previewView = findViewById(R.id.previewView);
    if (previewView == null) 
        Toast.makeText(this,
            "PreviewView not found",
            Toast.LENGTH_SHORT).show();
    
    iv = findViewById(R.id.face_image_view);
    if (iv == null) 
        Toast.makeText(this,
            "ImageView not found",
            Toast.LENGTH_SHORT).show();
    

    cameraProviderFuture = ProcessCameraProvider.getInstance(this);

    cameraProviderFuture.addListener(() - > 
        try 
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
            if (allPermissionsGranted()) 
                bindPreview(cameraProvider);
                Log.i(TAG, "here1");
             else 
                ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSION);
            


         catch (ExecutionException | InterruptedException e) 
            // No errors need to be handled for this Future.
            // This should never be reached.
        
    , ContextCompat.getMainExecutor(this));


void bindPreview(@NonNull ProcessCameraProvider cameraProvider) 
    cameraProvider.unbindAll();

    //bind preview
    Preview preview = new Preview.Builder()
        .build();

    CameraSelector cameraSelector = new CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
        .build();

    preview.setSurfaceProvider(previewView.getSurfaceProvider());

    //bind image analysis
    ImageAnalysis imageAnalysis =
        new ImageAnalysis.Builder()
        .setTargetResolution(new Size(previewView.getWidth(), previewView.getHeight()))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .build();

    imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() 
        @Override
        public void analyze(@NonNull ImageProxy imageProxy) 

            int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();

            Log.i(TAG, "here analyzer");
            @SuppressLint("UnsafeOptInUsageError") Image mediaImage = imageProxy.getImage();
            if (mediaImage != null) 
                InputImage image =
                    InputImage.fromMediaImage(mediaImage, rotationDegrees);

                initDrawingUtils(image);

                //START configuration of the facedetector
                FaceDetectorOptions realTimeOpts =
                    new FaceDetectorOptions.Builder()
                    .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
                    .build();

                FaceDetector detector = FaceDetection.getClient(realTimeOpts);
                //END of configuration of face detector

                // START detector
                detector.process(image)
                    .addOnSuccessListener(
                        new OnSuccessListener < List < Face >> () 
                            @Override
                            public void onSuccess(List < Face > faces) 
                                if (!faces.isEmpty()) 
                                    //Get information about detected faces
                                    processFaces(faces);
                                 else 
                                    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
                                    Log.i(TAG, "vuoto");
                                
                            
                        )
                    .addOnFailureListener(
                        e - > 
                            e.printStackTrace();
                        );
            
        
    );

    Log.i(TAG, "here4");

    //add preview and analysis to the lifecycle
    cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageAnalysis);

    Log.i(TAG, "here5");

代码永远不会到达分析器,因此不会处理实时帧。有人可以帮帮我吗?

【问题讨论】:

代码对我来说看起来是正确的。如果你能创建一个最小的可重现示例并将其放在 GitHub 上,我可以帮你调试。 我在 imageAnalysis.setAnalyzer 中使用“Runnable::run”而不是“executor”解决了 【参考方案1】:

不确定这是否是主要问题,但您似乎在处理图像后忘记关闭 ImageProxy。尝试将此侦听器添加到 process 方法返回的值:

.addOnCompleteListener(task -> imageProxy.close());

来自文档:

如果您正在使用 CameraX API,请确保在使用完 ImageProxy 后关闭它,例如,通过将 OnCompleteListener 添加到从 process 方法返回的 Task 中。有关示例,请参见快速入门示例应用中的 VisionProcessorBase 类。

【讨论】:

感谢您的回答,但无论如何都不起作用【参考方案2】:

回答有点晚,反正我今天也遇到并解决了同样的问题。

您应该在analyze 方法的末尾调用ImageProxy.close(),这将允许传送下一张图像进行分析:

imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() 
    @Override
    public void analyze(@NonNull ImageProxy imageProxy) 
        int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();

        @SuppressLint("UnsafeOptInUsageError") 
        Image mediaImage = imageProxy.getImage();
        if (mediaImage != null) 
            ...
        

        imageProxy.close() // <-- Add this line
    

【讨论】:

以上是关于ImageAnalysis 用例 CameraX 人脸检测的主要内容,如果未能解决你的问题,请参考以下文章

CameraX ImageAnalysis 设置 TargetResolution 小于 640x480

如何使用 Android CameraX ImageAnalysis 提高帧速率?

Android CameraX 多个分析器

如何在android studio中获取camera2 api中的每一帧,例如camera api中的PreviewCallback和camerax中的ImageAnalysis.Analyzer?

Android CameraX 分析图像流

Camerax 图像分析:将图像转换为 bytearray 或 ByteBuffer