java 實現基於opencv全景圖合成


因項目需要,自己做了demo,從中學習很多,所以分享出來,希望有這方面需求的少走一些彎路,opencv怎么安裝網上教程多多,這里不加詳細說明,我安裝的opencv-3.3.0

 

 如上圖所示,找到相應的jar包,這里講一下如何這個jar如何導入Maven倉庫

mvn install:install-file -Dfile=D:\opencv-3.0.0\opencv\build\java\opencv-300.jar 
-DgroupId=com.suibian -DartifactId=opencv-300 -Dversion=3.3.0 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true

 

<groupId>com.suibian</groupId>
  <artifactId>opencv-300</artifactId>
  <version>3.3.0</version>

 好了,這樣java可以通過這個jar操作opencv,那我們看一下,當然你能這樣想,說明你很單純,讓我們看一下opencv 中includ中的路徑和jar中包的對比

哈哈,全景圖的關鍵stitching並沒有,而且面向java的2015以后就一直沒有更新,如下圖所示一個全景圖(傻瓜)合成的關鍵類沒有,但是C++給我提供了

那怎么辦呢,如何用java調用C++的代碼,我們知道和操作系統打交道,C/C++無疑比Java更合適,opencv圖形處理的這方面的應用,大多數是C++開發比較多,java中的一個關鍵字native大家都不陌生吧,然而我們想點進去,想看看是怎么實現的,怎么也點不進去,因為他就不是java寫的,可能是C/C++,native對應都是java中jre下bin目錄的XXX.dll文件,所以把我們要使用的C++代碼打包成dll格式的文件放到bin目錄即可,當然這涉及到方法的參數和返回值,廢話不多說,安裝visual  studio  2017,安裝教程網上教程很多

點擊  文件-->新建--->項目--->windows桌面-->動態鏈接庫(Dll),這樣項目就新建成功,接下來上代碼

這是全景圖合成的C++代碼

#include "stdafx.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
bool try_use_gpu = false;
vector<Mat> imgs;
string result_name = "D:/result1.jpg";
int _tmain(int argc, char * argv[])
{
    Mat img1 = imread("D:/quanjingtu/hh/1.jpg");
    Mat img2 = imread("D:/quanjingtu/hh/2.jpg");
    Mat img3 = imread("D:/quanjingtu/hh/3.jpg");
    Mat img4 = imread("D:/quanjingtu/hh/4.jpg");
    Mat img5 = imread("D:/quanjingtu/hh/5.jpg");
    Mat img6 = imread("D:/quanjingtu/hh/6.jpg");
    Mat img7 = imread("D:/quanjingtu/hh/7.jpg");
    Mat img8 = imread("D:/quanjingtu/hh/8.jpg");
    Mat img9 = imread("D:/quanjingtu/hh/9.jpg");
    Mat img10 = imread("D:/quanjingtu/hh/10.jpg");
    
    //Mat img6 = imread("6.jpg");
    if (img1.empty() || img2.empty())
    {
        cout << "Can't read image" << endl;
        return -1;
    }
    imgs.push_back(img1);
    imgs.push_back(img2);
    imgs.push_back(img3);
    imgs.push_back(img4);
    imgs.push_back(img5);
    imgs.push_back(img6);
    imgs.push_back(img7);
    imgs.push_back(img8);
    imgs.push_back(img9);
    imgs.push_back(img10);
    

    
    //imgs.push_back(img6);
    Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
    // 使用stitch函數進行拼接
    Mat pano;
    Stitcher::Status status = stitcher.stitch(imgs, pano);
    imwrite(result_name, pano);
    Mat pano2 = pano.clone();
    // 顯示源圖像,和結果圖像
    //imshow("全景圖像", pano);
    if (waitKey() == 27)
        return 0;
    //imwrite(result_name, pano);
}

那么java如何和C++進行交互呢,通過java中jni技術

 讓我們了解一下java中JNI

  Java Native Interface(簡稱JNI),Java是跨平台語言,有時候需要調用本地代碼,Sun公司提供JNI接口,通過這個接口與操作系統本地代碼相互調用,如下圖所示是Java中native的調用原理

脈絡都理通了,那就開始吧

public class OpenCVUtil {
    static {
     //這里的system.load用來加載C++生成的動態鏈接庫,加載實際自己也可以決定不一定非的是靜態的。
        System.loadLibrary("OpenCVUtil");
    }

    public static native String changeArrValue(String str);
    public static void main(String[] args) throws UnsupportedEncodingException {
        String base="D:/quanjingtu/gg"+"/";
        int length=5;
        String url="";

        for (int i=1;i<=length;i++){
            if (i==1){
                url=url+base+i+".jpg";
            }else {
                url=url+","+base+i+".jpg";
            }

        }
        //System.out.println(url);
        String temp =new String(changeArrValue(url).getBytes(),"GBK");
        System.out.println(temp); ;

    }
}

定義native方法,將該java文件編譯成.class文件

進入cmd命令窗口,打開對應編譯好的class文件目錄執行javah命令

javah  -classpath <生成XX.h文件存放位置>  -jni <包路徑.類名>

 

 生成對應com_lianxi_securitytest_opencv_OpenCVUtil.h文件

#include <jni.h>
/* Header for class com_lianxi_securitytest_opencv_OpenCVUtil */

#ifndef _Included_com_lianxi_securitytest_opencv_OpenCVUtil
#define _Included_com_lianxi_securitytest_opencv_OpenCVUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_lianxi_securitytest_opencv_OpenCVUtil
 * Method:    changeArrValue
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_lianxi_securitytest_opencv_OpenCVUtil_changeArrValue
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

只把native方法處理了,復制該文件,到vs 2017項目所在的位置

  

#include "stdafx.h"
#include "com_lianxi_securitytest_opencv_OpenCVUtil.h"
#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <string>
using namespace std;
using namespace cv;
bool try_use_gpu = false;
vector<Mat> imgs;
string result_name = "D:/result.jpg";

JNIEXPORT jstring JNICALL Java_com_lianxi_securitytest_opencv_OpenCVUtil_changeArrValue
(JNIEnv *env, jclass obj, jstring prompt) {
    //這是接收過來的字符串,多個路徑
    const char* str;
//....................................................................

//...........................


    //imgs.push_back(img6);
    Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
    // 使用stitch函數進行拼接
    Mat pano;
    Stitcher::Status status = stitcher.stitch(imgs, pano);
    imwrite(result_name, pano);
    Mat pano2 = pano.clone();
    // 顯示源圖像,和結果圖像
    //imshow("全景圖像", pano);
    if (waitKey() == 27)


        if (status != Stitcher::OK) {
            return env->NewStringUTF("picture failure!!!");
            
        }

    //return env->NewStringUTF(result_name.c_str);
    string newstr = "picture success!!!URL=" + result_name;
    return env->NewStringUTF(const_cast<char*>(newstr.c_str()));
    
}

上面就是對應C++代碼

點擊生成--->重新生成解決方案    生成對應的dll文件,然后放到JDK的jre/bin目錄里

 運行java程序,結果如下

 

 看一下合成的全景圖吧

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM