java 实现基于opencv全景图合成

摘要:
由于项目的需要,我做了一个演示,从中学到了很多东西,所以我分享了它。我希望在这方面少走弯路。有很多关于如何安装opencv的在线教程。我不会在这里详细解释它们。我安装的opencv-3.3.0如上图所示。我找到了相应的jar包。在这里,我将告诉您如何将这个jar导入Maven仓库mvninstall:installfile Dfile=D:opencv-3.0.0 opencvuildjava opencv-300.jar-D

因项目需要,自己做了demo,从中学习很多,所以分享出来,希望有这方面需求的少走一些弯路,opencv怎么安装网上教程多多,这里不加详细说明,我安装的opencv-3.3.0

java 实现基于opencv全景图合成第1张

 如上图所示,找到相应的jar包,这里讲一下如何这个jar如何导入Maven仓库

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

java 实现基于opencv全景图合成第2张

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

 好了,这样java可以通过这个jar操作opencv,那我们看一下,当然你能这样想,说明你很单纯,让我们看一下opencv 中includ中的路径和jar中包的对比

java 实现基于opencv全景图合成第3张

哈哈,全景图的关键stitching并没有,而且面向java的2015以后就一直没有更新,如下图所示一个全景图(傻瓜)合成的关键类没有,但是C++给我提供了

java 实现基于opencv全景图合成第4张

那怎么办呢,如何用java调用C++的代码,我们知道和操作系统打交道,C/C++无疑比Java更合适,opencv图形处理的这方面的应用,大多数是C++开发比较多,java中的一个关键字native大家都不陌生吧,然而我们想点进去,想看看是怎么实现的,怎么也点不进去,因为他就不是java写的,可能是C/C++,native对应都是java中jre下bin目录的XXX.dll文件,所以把我们要使用的C++代码打包成dll格式的文件放到bin目录即可,当然这涉及到方法的参数和返回值,废话不多说,安装visual  studio  2017,安装教程网上教程很多

java 实现基于opencv全景图合成第5张

点击  文件-->新建--->项目--->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的调用原理

java 实现基于opencv全景图合成第6张

脉络都理通了,那就开始吧

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 <包路径.类名>

 java 实现基于opencv全景图合成第7张

java 实现基于opencv全景图合成第8张

 生成对应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项目所在的位置

  java 实现基于opencv全景图合成第9张

#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++代码

java 实现基于opencv全景图合成第10张

点击生成--->重新生成解决方案    生成对应的dll文件,然后放到JDK的jre/bin目录里

 运行java程序,结果如下

java 实现基于opencv全景图合成第11张

 看一下合成的全景图吧

 java 实现基于opencv全景图合成第12张

免责声明:文章转载自《java 实现基于opencv全景图合成》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ESXILinux 下 FreeSWITCH 远程连接使用 MySQL 替代 SQLite下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

C#-微信公众平台接口-上传临时素材

最烦做微信公众平台的东西。。文档说得不清不楚,又没示例代码,只能自己 慢慢搜索,弄了一晚上,基本弄出来了,把本地的图片上传到微信的临时素材那里,返回媒体ID,用于其他操作,代码如下 :(自己导入相应的类System.Net.Http,JSON解析用的LitJson)         /// <summary>        /// 上传临时素材...

asp.net关键字模糊查询(类似于各大网站搜索功能)

  今天与大家分享一个小算法,我是用C#写的,其他语言也一样换下语法就行了。以空格断开关键字模糊查询,类似于各大网站的搜索功能。我想的就是一个拼接sql语句的过程。都是以空格断开关键字,分两种情况,一种是以空格断开是”且”的关系,另一种是以空格断开是”或”的关系。其实也很简单,直接上代码吧。   关键字"或"的关系代码: /// <summary&g...

assert()函数用法总结

assert()函数用法总结assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include <assert.h>void assert( int expression );   assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向s...

java int与integer的区别

java int与integer的区别 int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象 1.Java 中的数据类型分为基本数据类型和复杂数据类型 int 是前者而integer 是后者(也就是一个类);因此在类进行初始化时int类的变量初始为0...

libuv::进程

对于基于事件(event-based)的程序来说, 有个限制,没办法很好地利用多核,提高CPU使用率. 即使能够使用多线程编程来分发 handle, 但是每个 loop 还是只有一个线程. 这时候, 使用多进程就能够分担 loop 的压力,并且通过多进程 + 通信的方法, 会比 多线程 + 共享内存的方法更加安全, 易于开发. #include <c...

交易所如何对接狗狗币(DOGE)钱包?这点不可忽视

一个大家非常熟悉的 meme 头像 doge 在一夜之间成为了全球热搜。在国内,「狗狗币一天暴涨逾 250%」登上了微博热搜第七位,在国外,「DOGE」或者「DOGECOIN」站上了多个地区的「推特趋势榜」。比特币似乎都没有如此高规格的待遇。   对于新入币圈的朋友们可能对狗狗币还不太熟悉。这个币是个很早期的山寨币,它基本上是比特币的翻版,但是在比特币的基...