Android Camera2+OpenCv实现摄像头数据预览(数据灰度处理)

这里主要记录一些重要的点。

1:摄像头的处理

camera2+TextureView

cameraDevice!!.createCaptureSession(
            listOf(
                (imageReader!!.surface)//这个地方只要传入render的Surface
            ), captureSessionCallback, handler
)

创建好摄像头的session之后

var request = captureSessionRequest.build()
captureSession!!.setRepeatingRequest(request, null, handler)

这样在OnImageAvailableListener的回调里面就会持续的收到数据

 var image = it.acquireLatestImage()
 if (image != null) {
    var convertPlanes2NV21 = yuv420ToNv21(image)//这个地方主要把yuv的数据转成了nv21
    postData(convertPlanes2NV21,image.width,image.height,mCameraId.toInt())
    image.close()
 }

接下来就是对数据进行处理,来看下cpp里面的代码。

int index = 0;
Mat gray;
Mat rgba;
ANativeWindow_Buffer buffer;
uint8_t *dstData;
extern "C"
JNIEXPORT void JNICALL
Java_com_henry_rtmp_cameraopencv_camera_Camera2Manager_postData(JNIEnv *env, jobject thiz,
                                                                jbyteArray data_, jint w, jint h,
                                                                jint cameraId) {
    jbyte *data = env->GetByteArrayElements(data_, NULL);
    Mat src(h + h / 2, w, CV_8UC1, data);
    cvtColor(src, src, COLOR_YUV2RGBA_NV21);
    if (cameraId == 1) {//前置摄像头
        rotate(src, src, ROTATE_90_COUNTERCLOCKWISE);
        flip(src, src, 1);//水平翻转
    } else {//后置摄像头
        //顺时针旋转90度
        rotate(src, src, ROTATE_90_CLOCKWISE);
    }
//    灰色
    cvtColor(src, gray, COLOR_RGBA2GRAY);
    //增强对比度 (直方图均衡)
    equalizeHist(gray, gray);
    cvtColor(gray,rgba, COLOR_GRAY2RGBA);
//    char p[100];
//    mkdir("/sdcard/camera2/", 0777);
//    sprintf(p, "/sdcard/camera2/%d.jpg", index++);
//    imwrite(p, result);//写入到本地查看图片
    if (window) {

        ANativeWindow_setBuffersGeometry(window, rgba.cols,rgba.rows, WINDOW_FORMAT_RGBA_8888);
//            缓冲区    得到
        if (ANativeWindow_lock(window, &buffer, 0)) {
            ANativeWindow_release(window);
            window = 0;
        }
        dstData  =   static_cast<uint8_t *>(buffer.bits);
        //  *4   rgba 一个像素有4个通道
        int srclineSize = rgba.cols*4 ;
        int dstlineSize = buffer.stride *4;
        for (int i = 0; i < buffer.height; ++i) {
            memcpy(dstData+i*dstlineSize, rgba.data+i*srclineSize, srclineSize);
        }
        ANativeWindow_unlockAndPost(window);
    }
    src.release();
    gray.release();
    rgba.release();
    env->ReleaseByteArrayElements(data_, data, 0);
}

这里面主要的两个点

1:rgba和灰度图

灰度图一个像素只有一个值,这样如果拷贝数据的话就会对不齐内存,拷贝出来的结果也是显示不全,乱序。
看下图
在这里插入图片描述所以在此基础上,又做了一个灰度图转rgba的操作

cvtColor(gray,rgba, COLOR_GRAY2RGBA);
2:数据的拷贝

由于rgba一个像素有4个通道值所以此时拷贝的时候要注意

 //  *4   rgba 一个像素有4个通道
        int srclineSize = rgba.cols*4 ;
        int dstlineSize = buffer.stride *4;
        for (int i = 0; i < buffer.height; ++i) {
            memcpy(dstData+i*dstlineSize, rgba.data+i*srclineSize, srclineSize);
        }

涉及到的几个难点都在这了。测试过程中也发现分辨率设置的过大摄像头会有一点卡顿的现象,考虑应该是cpu运算和内存的快速申请和释放导致的内存抖动。如果camera输出的分辨率设置小一些这个问题会得到缓解。如果有道友有这方面好的解决办法希望能赐教。
附上源码: camera2+opencv

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rnwater

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值