android studio cmake配置opencv3.2.0
下载:opencv
我下的是3.2.0
解压后将OpenCV-android-sdk\sdk\native\libs文件夹下的所有文件夹复制到项目的app\libs文件夹下
将OpenCV-android-sdk\sdk\native\jni文件夹下的include文件夹复制到项目的app\libs文件夹下
在CMakeLists.txt文件添加代码
#支持-std=gnu++11 set(CMAKE_VERBOSE_MAKEFILE on) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") set(distribution_DIR ../../../../libs) include_directories(libs/include)
add_library(OpenCV_java3 SHARED IMPORTED ) set_target_properties( OpenCV_java3 PROPERTIES IMPORTED_LOCATION ${distribution_DIR}/${ANDROID_ABI}/libopencv_java3.so )
target_link_libraries( native-lib ${log-lib} OpenCV_java3 )
配置build.gradle文件在android{}内添加代码
externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions" abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } }
android studio ->File->New->Import Module将OpenCV-android-sdk\sdk\java和项目关联起来
在AndroidManifest.xml内添加权限
<uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/> <uses-feature android:name="android.hardware.camera.front" android:required="false"/> <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
在布局文件内添加代码
<org.opencv.android.JavaCameraView android:id="@+id/activity_camera_view" android:layout_width="match_parent" android:layout_height="match_parent" opencv:show_fps="true" opencv:camera_id="any"/>
MainActivity
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2{ static { System.loadLibrary("native-lib"); } private Mat rgba; private Mat gray; private CameraBridgeViewBase mOpenCvCameraView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mOpenCvCameraView = findViewById(R.id.activity_camera_view); mOpenCvCameraView.setVisibility(CameraBridgeViewBase.VISIBLE); mOpenCvCameraView.setCvCameraViewListener(this); } @Override public void onCameraViewStarted(int width, int height) { rgba = new Mat(height, width, CvType.CV_8UC4); gray = new Mat(height, width, CvType.CV_8UC1); } @Override public void onCameraViewStopped() { rgba.release(); gray.release(); } @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { rgba = inputFrame.rgba(); gray = inputFrame.gray(); nativeProcessFrame(gray.getNativeObjAddr(), rgba.getNativeObjAddr()); return rgba; } @Override public void onPointerCaptureChanged(boolean hasCapture) { } @Override public void onPause() { super.onPause(); if (mOpenCvCameraView != null){ mOpenCvCameraView.disableView(); } } @Override public void onResume() { super.onResume(); if (!OpenCVLoader.initDebug()) { } else { mOpenCvCameraView.enableView(); } } @Override public void onDestroy() { super.onDestroy(); if (mOpenCvCameraView != null){ mOpenCvCameraView.disableView(); } } public native void nativeProcessFrame(long gray,long rgba); }
c++代码
extern "C" JNIEXPORT void JNICALL Java_com_example_opencv_MainActivity_nativeProcessFrame(JNIEnv *env, jobject instance, jlong gray, jlong rgba) { // TODO cv::Mat& g = *(cv::Mat *) gray; cv::Mat& r = *(cv::Mat *) rgba; std::vector<cv::KeyPoint> v; cv::Mat resized; resize(g, resized, cv::Size(g.cols, g.rows )); cv::Ptr<cv::ORB> orb = cv::ORB::create(); orb->detect(resized, v); for (int i = 0; i < v.size(); ++i) { const cv::KeyPoint& kp = v[i]; circle(r, cv::Point((int) kp.pt.x , (int) kp.pt.y ), 5, cv::Scalar(255, 0, 0, 255)); } }
启动后发现画面是旋转90度的
修改CameraBridgeViewBase代码
protected void deliverAndDrawFrame(CvCameraViewFrame frame) { Mat modified; if (mListener != null) { modified = mListener.onCameraFrame(frame); } else { modified = frame.rgba(); } boolean bmpValid = true; if (modified != null) { try { Utils.matToBitmap(modified, mCacheBitmap); } catch(Exception e) { Log.e(TAG, "Mat type: " + modified); Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight()); Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); bmpValid = false; } } if (bmpValid && mCacheBitmap != null) { Canvas canvas = getHolder().lockCanvas(); if (canvas != null) { canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); if (BuildConfig.DEBUG) Log.d(TAG, "mStretch value: " + mScale); //开始修改 canvas.save(); //竖屏时以中心为圆点,旋转90度 canvas.rotate(90,canvas.getWidth()/2f,canvas.getHeight()/2f); //根据角度宽高互换,在JavaCameraView内重新计算mScale //int width = canvas.getHeight(); //int height = canvas.getWidth(); int width = canvas.getWidth(); int height = canvas.getHeight(); Rect rect = new Rect(); if (mScale != 0) { rect.left = (int)((width- mScale*mCacheBitmap.getWidth()) / 2); rect.top = (int)((height - mScale*mCacheBitmap.getHeight()) / 2); rect.right = (int)((width - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()); rect.bottom = (int)((height - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight()); } else { rect.left = (width - mCacheBitmap.getWidth()) / 2; rect.top = (height - mCacheBitmap.getHeight()) / 2; rect.right = (width - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(); rect.bottom = (height - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight(); } canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()), rect, null); canvas.restore(); //修改结束 if (mFpsMeter != null) { mFpsMeter.measure(); mFpsMeter.draw(canvas, 20, 30); } getHolder().unlockCanvasAndPost(canvas); } } }
上面的方法只是旋转画布,图像还是不对的,还是原来旋转90度的,无法正常计算,做人脸识别时根本识别不了人脸
参考
http://blog.csdn.net/aaron121314/article/details/53516037
进行旋转
2017/09/08更新
按上边的方法虽然图片方向对了,可是还是无法正常显示,图片的长宽明显不对
进行如下修改就可以正常显示了
MainActivity中
@Override public void onCameraViewStarted(int width, int height) { rgba = new Mat(); gray = new Mat(); } @Override public void onCameraViewStopped() { if (rgba != null) { rgba.release(); } if (gray != null) { gray.release(); } } @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { Mat r = inputFrame.rgba(); Mat g = inputFrame.gray(); Core.transpose(r, rgba); Imgproc.resize(rgba, r, rgba.size(), 0.0D, 0.0D, 0); Core.flip(r, r, 1); Core.transpose(g, gray); Imgproc.resize(gray, g, gray.size(), 0.0D, 0.0D, 0); Core.flip(g, g, 1); return r; }
CameraBridgeViewBese中
protected void AllocateCache() { mCacheBitmap = Bitmap.createBitmap( mFrameHeight,mFrameWidth, Bitmap.Config.ARGB_8888); }
将宽高对调一下,图片就可以正常显示了
这是竖屏,横屏没实验,如果横屏显示不对的话,就要判断一下横竖屏再进行参数设置
下一篇准备写基于Camera2的JavaCameraView,Camera2还是挺坑的