最近做图像的处理这块,但是大多数对图像的处理都是使用c++去做的,比如opencv就是用c/c++去做的。网上对用java去做图像的拼接的资料倒是不多,于是我写这篇文章给大家提供一个思路。软件vs2017及eclipse
首先新建一个Java项目
new一个类
在类里定义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文件
这是我的文件目录
接着就会在项目目录里生成下面这个文件,这个文件等会要拷进vs的项目里
接着用vs新建一个动态连接库的新项目
这里要改成64位的
接着要把opencv添加进来
这里配置参考https://blog.csdn.net/dango_miracle/article/details/78681131
随后把下图三个文件拷进来,其中jni.h和jni_mid.h都在java jdk 的include的文件里
拷进来之后添加到头文件里
把代码写进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
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
matcher.match(imageDesc1, imageDesc2, matchePoints, Mat());
sort(matchePoints.begin(), matchePoints.end()); //特征点排序
//获取排在前N个的最优匹配特征点
vector
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_
Mat adjustHomo = adjustMat * homo;
//获取最强配对点在原始图像和矩阵变换后图像上的对应位置,用于图像拼接点的定位
Point2f originalLinkPoint, targetLinkPoint, basedImagePoint;
originalLinkPoint = keyPoint1[matchePoints[0].queryIdx].pt;
Mat originelP, targetP;
originelP = (Mat_
targetP = adjustHomo * originelP;
float x = targetP.at
float y = targetP.at
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
最后点击生成
把上图红色路径添加进环境变量的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!");
}
}
把上面代码写进去
运行项目即可
测试图片
生成图片