java如何实现基于opencv全景图合成实例代码

网友投稿 402 2023-01-27


java如何实现基于opencv全景图合成实例代码

全景图概述

每当一个平面图像映射到一个弯曲的表面就会发生图象投影,反之亦然,这中现象特别常见于全景摄影。例如地球的球面可以映射到一块平坦的纸张。由于在我们周围的整个视场的可以被认为是作为球体的表面(对于所有观测角度),我们需要一种能将球形投影到2-D平面以便照片打印的方法。

小的视角相对容易进行形变并投影到平坦的纸上。但是,当试图把一个球形图像映射到一个平面上,有些变形是不可避免的。因此,每一种类型的投影仅仅尝试避免一种类型的失真,这是以牺牲其他失真为代价的。随着视场角增大,观测弧(viewing arc)变得更弯曲,从而全景投影类型之间的差异变得更加显着。什么时候使用那一种投影,在很大程度上取决于每个投影应用。 在这里,我们集中介绍在几个最常用。

前言

因项目需要,自己做了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

com.suibian

opencv-300

3.3.0

好了,这样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

#include

#include

#include

#include

using namespace std;

using namespace cv;

bool try_use_gpu = false;

vector 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命令

生成对应com_lianxi_securitytest_opencv_OpenCVUtil.h文件

#include

/* 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_lianXunRwQRxi_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

#include

#include

#include

#include

#include

#include

using namespace std;

using namespace cv;

bool try_use_gpu = false;

vector 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(newstr.c_str()));

}

上面就是对应C++代码

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

运行java程序,结果如下

看一下合成的全景图吧

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:接口自动化测试找工作(自动化测试好找工作吗)
下一篇:共享文件系统怎么用(共享文件怎么使用)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~