全景图概述
每当一个平面图像映射到一个弯曲的表面就会发生图象投影,反之亦然,这中现象特别常见于全景摄影。例如地球的球面可以映射到一块平坦的纸张。由于在我们周围的整个视场的可以被认为是作为球体的表面(对于所有观测角度),我们需要一种能将球形投影到2-d平面以便照片打印的方法。
小的视角相对容易进行形变并投影到平坦的纸上。但是,当试图把一个球形图像映射到一个平面上,有些变形是不可避免的。因此,每一种类型的投影仅仅尝试避免一种类型的失真,这是以牺牲其他失真为代价的。随着视场角增大,观测弧(viewing arc)变得更弯曲,从而全景投影类型之间的差异变得更加显着。什么时候使用那一种投影,在很大程度上取决于每个投影应用。 在这里,我们集中介绍在几个最常用。
前言
因项目需要,自己做了demo,从中学习很多,所以分享出来,希望有这方面需求的少走一些弯路,opencv怎么安装网上教程多多,这里不加详细说明,我安装的opencv-3.3.0
如上图所示,找到相应的jar包,这里讲一下如何这个jar如何导入maven仓库
1
2
|
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
|
1
2
3
|
<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++代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#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的调用原理
脉络都理通了,那就开始吧
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#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项目所在的位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
#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程序,结果如下
看一下合成的全景图吧
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://www.cnblogs.com/developerxiaofeng/p/9242507.html