基于JAVA JNI的opencv全景图的拼接

最近做图像的处理这块,但是大多数对图像的处理都是使用c++去做的,比如opencv就是用c/c++去做的。网上对用java去做图像的拼接的资料倒是不多,于是我写这篇文章给大家提供一个思路。软件vs2017及eclipse

首先新建一个Java项目

基于JAVA JNI的opencv全景图的拼接

 new一个类

基于JAVA JNI的opencv全景图的拼接

 在类里定义native方法

package com.ws.study;


public class JavaPanorama {

    public native void SurfPanorama(); 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
}

}

接着用cmd把.class文件编译成.h文件

这是我的文件目录

基于JAVA JNI的opencv全景图的拼接

基于JAVA JNI的opencv全景图的拼接

接着就会在项目目录里生成下面这个文件,这个文件等会要拷进vs的项目里

基于JAVA JNI的opencv全景图的拼接

接着用vs新建一个动态连接库的新项目

基于JAVA JNI的opencv全景图的拼接

这里要改成64位的

基于JAVA JNI的opencv全景图的拼接

基于JAVA JNI的opencv全景图的拼接

接着要把opencv添加进来 

基于JAVA JNI的opencv全景图的拼接

这里配置参考https://blog.csdn.net/dango_miracle/article/details/78681131

随后把下图三个文件拷进来,其中jni.h和jni_mid.h都在java jdk 的include的文件里

基于JAVA JNI的opencv全景图的拼接

基于JAVA JNI的opencv全景图的拼接

 拷进来之后添加到头文件里

基于JAVA JNI的opencv全景图的拼接

把代码写进JavaPanorama.cpp里

// JavaPanorama.cpp: 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "com_ws_study_JavaPanorama.h"
#include "highgui/highgui.hpp"  
#include "opencv2/nonfree/nonfree.hpp"  
#include "opencv2/legacy/legacy.hpp" 

using namespace cv;
JNIEXPORT void JNICALL Java_com_ws_study_JavaPanorama_SurfPanorama
(JNIEnv *evn, jobject obj) {

    Mat image01 = imread("e:/img/1.png");
    Mat image02 = imread("e:/img/2.png");
    //imshow("拼接图像1", image01);
    //imshow("拼接图像2", image02);

    //灰度图转换
    Mat image1, image2;
    cvtColor(image01, image1, CV_RGB2GRAY);
    cvtColor(image02, image2, CV_RGB2GRAY);

    //提取特征点  
    SiftFeatureDetector siftDetector(800);  // 海塞矩阵阈值
    vector<KeyPoint> keyPoint1, keyPoint2;
    siftDetector.detect(image1, keyPoint1);
    siftDetector.detect(image2, keyPoint2);

    //特征点描述,为下边的特征点匹配做准备  
    SiftDescriptorExtractor siftDescriptor;
    Mat imageDesc1, imageDesc2;
    siftDescriptor.compute(image1, keyPoint1, imageDesc1);
    siftDescriptor.compute(image2, keyPoint2, imageDesc2);

    //获得匹配特征点,并提取最优配对      
    FlannBasedMatcher matcher;
    vector<DMatch> matchePoints;
    matcher.match(imageDesc1, imageDesc2, matchePoints, Mat());
    sort(matchePoints.begin(), matchePoints.end()); //特征点排序    
                                                    //获取排在前N个的最优匹配特征点
    vector<Point2f> imagePoints1, imagePoints2;
    for (int i = 0; i<10; i++)
    {
        imagePoints1.push_back(keyPoint1[matchePoints[i].queryIdx].pt);
        imagePoints2.push_back(keyPoint2[matchePoints[i].trainIdx].pt);
    }

    //获取图像1到图像2的投影映射矩阵,尺寸为3*3
    Mat homo = findHomography(imagePoints1, imagePoints2, CV_RANSAC);
    Mat adjustMat = (Mat_<double>(3, 3) << 1.0, 0, image01.cols, 0, 1.0, 0, 0, 0, 1.0);
    Mat adjustHomo = adjustMat * homo;

    //获取最强配对点在原始图像和矩阵变换后图像上的对应位置,用于图像拼接点的定位
    Point2f originalLinkPoint, targetLinkPoint, basedImagePoint;
    originalLinkPoint = keyPoint1[matchePoints[0].queryIdx].pt;

    Mat originelP, targetP;
    originelP = (Mat_<double>(3, 1) << originalLinkPoint.x, originalLinkPoint.y, 1.0);
    targetP = adjustHomo * originelP;
    float x = targetP.at<double>(0, 0) / targetP.at<double>(2, 0);
    float y = targetP.at<double>(1, 0) / targetP.at<double>(2, 0);

    targetLinkPoint = Point2f(x, y);
    basedImagePoint = keyPoint2[matchePoints[0].trainIdx].pt;

    //图像配准
    Mat imageTransform1;
    warpPerspective(image01, imageTransform1, adjustMat*homo, Size(image02.cols + image01.cols + 10, image02.rows));

    //在最强匹配点的位置处衔接,最强匹配点左侧是图1,右侧是图2,这样直接替换图像衔接不好,光线有突变
    Mat ROIMat = image02(Rect(Point(basedImagePoint.x, 0), Point(image02.cols, image02.rows)));
    ROIMat.copyTo(Mat(imageTransform1, Rect(targetLinkPoint.x, 0, image02.cols - basedImagePoint.x + 1, image02.rows)));

    imwrite("e:/img/3.png", imageTransform1);
    waitKey();

}

 

此代码参考https://blog.csdn.net/dcrmg/article/details/52629856

 

最后点击生成

基于JAVA JNI的opencv全景图的拼接

基于JAVA JNI的opencv全景图的拼接

把上图红色路径添加进环境变量的Path里 只到debug文件夹

C:\Users\Administrator\source\repos\JavaPanorama\x64\Debug

接着回到eclipse里

package com.ws.study;


public class JavaPanorama {

    public native void SurfPanorama(); 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.loadLibrary("JavaPanorama");
        JavaPanorama jPanorama=new JavaPanorama();
        jPanorama.SurfPanorama();
        System.out.println("ok!");

}

}
把上面代码写进去

运行项目即可

基于JAVA JNI的opencv全景图的拼接

测试图片 

 基于JAVA JNI的opencv全景图的拼接

 基于JAVA JNI的opencv全景图的拼接

生成图片

 基于JAVA JNI的opencv全景图的拼接