您的位置:首页 > 移动开发 > Android开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐