Android使用OpenCV合成双目裸眼3D图片(推荐Native方法)
2017-11-03 17:13
543 查看
Native中使用OpenCV
使用Native的好处:- 不需要安装OpenCV Manager
- 不需要去熟悉java层的OpenCV方法
- 使用C/C++移植方便
使用CMake
配置CMakeLists.txt
cmake_minimum_required(VERSION 3.6) ############################################ # 先设置本地opencv-sdk路径,配置库路径和include的路径 ############################################ #OpenCV set(CMAKE_VERBOSE_MAKEFILE on) #Path set(OpenCVNative_DIR E:/MyDocuments/Android/AndroidWorkSpace/OpenCV-android-sdk/sdk/native) #libs set(libs ${OpenCVNative_DIR}/libs) #include include_directories(${OpenCVNative_DIR}/jni/include) #添加导入opencv .so库 add_library(libopencv_java3 SHARED IMPORTED) set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libopencv_java3.so") #设置c特性 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -frtti") # 添加nativelib add_library( native-lib SHARED src/main/cpp/native-lib.cpp) #查找额外的库 find_library( log-lib log ) #链接native中要用的库 target_link_libraries( native-lib android log libopencv_java3 ${log-lib} )
配置app build.gradle
下面是完整的build.gradle,注意3点,
-
externalNativeBuild中配置cmake的编译属性,比如用到的cppflag,编译处理器平台
-
sourceSets中添加opencv的native库的路径
-
CMakeLists.txt的路径
android { compileSdkVersion 26 buildToolsVersion "26.0.2" defaultConfig { applicationId "com.righere.test" minSdkVersion 21 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "-frtti -fexceptions -std=c++11" abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } } } sourceSets{ main{ jniLibs.srcDirs = ['E:\\MyDocuments\\Android\\AndroidWorkSpace\\OpenCV-android-sdk\\sdk\\native\\libs'] } } externalNativeBuild { cmake { path "CMakeLists.txt" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
OpenCV的例子
下面通过一个例子简单了解Opencv4Android Native的使用,Demo的功能是将左右格式的双目图片转换成一张裸眼3D的图片,在android裸眼显示设备上显示出来。native-lib
实现将手机中的双目图像分割,然后合成为一张裸眼图片RGB像素,RGB数据再转换为Bitemap的color数据,最后传给java上层的Bitmap显示出来。分割图像
IplImage* srcImg = cvLoadImage("/sdcard/convexd.jpg", CV_LOAD_IMAGE_COLOR); int width = w; int height = h; int IMAGE_SIZE = srcImg->height * srcImg->widthStep; IplImage* dstImg[2]; IplImage* viewImg[2]; dstImg[0] = cvCreateImage(cvSize(srcImg->width/2, srcImg->height), srcImg->depth, srcImg->nChannels); dstImg[1] = cvCreateImage(cvSize(srcImg->width/2, srcImg->height), srcImg->depth, srcImg->nChannels); viewImg[0] = cvCreateImage(cvSize(width, height), srcImg->depth, srcImg->nChannels); viewImg[1] = cvCreateImage(cvSize(width, height), srcImg->depth, srcImg->nChannels); for(int i = 0; i < srcImg->height; i++) { memcpy(dstImg[0]->imageData + (i * dstImg[0]->widthStep), srcImg->imageData + i * srcImg->widthStep, dstImg[0]->widthStep); } for(int i = 0; i < srcImg->height; i++) { memcpy(dstImg[1]->imageData + (i * dstImg[1]->widthStep), srcImg->imageData + (int)(srcImg->widthStep) * 1 / 2 + i * srcImg->widthStep, dstImg[1]->widthStep); }
上面使用的是拷贝内存的方式分割图像,也可以使用opencv内置的
cvSetImageROI函数来切割图像
cvSetImageROI(srcImg, cvRect(0, 0, srcImg->width*0.5, srcImg->height)); cvCopy(srcImg, dstImg[0]); cvSetImageROI(srcImg, cvRect(srcImg->width*0.5, 0, srcImg->width*0.5, srcImg->height)); cvCopy(srcImg, dstImg[1]); cvResetImageROI(srcImg);
缩放图像
cvResize(dstImg[0], viewImg[0], CV_INTER_LINEAR); cvResize(dstImg[1], viewImg[1], CV_INTER_LINEAR);
合成图像,并将rgb子像素数据转换成Color数据
可以先看看我的前面的一篇,http://blog.csdn.net/danjuan123/article/details/78437110
Bitmap是使用sRGB数组来填充的,所以先要将RGB子像素数组转换成
int size = width * height; int* outImgrgb = new int[size]; for(int i = 0; i < height * width / 2; i ++) { outImgrgb[2*i] = 0xff; outImgrgb[2*i] = (outImgrgb[2*i] << 8) + viewImg[0]->imageData[2*i * 3 + 2]; outImgrgb[2*i] = (outImgrgb[2*i] << 8) + viewImg[0]->imageData[2*i * 3 + 1]; outImgrgb[2*i] = (outImgrgb[2*i] << 8) + viewImg[0]->imageData[2*i * 3]; outImgrgb[2*i + 1] = 0xff; outImgrgb[2*i + 1] = (outImgrgb[2*i + 1] << 8) + viewImg[1]->imageData[(2*i + 1) * 3 + 2]; outImgrgb[2*i + 1] = (outImgrgb[2*i + 1] << 8) + viewImg[1]->imageData[(2*i + 1) * 3 + 1]; outImgrgb[2*i + 1] = (outImgrgb[2*i + 1] << 8) + viewImg[1]->imageData[(2*i + 1) * 3]; }
返回color数据
jintArray result = env->NewIntArray(size); env->SetIntArrayRegion(result, 0, size, outImgrgb);
java中配置
// Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); System.loadLibrary("opencv_java3"); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native int[] splitter(int w, int h); private void splitPic(){ if(splitStatus){ int[] resultInt = splitter(w, h); Bitmap resultImg = Bitmap.createBitmap(resultInt, w, h, Bitmap.Config.ARGB_8888); imageView.setImageBitmap(resultImg); mButton_split.setText("Unsplit"); splitStatus = false; Toast.makeText(this,"OpenCV_native_split_picture_success",Toast.LENGTH_SHORT).show(); } else{ imageView.setImageResource(R.drawable.convexd); mButton_split.setText("Split"); splitStatus = true; Toast.makeText(this,"Original",Toast.LENGTH_SHORT).show(); } }
最后效果:
附上github工程地址:
https://github.com/righere/Free3DPicture.git
相关文章推荐
- 谈谈Android下载图片的方法中SoftReference的使用
- 在Android中使用OpenCv 来处理图片
- Android自定义“图片+文字”控件四种实现方法之 二--------个人最推荐的一种
- android 针对于GridView中的getView方法的bug,使用本地缓存来处理图片显示的问题
- Android 使用decodeFile方法加载手机磁盘中的图片文件
- android两种使用照相功能获取图片的方法
- Android最简单的图片裁剪方法,非使用系统裁切功能
- 【移动开发】Android中图片过大造成内存溢出,OOM(OutOfMemory)异常解决方法 推荐
- android的图片缓存universal-image-loader使用方法
- android中使用BitmapFactory的decodeStream()方法解码图片失败问题
- Android Smart Image View使用方法--从url获取图片或从通讯录获取图片,支持缓存
- 说说Android 两种为自定义组件添加属性的使用方法和区别 推荐
- android两种使用照相功能获取图片的方法
- 【Android 开发】:UI控件之显示图片控件 ImageView 的使用方法
- android中使用BitmapFactory的decodeStream()方法解码图片失败问题
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码
- 转载 Android中使用BitmapFactory的decodeStream()方法解码图片失败问题
- 生成黑白画笔,android使用系统浏览器打开网页,将Bitmap图片存储在本地JPG文件的方法
- 如何在Android中使用OpenCV 推荐
- Android使用OpenCV和FFMpeg的简单方法-开源项目javacv的使用