国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > Android设备上opencv开发图像格式

Android设备上opencv开发图像格式

来源:程序员人生   发布时间:2015-03-30 08:26:24 阅读次数:5521次

Windows的图象格式和Android移动装备上的图象格式存在差异,使得处理存在1些问题!简单来说


Camera得到的数据是:YUV,而在移动端装备上显示的数据又是:RGBA, 但是C++程序中处理的数据又是RGB。因此需要做数据的转换。具体的操作示意图以下:

                                                           


0. 使用前的准备。


Camera的使用需要先在AndroidManifest.xml 文件当中加入camera的权限:

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

1些小Tips:

Android 2.3以后,可使用Camera.open(int)来获得特定的相机。

API Level 9以后,可使用 Camera.getCameraInfo()来查看相机是在装备前面还是后面,还可以得到图象的方向。

相机是装备资源,被所有利用同享,当利用不使用相机时应当及时释放,应当在Activity.onPause()中释放。

如果不及时释放,后续的相机要求(包括你自己的利用和其他的利用发出的)都将失败并且致使利用退出。

1. 数据的取得:

需要先打开摄像头:

Camera mCamera = Camera.open(); Camera.Parameters p = mCamera.getParameters(); p.setPreviewFormat(ImageFormat.NV21); /*这是唯1值,也能够不设置。*/
mCamera.setParameters(p); mCamera.startPreview();


Camera提供了这个接口,用法以下:( take care of the function format here):

mCamera.setPreviewCallback(new PreviewCallback(){ @Override public void onPreviewFrame(byte[] data, Camera camera) { //你的操作 } });

在这个回调里我们就可以够获得到当前帧的数据,我们可以对其进行预处理,比如紧缩、加密、殊效处理等,不过byte[]这个buffer里面的数据是YUV格式的,1般是YUV420SP,而Android提供的SurfaceView、GLSurfaceView、TextureView等控件只支持RGB格式的渲染,因此我们需要1个算法来解码。也就是做数据的转化。


2.数据的转换(+JNI 的方法  总共有3种):


第1种方式:

@Override public void onPreviewFrame(byte[] data, Camera camera) { Size size = camera.getParameters().getPreviewSize(); try{ YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null); if(image!=null){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream); Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size()); stream.close(); } }catch(Exception ex){ Log.e("Sys","Error:"+ex.getMessage()); } }

其实在取得数据流以后没必要紧缩,会下降速度:

以320×240大小的视频传输为例

方案 紧缩率 紧缩/传输方式 实时性 平均流量消耗  传输距离
用camera的回调函数发送原始的yuv420数据 0 无紧缩,按帧传输 高(20~30 fps) 很高(6.5 Mbps)太恐怖了O_O  近距离有线或无线
用MediaRecorder对yuv420进行H264硬编码后发送 高(95%) 帧间紧缩,视频流传输 高(20 fps) 低(30~70 Kbps)  可以远距离
调用本地H264编码库(JNI)对1帧YUV420数据编码后发送 高(97%) 帧间紧缩,按帧传输 低(2 fps) 低(20 Kbps)  可以远距离
对1帧数据用GZIP库紧缩后发送(很奇葩的做法) 较高(70%~80%) 帧内紧缩,按帧传输 低(5 fps) 较高(300 Kbps)  可以远距离
对1帧数据用JPEG方式紧缩后传输 1般(60%左右) 帧内紧缩,按帧传输 高(25 fps) 高(170 Kbps)  可以远距离(带宽允许的话)
<span style="background-color: rgb(255, 255, 255);">BitmapFactory.decodeByteArray</span>
听说也很慢!

其实可以用它取得数据:

byte[] tmp = stream.toByteArray();
再用其他的方法处理。


第2种:


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; }

第3种:

JNIEXPORT void JNICALL Java_com_dvt_pedDetec_pedDetec_yuv2rgb( JNIEnv* env, jobject, jint width, jint height, jbyteArray yuv,jintArray bgr) //JNIEXPORT void JNICALL Java_<package>_<class>_<function>( JNIEnv* env, jobject, <Args>) { jbyte* _yuv =env->GetByteArrayElements(yuv,0); jint* _bgr =env->GetIntArrayElements(bgr,0); Mat myuv(height+height/2, width, CV_8UC1, (uchar *)_yuv); Mat mbgr(height, width, CV_8UC3, (uchar *)_bgr); cvtColor(myuv, mbgr, CV_yuv420sp2BGR); //cvtColor(mbgr, mbgra,CV_BGR2BGRA); for display }

更正:
cvtColor(myuv, mbgr, CV_yuv420sp2BGR)
里面的更正为:CV_YUV420sp2BGR。


生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生