OpenCV向JNI层的参数转换
??????? 九層之臺,起于累土;千里之堤毀于蟻穴;成者半于九十。最近工程項目完全可以調試,卻最后在 OpenCV向JNI層的參數轉換?這個節點上遇到麻煩,看來得好好的思考一番,仔細尋找其中的紕漏。
一、實例
????????根據可運行的openCv sample,可以用與人臉檢測的函數是這樣的:
//貌似 必須要特殊編寫,便可以默認調用!wishchin! public Mat onCameraFrame(CvCameraViewFrame inputFrame) {mRgba = inputFrame.rgba();mGray = inputFrame.gray();if (mAbsoluteFaceSize == 0) {int height = mGray.rows();if (Math.round(height * mRelativeFaceSize) > 0) {mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);}mNativeDetector.setMinFaceSize(mAbsoluteFaceSize);}MatOfRect faces = new MatOfRect();if (mDetectorType == JAVA_DETECTOR) {if (mJavaDetector != null)mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGEnew Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());}else if (mDetectorType == NATIVE_DETECTOR) {if (mNativeDetector != null)mNativeDetector.detect(mGray, faces);//Detect 面部的代碼,使用C++!wishchin!}else {Log.e(TAG, "Detection method is not selected!");}//0.2.把檢測到的框畫在圖片上!wishchin!Rect[] facesArray = faces.toArray();for (int i = 0; i < facesArray.length; i++){Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3); }if (mNativeDetector != null){//Detect 使用C++!wishchin!//mCamParam.dof6CamRecog(mGray,mCamParam);//具體函數已經轉移!}return mRgba; }函數分析:
主要處理過程:
對應CPP內的JNI接口:
JNIEXPORT void JNICALL Java_com_example_feeljulygpsmap_FeelJulyGpsMap_nativeDetect (JNIEnv * jenv, jclass,jlong thiz,jlong imageGray, jlong faces) {LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect enter");try{vector<Rect> RectFaces;((DetectionBasedTracker*)thiz)->process(*((Mat*)imageGray));((DetectionBasedTracker*)thiz)->getObjects(RectFaces);vector_Rect_to_Mat(RectFaces, *((Mat*)faces));}catch(cv::Exception& e){LOGD("nativeCreateObject caught cv::Exception: %s", e.what());jclass je = jenv->FindClass("org/opencv/core/CvException");if(!je)je = jenv->FindClass("java/lang/Exception");jenv->ThrowNew(je, e.what());}catch (...){LOGD("nativeDetect caught unknown exception");jclass je = jenv->FindClass("java/lang/Exception");jenv->ThrowNew(je, "Unknown exception in JNI code DetectionBasedTracker.nativeDetect()");}LOGD("Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeDetect exit"); }
二、參數解析
1.java到C++
第一層參數轉換:由Java到C++,通過jlong類型
??????? 轉換語法:
nativeDetect( mNativeObj, imageGray.getNativeObjAddr(), faces.getNativeObjAddr() );通過Mat型 .getNativeObjAddr()成員函數獲取矩陣地址,通過jlong型進行JNI參數代入對應形式:
JNIEXPORT void JNICALL Java_com_example_feeljulygpsmap_FeelJulyGpsMap_nativeDetect (JNIEnv * jenv, jclass,jlong thiz,jlong imageGray, jlong faces)函數進行運算的過程: ((DetectionBasedTracker*)thiz)->process(*((Mat*) imageGray) );涉及到的第二次參數轉化:
*((Mat*) imageGray) 把jlong型在C++層強制轉化為Mat類型的指針,供其他C++函數使用,由此完成Java層到C++層的全部語法轉換!
其中前兩個參數的作為JNI本地參數默認調用;
第三個參數jlong?thiz顧名思義即是所使用參數類的載入地址,通過獲取C++類的地址載入,由此可以使用在底層使用C++的類,并獲取C++類的類函數和成員變量。
第四個和第五個參數分別對應了java層載入的兩個mat型參數的地址,由此完成java向JNI層的陷入。
自此檢測,我的代碼和sample在語法層面完全一致,并且代入變元的語義一致,在此過程的移植方法上,理所應當是沒有錯誤的。
注意事項:不管有沒有聲明const,載入的Mat型是不能被改變的,已經初始化的mat型不能再被修改,比如
<del>*((Mat*) imageGray)</del> 為什么?難道是為了保持上層變量的完整性?
2.由C++到java層
參數變元,經過一系列運算,得到函數結果,或者以參數或者以返回值的方式向java層返回。
由C++到java層返回的語法是這樣的:
mNativeDetector.detect(mGray, faces);//Detect 面部的代碼,使用C++!wishchin!所調用的java函數: mNativeDetector.detect(mGray, faces);//Detect 面部的代碼,使用C++!wishchin! <pre name="code" class="java"> public void detect(Mat imageGray, MatOfRect faces) {nativeDetect( mNativeObj, imageGray.getNativeObjAddr(), faces.getNativeObjAddr() );} 所使用的Native函數: private static native void nativeDetect(long thiz, long inputImage, long faces);
對應CPP內的JNI接口:
JNIEXPORT void JNICALL Java_com_example_feeljulygpsmap_FeelJulyGpsMap_nativeDetect (JNIEnv * jenv, jclass,jlong thiz,jlong imageGray, jlong faces);JNI函數處理過程: ((DetectionBasedTracker*)thiz)->getObjects(RectFaces);vector_Rect_to_Mat(RectFaces, *((Mat*)faces));參數轉變的函數調用: vector_Rect_to_Mat(RectFaces, *((Mat*)faces));參數轉變函數: inline void vector_Rect_to_Mat(vector<Rect>& v_rect, Mat& mat) {mat = Mat(v_rect, true); }完成效果:
返回臉部檢測的識別框,壓入Vector,并通過函數強制轉換成 Mat型指針,
java頂層調用:
//0.2.把檢測到的框畫在圖片上!wishchin!Rect[] facesArray = faces.toArray();這樣可以通過數組轉化為java層的 CvArray 類型,以便
for (int i = 0; i < facesArray.length; i++){Core.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3); }此代碼段使用。
顯示效果為:
總結
以上是生活随笔為你收集整理的OpenCV向JNI层的参数转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王采的家居风水让你的家繁荣昌盛
- 下一篇: 图像局部显著性—线特征