android stdudio OpenCV NDK 開發環境搭建 之找查條形碼

開發環境

Android Studio 3.6

SDK 28

NDK:android-ndk-r17b

JAVA JDK 1.8

1,opencv sdk 下載

我這裏下載的是 3.4.8

OpenCV-3.4.8-android-sdk

下載地址

或者:https://github.com/opencv/opencv

第二步:解壓 810M

java中存放的是我們接下來使用的Android SDK

native中存放基於c/c++編譯好的本地庫文件,JNI層開發需要的頭文件和CMake文件

第三步:導入SDK

第三步:導入SDK

(1)創建一個新的工程,選擇 ndk

然後選擇 “File”-->"New"-->"Import Module",然後選擇OpenCV-3.4.8-android-sdk 中的java文件夾點擊OK“”即可;待工程構建完成之後,項目結構如下圖

native文件夾中libs目錄下面的所以文件copy到我們 app 項目的src/main/jniLibs目錄下

添加項目依賴,app 依賴 openCVLibrary348;

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.2"

    defaultConfig {
        applicationId "com.iai.myapplication"
        minSdkVersion 22
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
            }
        }
        ndk {
            // 設置支持的 SO 庫構架
            abiFilters 'armeabi-v7a' , 'arm64-v8a'//, 'x86', 'x86_64'
            ldLibs "log"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation project(path: ':openCVLibrary348')

}

修改 CMakeList.txt  

jnigraphics 這個是Bitmap 需要的;

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)
set(MY_ROOT ${CMAKE_CURRENT_LIST_DIR})
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
set(OpenCV_DIR "D:/SVN/facesdk/OpenCV-3.4.8-android-sdk/sdk/native/jni")
set(Lib_DIR ${PROJECT_SOURCE_DIR}/../bin)

macro(ADD_ALG_LIBS1)
    foreach(one ${ARGN})
        message(STATUS "Add ${one}")
        add_library(${one}  SHARED IMPORTED)
        set_target_properties(${one} PROPERTIES IMPORTED_LOCATION  ${MY_ROOT}/../jniLibs/${ANDROID_ABI}/lib${one}.so )
        #
        #message(STATUS ""
        list(APPEND ALG_DEP ${one})
    endforeach(one)
endmacro()

ADD_ALG_LIBS1(opencv_java3)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib
                       opencv_java3
                       jnigraphics
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

 

NDK 代碼

extern "C" JNIEXPORT jobject JNICALL
Java_com_iai_myapplication_MainActivity_getRectSmallImage(
        JNIEnv *env,
        jobject /* this */object, jstring path) {

    string filepath = jstring2str(env,path);
    Mat image, imageGray, imageGuussian;
    Mat imageSobelX, imageSobelY, imageSobelOut;
   // bmp2mat(env, bitmap,  image, false);
    image = imread(filepath);
    //1. 原圖像大小調整,提高運算效率
    //resize(image, image, Size(500, 300));

//    // 銳化
//	Mat sblur,usm;
//	GaussianBlur(image, sblur, Size(0, 0), 25);
//	addWeighted(image, 1.5, sblur, -0.5, 0, usm);

    //2. 轉化爲灰度圖
    cvtColor(image, imageGray, CV_RGB2GRAY);

    //3. 高斯平滑濾波
    GaussianBlur(imageGray, imageGuussian, Size(3, 3), 0);


    //4.求得水平和垂直方向灰度圖像的梯度差,使用Sobel算子
    Mat imageX16S, imageY16S;
    Sobel(imageGuussian, imageX16S, CV_16S, 1, 0, 3, 1, 0, 4);
    Sobel(imageGuussian, imageY16S, CV_16S, 0, 1, 3, 1, 0, 4);
    convertScaleAbs(imageX16S, imageSobelX, 1, 0);
    convertScaleAbs(imageY16S, imageSobelY, 1, 0);
    imageSobelOut = imageSobelX - imageSobelY;


    //5.均值濾波,消除高頻噪聲
    blur(imageSobelOut, imageSobelOut, Size(3, 3));


    //6.二值化
    Mat imageSobleOutThreshold;
    threshold(imageSobelOut, imageSobleOutThreshold, 130, 255, CV_THRESH_BINARY);
    //Mat imageOutMat = imageSobleOutThreshold.clone();


    //7.閉運算,填充條形碼間隙
    Mat  element = getStructuringElement(0, Size(7, 7));
    morphologyEx(imageSobleOutThreshold, imageSobleOutThreshold, MORPH_CLOSE, element);


    //8. 腐蝕,去除孤立的點
    erode(imageSobleOutThreshold, imageSobleOutThreshold, element);


    //9. 膨脹,填充條形碼間空隙,根據核的大小,有可能需要2~3次膨脹操作
    dilate(imageSobleOutThreshold, imageSobleOutThreshold, element);
    dilate(imageSobleOutThreshold, imageSobleOutThreshold, element);
    dilate(imageSobleOutThreshold, imageSobleOutThreshold, element);

    vector<vector<Point>> contours;
    vector<Vec4i> hiera;

    //10.通過findContours找到條形碼區域的矩形邊界
    findContours(imageSobleOutThreshold, contours, hiera, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    Rect bigRect = Rect() ;
    bigRect.width=0;

    for (int i = 0; i<contours.size(); i++)
    {
        Rect rect = boundingRect((Mat)contours[i]);
        //rectangle(image, rect, Scalar(255), 2);

        if(rect.width>bigRect.width )
        {
            bigRect = rect ;

        }
        if(rect.width>100)
        {

            Rect rectScale = rect +  Point(-rect.width/8,  -rect.height/8) +
                             Size(rect.width/4, rect.height/4);  //move  //scale;
            Mat myoutMat   = image(rect);     //crop

            std::vector<int> compression_params;
            compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
            compression_params.push_back(0);    // 無壓縮png.
            compression_params.push_back(cv::IMWRITE_PNG_STRATEGY);
            compression_params.push_back(cv::IMWRITE_PNG_STRATEGY_DEFAULT);

            char tmp[128]={0};

            string ddstr = tmp;
            string filename = "/sdcard/small/"+ddstr +"_.png";
            // Mat dst;
            // resize(myoutMat, dst, Size(),1.5,1.5);//scale 1.5
            jobject sbitmap = createBitmap(env, myoutMat);
            mat2bmp(env, myoutMat, sbitmap, false);


            //imwrite(filename,myoutMat,compression_params);
            LOGE("============getRectSmallImage %s\n",filename.c_str()  );

            return sbitmap;
        }

    }

    jobject sbitmap = createBitmap(env, imageSobelOut);
    mat2bmp(env, imageSobelOut, sbitmap, false);

    return sbitmap;
}

這個主要是查找條形碼,並返回 條形碼的小區域圖片;

原圖:

裁後的圖片:

還是比較精確的;

注: 讀圖片記得請求權限;另外 sdk 版本需要都寫 23以上纔可以;

demo 下載

參考:

https://blog.csdn.net/hfut_why/article/details/84594168

https://blog.csdn.net/qq_15602525/article/details/78533517

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章