Android裝置上opencv開發映像格式

來源:互聯網
上載者:User

標籤:opencv   c++   android   yuv   jni   

Windows的映像格式和Android行動裝置上的映像格式存在差異,使得處理存在一些問題!簡單來講


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" />

一些小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);/*這是唯一值,也可以不設定。*/
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格式的,一般是YUV420SP,而Android提供的SurfaceView、GLSurfaceView、TextureView等控制項只支援RGB格式的渲染,因此我們需要一個演算法來解碼。也就是做資料的轉化。


2.資料的轉換(+JNI 的方法  總共有三種):


第一種方式:

@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)對一幀YUV420資料編碼後發送 高(97%) 幀間壓縮,按幀傳輸 低(2 fps) 低(20 Kbps)  可以遠距離
對一幀資料用GZIP庫壓縮後發送(很奇葩的做法) 較高(70%~80%) 幀內壓縮,按幀傳輸 低(5 fps) 較高(300 Kbps)  可以遠距離
對一幀資料用JPEG方式壓縮後傳輸 一般(60%左右) 幀內壓縮,按幀傳輸 高(25 fps) 高(170 Kbps)  可以遠距離(頻寬允許的話)
<span style="background-color: rgb(255, 255, 255);">BitmapFactory.decodeByteArray</span>
據說也很慢!

其實可以用它獲得資料:

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


第二種:


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

第三種:

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。


Android裝置上opencv開發映像格式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.