初学demo 在本地选择单张图片进行图像融合

2023-12-14 06:00:19

?找出了每张图片的清晰点

选择本地图片代码:

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 <QMainWindow>

#include "opencv2/opencv.hpp"
//#include"opencv2/features2d/features2d.hpp"
#include <vector>
using namespace cv;
using namespace std;

#include <QFileDialog>
#include <QDir>
#include <QTextCodec>

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_<Vec3f> left;
    Mat_<Vec3f> right;
    Mat_<float> blendMask;

    vector<Mat_<Vec3f> > leftLapPyr, rightLapPyr, resultLapPyr;//Laplacian Pyramids
    Mat leftHighestLevel, rightHighestLevel, resultHighestLevel;
    vector<Mat_<Vec3f> > 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<Mat_<Vec3f> >& 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_<Vec3f> 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_<Vec3f> blendedLevel = A + B;

            resultLapPyr.push_back(blendedLevel);
        }
    }

public:
    LaplacianBlending(const Mat_<Vec3f>& _left, const Mat_<Vec3f>& _right, const Mat_<float>& _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_<Vec3f> blend() {
        return reconstructImgFromLapPyramid();//reconstruct Image from Laplacian Pyramid
    }
};
#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"QDebug"
//#include <opencv2/xfeatures2d.hpp>
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_<Vec3f> LaplacianBlend(const Mat_<Vec3f>& l, const Mat_<Vec3f>& r, const Mat_<float>& m) {
    LaplacianBlending lb(l, r, m, 4);
    return lb.blend();
}




void MainWindow::on_BtnFusion_clicked()
{


    vector<Mat> 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> alignMTB = createAlignMTB();
    alignMTB->process(images, images);

           //曝光合成(Mertens是该论文的作者)被OpenCV集成为函数了
    Mat Fusion;
    Ptr<MergeMertens> 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<cv::Feature2D> orb = cv::ORB::create();

        // 在两张图像上分别检测特征点和计算描述子
        std::vector<cv::KeyPoint> 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<cv::DMatch> 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<cv::DMatch> 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:

文章来源:https://blog.csdn.net/Heart912921/article/details/134977037
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。