找出了每张图片的清晰点
选择本地图片代码:
void MainWindow::on_BtnPicture_clicked()
{
QString fullname = QFileDialog::getOpenFileName();
leftimg = imread(fullname.toStdString());
QImage qImage(leftimg.data, leftimg.cols,
leftimg.rows, leftimg.step, QImage::Format_RGB888);
qImage = qImage.rgbSwapped();
qImage = qImage.scaled(ui->labPicture->size(),Qt::KeepAspectRatio);
ui->labPicture->setPixmap(QPixmap::fromImage(qImage));
ui->labPicture->setScaledContents(true);
// QImage leftimg("D:\\test\\depthfusion\\88.jpg");
// leftimg = leftimg.scaled(ui->labPicture->size(),Qt::KeepAspectRatio);
// ui->labPicture->setPixmap(QPixmap::fromImage(leftimg));
// ui->labPicture->setScaledContents(true);
// QPixmap leftpix;
// leftpix.load("D:\\test\\depthfusion\\88.jpg");
// ui->labPicture->clear();
// ui->labPicture->setPixmap(leftpix);
// ui->labPicture->show();
}
void MainWindow::on_BtnPicture_2_clicked()
{
QString fullname = QFileDialog::getOpenFileName();
rightimg = imread(fullname.toStdString());
QImage qImage(rightimg.data, rightimg.cols,
rightimg.rows, rightimg.step, QImage::Format_RGB888);
qImage = qImage.rgbSwapped();
qImage = qImage.scaled(ui->labPicture_2->size(),Qt::KeepAspectRatio);
ui->labPicture_2->setPixmap(QPixmap::fromImage(qImage));
ui->labPicture_2->setScaledContents(true);
// QImage rightimg("D:\\test\\depthfusion\\89.jpg");
// rightimg = rightimg.scaled(ui->labPicture_2->size(),Qt::KeepAspectRatio);
// ui->labPicture_2->setPixmap(QPixmap::fromImage(rightimg));
// ui->labPicture_2->setScaledContents(true);
}
实现效果:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include "opencv2/opencv.hpp"
//#include"opencv2/features2d/features2d.hpp"
#include
using namespace cv;
using namespace std;
#include
#include
#include
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_BtnPicture_clicked();
void on_BtnPicture_2_clicked();
void on_BtnClose_clicked();
void on_BtnFusion_clicked();
private:
Ui::MainWindow *ui;
cv::Mat rightimg;
cv::Mat leftimg;
};
class LaplacianBlending {
private:
Mat_ left;
Mat_ right;
Mat_ blendMask;
vector > leftLapPyr, rightLapPyr, resultLapPyr;//Laplacian Pyramids
Mat leftHighestLevel, rightHighestLevel, resultHighestLevel;
vector > maskGaussianPyramid; //masks are 3-channels for easier multiplication with RGB
int levels;
void buildPyramids() {
buildLaplacianPyramid(left, leftLapPyr, leftHighestLevel);
buildLaplacianPyramid(right, rightLapPyr, rightHighestLevel);
buildGaussianPyramid();
}
void buildGaussianPyramid() {//金字塔内容为每一层的掩模
assert(leftLapPyr.size() > 0);
maskGaussianPyramid.clear();
Mat currentImg;
cvtColor(blendMask, currentImg, COLOR_GRAY2BGR);//store color img of blend mask into maskGaussianPyramid
maskGaussianPyramid.push_back(currentImg); //0-level
currentImg = blendMask;
for (int l = 1; l < levels + 1; l++) {
Mat _down;
if (leftLapPyr.size() > l)
pyrDown(currentImg, _down, leftLapPyr[l].size());
else
pyrDown(currentImg, _down, leftHighestLevel.size()); //lowest level
Mat down;
cvtColor(_down, down, COLOR_GRAY2BGR);
maskGaussianPyramid.push_back(down);//add color blend mask into mask Pyramid
currentImg = _down;
}
}
void buildLaplacianPyramid(const Mat& img, vector >& lapPyr, Mat& HighestLevel) {
lapPyr.clear();
Mat currentImg = img;
for (int l = 0; l < levels; l++) {
Mat down, up;
pyrDown(currentImg, down);
pyrUp(down, up, currentImg.size());
Mat lap = currentImg - up;
lapPyr.push_back(lap);
currentImg = down;
}
currentImg.copyTo(HighestLevel);
}
Mat_ reconstructImgFromLapPyramid() {
//将左右laplacian图像拼成的resultLapPyr金字塔中每一层
//从上到下插值放大并相加,即得blend图像结果
Mat currentImg = resultHighestLevel;
for (int l = levels - 1; l >= 0; l--) {
Mat up;
pyrUp(currentImg, up, resultLapPyr[l].size());
currentImg = up + resultLapPyr[l];
}
return currentImg;
}
void blendLapPyrs() {
//获得每层金字塔中直接用左右两图Laplacian变换拼成的图像resultLapPyr
resultHighestLevel = leftHighestLevel.mul(maskGaussianPyramid.back()) +
rightHighestLevel.mul(Scalar(1.0, 1.0, 1.0) - maskGaussianPyramid.back());
for (int l = 0; l < levels; l++) {
Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
Mat antiMask = Scalar(1.0, 1.0, 1.0) - maskGaussianPyramid[l];
Mat B = rightLapPyr[l].mul(antiMask);
Mat_ blendedLevel = A + B;
resultLapPyr.push_back(blendedLevel);
}
}
public:
LaplacianBlending(const Mat_& _left, const Mat_& _right, const Mat_& _blendMask, int _levels) ://construct function, used in LaplacianBlending lb(l,r,m,4);
left(_left), right(_right), blendMask(_blendMask), levels(_levels)
{
assert(_left.size() == _right.size());
assert(_left.size() == _blendMask.size());
buildPyramids(); //construct Laplacian Pyramid and Gaussian Pyramid
blendLapPyrs(); //blend left & right Pyramids into one Pyramid
};
Mat_ blend() {
return reconstructImgFromLapPyramid();//reconstruct Image from Laplacian Pyramid
}
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"QDebug"
//#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_BtnPicture_clicked()
{
QString fullname = QFileDialog::getOpenFileName();
leftimg = imread(fullname.toStdString());
QImage qImage(leftimg.data, leftimg.cols,
leftimg.rows, leftimg.step, QImage::Format_RGB888);
qImage = qImage.rgbSwapped();
qImage = qImage.scaled(ui->labPicture->size(),Qt::KeepAspectRatio);
ui->labPicture->setPixmap(QPixmap::fromImage(qImage));
ui->labPicture->setScaledContents(true);
}
void MainWindow::on_BtnPicture_2_clicked()
{
QString fullname = QFileDialog::getOpenFileName();
rightimg = imread(fullname.toStdString());
QImage qImage(rightimg.data, rightimg.cols,
rightimg.rows, rightimg.step, QImage::Format_RGB888);
qImage = qImage.rgbSwapped();
qImage = qImage.scaled(ui->labPicture_2->size(),Qt::KeepAspectRatio);
ui->labPicture_2->setPixmap(QPixmap::fromImage(qImage));
ui->labPicture_2->setScaledContents(true);
}
void MainWindow::on_BtnClose_clicked()
{
this->close();
}
Mat_ LaplacianBlend(const Mat_& l, const Mat_& r, const Mat_& m) {
LaplacianBlending lb(l, r, m, 4);
return lb.blend();
}
void MainWindow::on_BtnFusion_clicked()
{
vector images;
images.push_back(leftimg);
images.push_back(rightimg);
int hight = leftimg.rows;
int width = leftimg.cols;
Mat leftImg32f, rightImg32f;
leftimg.convertTo(leftImg32f, CV_32F);
rightimg.convertTo(rightImg32f, CV_32F);
//创建用于混合的掩膜,这里在中间进行混合
Mat mask = Mat::zeros(hight, width, CV_32FC1);
mask(Range::all(), Range(0, mask.cols * 0.5)) = 1.0;
Mat blendImg = LaplacianBlend(leftImg32f, rightImg32f, mask);
blendImg.convertTo(blendImg, CV_8UC3);
//对齐图片
Ptr alignMTB = createAlignMTB();
alignMTB->process(images, images);
//曝光合成(Mertens是该论文的作者)被OpenCV集成为函数了
Mat Fusion;
Ptr mergeMertens = createMergeMertens();
mergeMertens->process(images,Fusion);
// imshow("fusion", Fusion);
Fusion = Fusion * 255;
imwrite("test.png",Fusion);
cv::Mat dst = imread("test.png");
// 创建 ORB 特征检测器
cv::Ptr orb = cv::ORB::create();
// 在两张图像上分别检测特征点和计算描述子
std::vector keypoints1, keypoints2;
cv::Mat descriptors1, descriptors2;
orb->detectAndCompute(leftimg, cv::noArray(), keypoints1, descriptors1);
orb->detectAndCompute(rightimg, cv::noArray(), keypoints2, descriptors2);
// 使用基于距离的匹配算法进行特征匹配
cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector matches;
matcher.match(descriptors1, descriptors2, matches);
// 根据匹配结果筛选出较好的匹配点
double min_dist = std::min_element(matches.begin(), matches.end(), [](const cv::DMatch& m1, const cv::DMatch& m2) {
return m1.distance < m2.distance;
})->distance;
std::vector good_matches;
for (const cv::DMatch& match : matches) {
if (match.distance <= 3 * min_dist) {
good_matches.push_back(match);
}
}
// 绘制匹配结果
cv::Mat image_matches;
cv::drawMatches(leftimg, keypoints1, rightimg, keypoints2, good_matches, image_matches);
// 显示融合后的图片
cv::imshow("Merged Image1208", image_matches);
QImage mImage(dst.data, dst.cols,
dst.rows, dst.step, QImage::Format_RGB888);
mImage = mImage.rgbSwapped();
mImage = mImage.scaled(ui->labPicfusion->size(),Qt::KeepAspectRatio);
ui->labPicfusion->setPixmap(QPixmap::fromImage(mImage));
ui->labPicfusion->setScaledContents(true);
}
mainwindow.ui: