Android JUnit test with OpenCV

This article shows how to do image matching in android JUnit test.

The following shows the method to search for a second image in a first image and return a simularity percentage.
  1. Import OpenCV to android
  2. Code to do the comparing
  3. Improve code
    Thanks to all of them, saved my time.

1.1 Download the latest OpenCV sdk from OpenCV.org, choose "Android pack", decompress the zip file to local.
1.2 Import the OpenCV to Android Studio, in the project, from "File -> New -> Import Module", choose "sdk/java" folder in OpenCV android sdk folder.
1.3 Update "build.gradle" under the "imported module" to update the 4 fields to match the "app/build.gradle"
a. compileSdkVersion
b. buildToolsVersion
c. minSdkVersion
d. targetSdkVersion
1.4 Add module dependency by "File -> Project Structure", and in "app" select the "Dependencies", click "+" on the top right corner, choose "Module Dependency" and select the imported OpenCV module.
1.5 Copy libs folder under "sdk/native" to android studio under "app/src/main".
1.6 Under "app/src/main/libs", remove the unnecessary folders according to your platform. In this case, I removed all folders except for "armeabi" and "armeabi-v7a".
Then remove the unnecessary files from the remaining folders under "app/src/main/libs/", in my case, I removed all files except for the one "libopencv_java3.so" in the two remaining folders.
1.7 In android studio, rename the copied libs directory to 'jniLibs'.
This step is very important, since Android Studio expects native libs in app/src/main/jniLibs instead of libs folder. And the new folder name MUST exactly be jniLibs.
(OR create a jni folder in the first place:

  • Locate Project
  • Locate app
  • Right click - New - Folder - JNI Folder)
    1.8 In the test class, add the following code, and we can get the result from the log:
    private static String TAG = "Test";

    static {
        System.loadLibrary("opencv_java3");
    }

    static {
        if (!OpenCVLoader.initDebug()){
            Log.w(TAG, "static initializer: Fail to load opencv libs !");
            Log.w(TAG, "static initializer: Thus fail the case.");
            fail();
        } else {
            Log.i(TAG, "static initializer: Succeed to load opencv libs !");
        }
    }

If we get the log "static initializer: Succeed to load opencv libs !", then the whole importing thing is done!

-----------------------------------------------------------------------------------------

The first stage is done.

The second and the third stages are shown below :
private static final double THRESHOLD = 0.95;
private static String TAG = "Test";

Boolean matchImages(Mat img, Mat template, String outFile, String suffix) throws IOException {
        Log.i(TAG, "matchImages: Run image match method complex version.");
        outFile += suffix;
        if (new File(outFile).exists()){
            Boolean flag = new File(outFile).delete();
            Log.i(TAG, "matchImages: The result file already exists , delete it now : " + flag);
        }

        //Mat img = Utils.loadResource(mContext, inFileID, Imgcodecs.CV_LOAD_IMAGE_COLOR);
        if (!img.empty()){
            Log.i(TAG, "matchImages: Load source image succeed !");
        } else {
            Log.w(TAG, "matchImages: Fail to load source image !!!");
        }

        //Mat template = Utils.loadResource(mContext, templateFileID, Imgcodecs.CV_LOAD_IMAGE_COLOR);

        if (!template.empty()) {
            Log.i(TAG, "matchImages: Load template image succeed !");
        } else {
            Log.w(TAG, "matchImages: Fail to load template image !!!");
        }

        int result_cols = img.cols() - template.cols() + 1;
        int result_rows = img.rows() - template.rows() + 1;
        Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

        //NEVER do the matching and NOT normalize
        Imgproc.matchTemplate(img, template, result, Imgproc.TM_CCOEFF_NORMED);

        //Localize the best match with minMaxLoc
        Core.MinMaxLocResult mmr = Core.minMaxLoc(result);

        Point matchLoc;

        matchLoc = mmr.maxLoc;

        Log.i(TAG, "Match percentage : " + mmr.maxVal);

        //Draw the rectangle.
        Imgproc.rectangle(img, matchLoc, new Point(matchLoc.x + template.cols(), matchLoc.y + template.rows()),
                new Scalar(0, 255, 0), 8);

        //Save the visualized detection
        Log.i(TAG, "matchImages: Write to " + outFile);
        Imgcodecs.imwrite(outFile, img);
        if (mmr.maxVal >= THRESHOLD) {
            Log.i(TAG, "matchImages: Match percentage is above the THRESHOLD.");
            Log.i(TAG, "matchImages: ###### Found match . ######");
            return true;
        } else {
            Log.w(TAG, "matchImages: Match percentage is below the THRESHOLD!!!");
            Log.w(TAG, "matchImages: ****** None match . ******");
            return false;
        }
    }

As suggested, certain points MUST be noticed:

a. The matching method should better be "Imgproc.TM_CCOEFF_NORMED".
b. With this matching method, "mmr.maxVal" returns the highest simularity percentage of the images.
c. The following code should NOT be applied if we'd like to get a proper percentage:

Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

d. The format of the two Mat images MUST be exactly the same. That is :

Mat.channels()
Mat.type()

If not, android studio is likely to throw an error.
Transfer one to match the other before do image matching.
Refer to:

And that's all.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末孤钦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子楣铁,更是在濱河造成了極大的恐慌养篓,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異设哗,居然都是意外死亡唱捣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門网梢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來震缭,“玉大人,你說我怎么就攤上這事战虏〖鹪祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵烦感,是天一觀的道長巡社。 經(jīng)常有香客問我,道長手趣,這世上最難降的妖魔是什么晌该? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮绿渣,結(jié)果婚禮上朝群,老公的妹妹穿的比我還像新娘。我一直安慰自己中符,他們只是感情好姜胖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淀散,像睡著了一般右莱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上档插,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天慢蜓,我揣著相機(jī)與錄音,去河邊找鬼阀捅。 笑死胀瞪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饲鄙。 我是一名探鬼主播凄诞,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忍级!你這毒婦竟也來了帆谍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤轴咱,失蹤者是張志新(化名)和其女友劉穎汛蝙,沒想到半個(gè)月后烈涮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窖剑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年坚洽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片西土。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡讶舰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出需了,到底是詐尸還是另有隱情跳昼,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布肋乍,位于F島的核電站鹅颊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏墓造。R本人自食惡果不足惜堪伍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滔岳。 院中可真熱鬧杠娱,春花似錦挽牢、人聲如沸谱煤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刘离。三九已至,卻和暖如春睹栖,著一層夾襖步出監(jiān)牢的瞬間硫惕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國打工野来, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恼除,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓曼氛,卻偏偏與公主長得像豁辉,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舀患,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Correctness AdapterViewChildren Summary: AdapterViews can...
    MarcusMa閱讀 8,863評(píng)論 0 6
  • afinalAfinal是一個(gè)android的ioc徽级,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評(píng)論 2 45
  • 若是想著遙遠(yuǎn)的遠(yuǎn)方 就會(huì)有遍地的荒涼 還有那光腳的悲傷 所以我們抓住了太陽 雙腳滾燙 遺忘了遠(yuǎn)方的荒涼 遠(yuǎn)方那個(gè)地...
    _三公子_閱讀 206評(píng)論 0 0
  • 湘西的年是最有味道的,濃濃的年味從冬月就開始了:打粑粑聊浅,推豆腐餐抢,過趕年现使,洗年腳,當(dāng)然還有百獅會(huì)旷痕,調(diào)年盤歌……熱熱鬧...
    財(cái)神出位閱讀 671評(píng)論 1 4
  • 相信所有的經(jīng)歷都是渡緣的船 相信有愛的心會(huì)遇見美好 相信偌大的地球空間里 沒有早一步亦沒有晚一步的遇見 讓過去過去...
    舍得_之間閱讀 248評(píng)論 7 5