这里主要记录一些重要的点。
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