Android OpenCV使用4_双目摄像头双开两个预览界面,并获取当前帧图片

本篇博客其实跟OpenCV也没什么多大关系,因为是同一个项目,博客就顺溜着写了。
在自研设备开发过程中,在项目研发过程中碰到了双目摄像头双开(一个普通摄像头,一个红外摄像头)并获取当前帧的这么一个需求,我觉得有必要总结一下:

这边的demo使用的是两个Camera,本来想用两个OpenCV里的JavaCameraView,但结果并不如人意,可能还需要在康康OpenCV的源码,最终我项目中使用了JavaCameraView+Camera,如果后面研究有成,再来更新本博客

首先硬件上是必须要支持多开的,这样的话一般的手机估计是不能用来测试了,如果不支持请联系摄像头厂商和主板厂商,以下文件是必须要修改的:
Android OpenCV使用4_双目摄像头双开两个预览界面,并获取当前帧图片_第1张图片
当然我厂商回复我的截图长这样:
Android OpenCV使用4_双目摄像头双开两个预览界面,并获取当前帧图片_第2张图片
接下来就简单放一个预览demo好了:
新建一个camerademo项目,并做一下动态权限获取,我这边用的permissionsdispatcher:
GitHub:https://github.com/permissions-dispatcher/PermissionsDispatcher

接下来就是愉快的贴代码环节:
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.zhb.camerademo">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.front"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.front.autofocus"
        android:required="false" />
        
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

配置build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "com.zhb.camerademo"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    // Permission
    implementation 'com.github.hotchemi:permissionsdispatcher:3.2.0'
    annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:3.2.0'
}

MainActivity
本来想通过takePicture()方法拍照获取,结果发现在双目摄像头下,能拍摄普通摄像头的图片,但不能拍摄红外摄像头图片,调用takePicture后,红外摄像头被关闭了,我想这可能是主板系统的问题,不能速度解决的情况下,只能通过PreviewCallback预览回调获取下一帧图片

package com.zhb.camerademo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;

import java.io.IOException;

import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.RuntimePermissions;

@RuntimePermissions
public class MainActivity extends AppCompatActivity {
    SurfaceView surfaceview1;
    SurfaceHolder holder1;
    Camera mCamera1;

    SurfaceView surfaceview2;
    SurfaceHolder holder2;
    Camera mCamera2;

    ImageView imageView;

    boolean showClick1 = false;
    boolean showClick2 = false;

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

        surfaceview1 = findViewById(R.id.surfaceView1);
        holder1 = surfaceview1.getHolder();
        holder1.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                try {
                    mCamera1.setPreviewDisplay(holder);
                    mCamera1.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });

        surfaceview2 = findViewById(R.id.surfaceView2);
        holder2 = surfaceview2.getHolder();
        holder2.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                try {
                    mCamera2.setPreviewDisplay(holder);
                    mCamera2.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });

        imageView = findViewById(R.id.imageView);

        surfaceview1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showClick1 = true;
            }
        });

        surfaceview2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showClick2 = true;
            }
        });

    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mCamera1 != null){
            mCamera1.stopPreview();
            mCamera1.release();
        }

        if(mCamera2 != null){
            mCamera2.stopPreview();
            mCamera2.release();
        }
    }
    @Override
    public void onResume() {
        super.onResume();
        MainActivityPermissionsDispatcher.CAMERAWithPermissionCheck(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    public Bitmap rawByteArray2RGBABitmap2(byte[] data, int width, int height) {
        int frameSize = width * height;
        int[] rgba = new int[frameSize];

        for (int i = 0; i < height; i++)
            for (int j = 0; j < width; j++) {
                int y = (0xff & ((int) data[i * width + j]));
                int u = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 0]));
                int v = (0xff & ((int) data[frameSize + (i >> 1) * width + (j & ~1) + 1]));
                y = y < 16 ? 16 : y;

                int r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128));
                int g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128));
                int b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128));

                r = r < 0 ? 0 : (r > 255 ? 255 : r);
                g = g < 0 ? 0 : (g > 255 ? 255 : g);
                b = b < 0 ? 0 : (b > 255 ? 255 : b);

                rgba[i * width + j] = 0xff000000 + (b << 16) + (g << 8) + r;
            }

        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bmp.setPixels(rgba, 0 , width, 0, 0, width, height);
        return bmp;
    }

    public static Bitmap Bytes2Bimap(byte[] b) {
        if (b.length != 0) {
            return BitmapFactory.decodeByteArray(b, 0, b.length);
        } else {
            Log.i("zzz ", "Byte = null");
            return null;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // NOTE: delegate the permission handling to generated method
        MainActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    @NeedsPermission({
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA
    })
    void CAMERA() {
        mCamera1 = Camera.open(0);
        mCamera1.setDisplayOrientation(90);

        mCamera2 = Camera.open(1);
        mCamera2.setDisplayOrientation(90);

        mCamera1.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] bytes, Camera camera) {
                if(showClick1){
                    showClick1 = false;
                    int w = camera.getParameters().getPreviewSize().width;
                    int h = camera.getParameters().getPreviewSize().height;
                    Bitmap bitmap = rawByteArray2RGBABitmap2(bytes, w, h);
                    imageView.setImageBitmap(bitmap);
                }
            }
        });

        mCamera2.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] bytes, Camera camera) {
                if(showClick2){
                    showClick2 = false;
                    int w = camera.getParameters().getPreviewSize().width;
                    int h = camera.getParameters().getPreviewSize().height;
                    Bitmap bitmap = rawByteArray2RGBABitmap2(bytes, w, h);
                    imageView.setImageBitmap(bitmap);
                }
            }
        });

    }
}

布局layout_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <SurfaceView
        android:layout_weight="1"
        android:id="@+id/surfaceView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <SurfaceView
        android:layout_weight="1"
        android:id="@+id/surfaceView2"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

demo:https://download.csdn.net/download/u013370255/12694880

你可能感兴趣的:(Android-基础知识,android,摄像头双开)