Android將camera獲取到的YuvData在jni中轉(zhuǎn)化為Mat方法
Android中可以通過(guò)camera獲取圖像,并實(shí)時(shí)處理,不同的手機(jī)camera支持的的圖像格式不同,可以采用getCameraPreviewFormat來(lái)得到preview支持的圖像編碼格式,Android默認(rèn)使用NV21(yuv420sp)的圖像格式,因?yàn)榇蟛糠质謾C(jī)都支持。
為了達(dá)到實(shí)時(shí)處理的目的,很多時(shí)候我們將得到的yuv數(shù)據(jù)直接傳入jni中的c++使用,減少上層轉(zhuǎn)化圖像格式的過(guò)程yuv420本身屬于單通道圖像,若圖像處理中只需要獲取灰度圖像,可以在c++中直接通過(guò)Mat構(gòu)造函數(shù)構(gòu)造生成灰度圖像,代碼如下:
/* * ImageProcessing.cpp * 實(shí)時(shí)顯示canny算子結(jié)果 */ #include <jni.h> #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc_c.h> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; Mat * mCanny = NULL; extern "C" jboolean Java_my_project_MyRealTimeImageProcessing_CameraPreview_ImageProcessing( JNIEnv* env, jobject thiz, jint width, jint height, jbyteArray NV21FrameData, jintArray outPixels) { jbyte * pNV21FrameData = env->GetByteArrayElements(NV21FrameData, 0); //輸入yuv數(shù)據(jù) jint * poutPixels = env->GetIntArrayElements(outPixels, 0); //輸出結(jié)果的int數(shù)據(jù) if ( mCanny == NULL ) { mCanny = new Mat(height, width, CV_8UC1); } Mat mGray(height, width, CV_8UC1, (unsigned char *)pNV21FrameData); //構(gòu)建灰度圖時(shí)構(gòu)造函數(shù) Mat mResult(height, width, CV_8UC4, (unsigned char *)poutPixels); IplImage srcImg = mGray; IplImage CannyImg = *mCanny; IplImage ResultImg = mResult; cvCanny(&srcImg, &CannyImg, 80, 100, 3); cvCvtColor(&CannyImg, &ResultImg, CV_GRAY2BGRA); env->ReleaseByteArrayElements(NV21FrameData, pNV21FrameData, 0); env->ReleaseIntArrayElements(outPixels, poutPixels, 0); return true; }
若圖像處理時(shí)需要彩色圖像,則需要先將nv21類(lèi)型的數(shù)據(jù)轉(zhuǎn)化為yuv格式,再將yuv轉(zhuǎn)化為BGR彩色圖像,構(gòu)造yuv時(shí)的構(gòu)造函數(shù)和直接構(gòu)造灰度圖有些不同,在YUV420中一個(gè)像素對(duì)應(yīng)一個(gè)Y,一個(gè)2*2的小方塊對(duì)應(yīng)一個(gè)UV,對(duì)于所有YUV420圖像,它們的Y值排列是完全相同的,因?yàn)橹挥衁的圖像就是灰度圖像。YUV420sp與YUV420p的數(shù)據(jù)格式它們的UV排列在原理上是完全不同的。420p它是先把U存放完后,再存放V,也就是說(shuō)UV它們是連續(xù)的。而420sp它是UV、UV這樣交替存放的。對(duì)于一個(gè)YUV420在內(nèi)存中存放的大?。?/p>
Y = width*height U = Y/4 v = Y/4
所以獲取灰度圖只需要Y的數(shù)據(jù)大小就可以,所以構(gòu)造函數(shù)中寬高都是圖像的寬高,而要獲取YUV彩色圖像則需要獲取的內(nèi)存長(zhǎng)度為width*height*3/2
構(gòu)造函數(shù)中圖像高度需再加上1/2*height,代碼如下:
JNIEXPORT int JNICALL Java_com_ProjectName_nativecaller_ClassName_readYUV420SP(JNIEnv *env, jclass clz, jbyteArray yuv,jint len,jint height,jint width) { jbyte * pBuf = (jbyte*)env->GetByteArrayElements(yuv, 0); Mat image(height + height/2,width,CV_8UC1,(unsigned char *)pBuf); //注意這里是height+height/2 Mat mBgr; cvtColor(image, mBgr, CV_YUV2BGR_NV21); imwrite("/mnt/sdcard/readYuv.jpg",mBgr); env->ReleaseByteArrayElements(yuv, pBuf, 0); return 0; }
以上這篇Android將camera獲取到的YuvData在jni中轉(zhuǎn)化為Mat方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
android端微信支付V3版本地簽名統(tǒng)一下單詳解
本篇文章主要介紹了android端微信支付V3版本地簽名統(tǒng)一下單,具有一定的參考價(jià)值,有興趣的同學(xué)可以了解一下。2016-11-11Android中GridView布局實(shí)現(xiàn)整體居中方法示例
最近在工作中遇到了GridView布局的相關(guān)問(wèn)題,通過(guò)查找相關(guān)資料終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于Android中GridView布局實(shí)現(xiàn)整體居中的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒。2017-09-09Android中findViewById返回為空null的快速解決辦法
這篇文章主要介紹了Android中findViewById返回為空null的快速解決辦法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06Android Intent調(diào)用 Uri的方法總結(jié)
這篇文章主要介紹了Android Intent調(diào)用 Uri的方法總結(jié)的相關(guān)資料,這里整理了Android Intent 調(diào)用Uri的常用方法,需要的朋友可以參考下2017-09-09設(shè)備APP開(kāi)發(fā)環(huán)境配置細(xì)節(jié)介紹
隨著工業(yè)自動(dòng)化的不斷發(fā)展,設(shè)備APP也越來(lái)越重要,本文就設(shè)備APP開(kāi)發(fā)軟件配置細(xì)節(jié)做一個(gè)深入詳解2022-09-09Android 實(shí)現(xiàn)長(zhǎng)按彈出PopupMenu 菜單欄
這篇文章主要介紹了Android 實(shí)現(xiàn)長(zhǎng)按彈出PopupMenu 菜單欄,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Android 使用viewpager實(shí)現(xiàn)無(wú)限循環(huán)(定時(shí)+手動(dòng))
這篇文章主要介紹了Android 使用viewpager實(shí)現(xiàn)無(wú)限循環(huán)(定時(shí)+手動(dòng))的相關(guān)資料,需要的朋友可以參考下2015-11-11