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

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

生成对应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程序,结果如下

看一下合成的全景图吧

总结

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

(0)

相关推荐

  • 详解OpenCV For Java环境搭建与功能演示

    OpenCV概述 OpenCV做为功能强大的计算机视觉开源框架,包含了500多个算法实现,而且还在不断增加,其最新版本已经更新到3.2.其SDK支持Android与Java平台开发,对于常见的图像处理需求几乎都可以满足,理应成为广大Java与Android程序员的首先的图像处理框架.Java中使用OpenCV的配置及其简单,可以毫不客气的说几乎是零配置都可以. 一:配置 配置引入OpenCV相关jar包,首先要下载OpenCV的自解压版本,下载地址: http://opencv.org/open

  • Java+opencv3.2.0实现重映射

    通过重映射来表达每个像素的位置(x,y) :g(x,y)=f(h(x,y)),h(x,y)是映射方法函数.当h(x,y) = (I.cols()-x,y),表示按照x轴方向发生偏转. 函数:Imgproc.remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, int borderMode, Scalar borderValue) 参数说明: src:源图像 dst:目标图像 map1:它有两种可能表示的对象,一种是表示点(x

  • Java+opencv3.2.0实现人脸检测功能

    说到人脸检测,首先要了解Haar特征分类器.Haar特征分类器说白了就是一个个的xml文件,不同的xml里面描述人体各个部位的特征值,比如人脸.眼睛等等.OpenCV3.2.0中提供了如下特征文件: haarcascade_eye.xml haarcascade_eye_tree_eyeglasses.xml haarcascade_frontalcatface.xml haarcascade_frontalcatface_extended.xml haarcascade_frontalface

  • Java+opencv3.2.0实现模板匹配

    模板匹配是一项在一幅图像中寻找与另一幅模板图像最匹配(相似)部分的技术. 函数:Imgproc.matchTemplate(Mat image, Mat templ, Mat result, int method) 参数说明: image:源图像 templ:模板图像 result:比较结果 method:匹配算法 匹配算法: TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配:最好的匹配值为0:匹配越差,匹配值越大. TM_CCORR 相关匹配法:该方法采用乘法操作:数值越大表明匹配

  • OPENCV+JAVA实现人脸识别

    本文实例为大家分享了JAVA实现人脸识别的具体代码,供大家参考,具体内容如下 官方下载 安装文件 ,以win7为例,下载opencv-2.4.13.3-vc14.exe 安装后,在build目录下 D:\opencv\build\java,获取opencv-2413.jar,copy至项目目录 同时需要dll文件 与 各 识别xml文件,进行不同特征的识别(人脸,侧脸,眼睛等) dll目录:D:\opencv\build\java\x64\opencv_java2413.dll xml目录:D:

  • Java+opencv3.2.0实现hough圆检测功能

    hough圆检测和hough线检测的原理近似,对于圆来说,在参数坐标系中表示为C:(x,y,r). 函数: Imgproc.HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius) 参数说明: image:源图像 circles:检测到的圆的输出矢量(x,y,r) method:使用的

  • Java+opencv3.2.0实现hough直线检测

    hough变换是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合特定形状的集合作为hough变换结果. 发展史: 1962年由PaulHough首次提出,用来检测直线和曲线. 1972年由Richard Duda & Peter Hart推广使用,扩展到任意形状物体的识别. 原理: 一条直线在直角坐标系下的表示形式为y=k*x+b,而在极坐标系下表示为r=x*cos(theta)+y*sin(theta).hough变换的思想为在直角坐标系下的一个点对

  • Java+opencv3.2.0之直方图均衡详解

    直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法. 直方图均衡化的步骤: 1.计算输入图像的直方图H 2.进行直方图归一化,使直方图组距的和为255 3.计算直方图积分 4.采用H'作为查询表:dst(x,y)=H'(src(x,y))进行图像变换 函数:Imgproc.equalizeHist(Mat src, Mat dst) 参数说明: src:源图像 dst:运算结果图像 示例代码: public static void main(String[] args) { Sys

  • 详解使用JavaCV/OpenCV抓取并存储摄像头图像

    本程序通过JFrame实时显示本机摄像头图像,并将图像存储到一个缓冲区,当用户用鼠标点击JFrame中任何区域时,显示抓取图像的简单动画,同时保存缓冲区的图像到磁盘文件中.点击JFrame关闭按钮可以退出程序. 实现: import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; imp

  • Java+opencv3.2.0之scharr滤波器

    在opencv中scharr滤波器是配合sobel算子的运算而存在的.当sobel内核为3时,结果可能会产生比较明显的误差,针对这一问题,Opencv提供了scharr函数.该函数只针对大小为3的核,并且运算速率和sobel函数一样快,结果更加精确,但抗噪性不如sobel函数. 使用scharr滤波器计算x或y方向的图像差分,它的参数变量和sobel一样. 函数:Imgproc.Scharr(Mat src, Mat dst, int ddepth, int dx, int dy, double

随机推荐