音视频/图像处理Android专题JNI和【NDK】

android 引入图像处理库OpenCV

2019-03-21  本文已影响246人  小小混世魔王

这里省去ndk开发环境的配置 直接进入opencv集成到Android studio中
我们在opencv官网下载到的https://opencv.org android开发包 解压压缩包结构

U$MD9(`)]]TK6WHT8H`O470.png
在项目的main文件下新建jniLibs目录 将opencv的.so文件拷贝到该目录下 ss.png
将opencv的include文件夹拷贝到cpp文件夹下
includ.png
配置cmake文件

# 设置include文件夹的地址
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

# 设置opencv的动态库
add_library(libopencv_java3
        SHARED
        IMPORTED)

set_target_properties(libopencv_java3
        PROPERTIES
        IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)


target_link_libraries( # Specifies the target library.
        native-lib libopencv_java3 jnigraphics

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

build.gradle文件 android 节点下配置

android {
.......
  sourceSets {
          main {
              jniLibs.srcDirs = ['src/main/jniLibs']
          }
      }
.......

到此我们opencv 已经配置完成 下面我们来写一个小demo验证是否配置成功

public class MainActivity extends AppCompatActivity {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView iv_show = findViewById(R.id.iv_show);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.zyz);

        BitmapUtils.counterWorld(bitmap);

        iv_show.setImageBitmap(bitmap);

    }

}

下面是利用opencv 实现的一个逆世界效果

#include <jni.h>
#include <string>
#include<opencv2/opencv.hpp>
#include "bitmap/com_youyangbo_opencv_BitmapUtils.h"
#include "bitmap/opencvHelp.h"


using namespace cv;


extern "C" void JNICALL Java_com_youyangbo_opencv_BitmapUtils_counterWorld
        (JNIEnv *env, jclass jclazz, jobject bitmap) {


    Mat src;

    bitmap2Mat(env, src, bitmap);
    int middleRows = src.rows >> 1;
    int quarterRows = middleRows >> 1;
    Mat conword_imag(src.size(), src.type());

    for (int row = 0; row < middleRows; ++row) {

        for (int col = 0; col < src.cols; ++col) {

            conword_imag.at<float>(middleRows + row, col) = src.at<float>(
                    quarterRows + row, col);
        }

    }


    for (int row = 0; row < middleRows; ++row) {
        for (int col = 0; col < src.cols; ++col) {
            conword_imag.at<float>(middleRows - row, col) = src.at<float>(quarterRows + row, col);
        }
    }


    mat2Bitmap(env, conword_imag, bitmap);
}



opencv 是c/c++的库,处理图片数据是Mat(矩阵),Android 图片表现形式是Bitmap,所以Android中的图片交给opencv处理必须先将Bitmap转化成Mat,

#include "bitmap/opencvHelp.h"
#include <android/log.h>

/**
 * bitmap 转化为矩阵(Mat)
 * @param pEnv
 * @param mat
 * @param bitmap
 */
void bitmap2Mat(JNIEnv *env, cv::Mat &mat, jobject bitmap) {

    AndroidBitmapInfo bitmap_info;
    void *pPixel = NULL;

    AndroidBitmap_getInfo(env, bitmap, &bitmap_info);

    AndroidBitmap_lockPixels(env, bitmap, &pPixel);



    //判断传入的图片是什么类型
    if (bitmap_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {//32
        //对应opncv Mat 类型  CV_8UC4
        cv::Mat temp(bitmap_info.height, bitmap_info.width, CV_8UC4, pPixel);
        temp.copyTo(mat);


    } else if (bitmap_info.format == ANDROID_BITMAP_FORMAT_RGB_565) {//16
        //对应opncv Mat 类型  CV_8UC2

        cv::Mat temp(bitmap_info.height, bitmap_info.width, CV_8UC2, pPixel);

        cv::cvtColor(temp, mat, CV_BGRA2BGR565);

    }


    AndroidBitmap_unlockPixels(env, bitmap);
}


/**
 * Mat转化为Bitmap
 * @param pEnv
 * @param mat
 * @param bitmap
 */
void mat2Bitmap(JNIEnv *env, cv::Mat &mat, jobject bitmap) {
    AndroidBitmapInfo bitmap_info;
    void *pPixel = NULL;

    AndroidBitmap_lockPixels(env, bitmap, &pPixel);

    AndroidBitmap_getInfo(env, bitmap, &bitmap_info);

    //判断传入的图片是什么类型
    if (bitmap_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {//32
        cv::Mat tmp(bitmap_info.height, bitmap_info.width, CV_8UC4, pPixel);
        //对应opncv Mat 类型  CV_8UC4
        if (mat.type() == CV_8UC4) {
            //对应bitmap   RGBA_8888
            mat.copyTo(tmp);

        } else if (mat.type() == CV_8UC2) {
            //对应bitmap   RGB_565
            cv::cvtColor(mat, tmp, CV_BGR5652BGRA);


        } else if (mat.type() == CV_8UC1) {
            //单通道 0-255 的灰度图
            cv::cvtColor(mat, tmp, CV_GRAY2BGRA);

        }

    } else if (bitmap_info.format == ANDROID_BITMAP_FORMAT_RGB_565) {//16
        cv::Mat tmp(bitmap_info.height, bitmap_info.width, CV_8UC2, pPixel);
        //对应opncv Mat 类型  CV_8UC2
        if (mat.type() == CV_8UC4) {
            //对应bitmap   RGBA_8888
            cv::cvtColor(mat, tmp, CV_BGRA2BGR565);

        } else if (mat.type() == CV_8UC2) {
            //对应bitmap   RGB_565

            mat.copyTo(tmp);

        } else if (mat.type() == CV_8UC1) {
            //单通道 0-255 的灰度图

            cv::cvtColor(mat, tmp, CV_GRAY2BGR565);
        }

    }


    AndroidBitmap_unlockPixels(env, bitmap);

}

代码运行效果:

原图: 2.jpg
经过opencv处理过的 demo.png
上一篇 下一篇

猜你喜欢

热点阅读