天天看点

QT+opencv ROI区域图像叠加&初级图像混合 label里输出Mat图片要做的变换

虽然使用opencv大多不使用ui,但是这次输出的图像用来对比比较有意义,我为了让他们输出在界面上好看一些,弄了一下午,达到如下效果。

QT+opencv ROI区域图像叠加&初级图像混合 label里输出Mat图片要做的变换

1.

先说一下QT label中输出opencv Mat图像的事情:

因为使用Imread读入的Mat图像,其矩阵格式是BGR的,我们在label上输出只能使用QT自带的比如QPixmap函数,此时就要对Mat图像进行转化。

主要就3行代码,如下 srcImage4就是用imread读入的图像,或者你经过各种其他处理之后的Mat型的数据就行。先使用cvtColor把BGR颜色空间换成QImage图像的RGB颜色空间,用QImage读入数据,在label上输出就行。

后两句代码是对label中输出图像的设置,可以使图像按照label大小直接输出。

Mat srcImage4 = imread("girl.jpg");
    QImage img4;

    cvtColor(srcImage4,srcImage4,CV_BGR2RGB);
    img4=QImage((const unsigned char*)(srcImage4.data),                                                              
            srcImage4.cols,srcImage4.rows,QImage::Format_RGB888);                                        

    ui->label_4->setScaledContents(true);
    ui->label_4->resize(ui->label->width(),ui->label->height());
           

2.

void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-);  
           
第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
第二个参数,alpha,表示第一个数组的权重
第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
第四个参数,beta,表示第二个数组的权重值。
第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
           

简单来说,就是把Mat类型的图片src1和src2以alpha:beta的比例加在一起显示出来。

如果用数学公式来表达,addWeighted函数计算如下两个数组(src1和src2)的加权和,得到结果输出给第四个参数。即addWeighted函数的作用可以被表示为为如下的矩阵表达式为:

dst = src1[I]*alpha+ src2[I]*beta + gamma;
           

其中的I,是多维数组元素的索引值。而且,在遇到多通道数组的时候,每个通道都需要独立地进行处理。另外需要注意的是,当输出数组的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。

窗口输出源代码:

#include <QCoreApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <qdebug.h>
using namespace cv;
using namespace std;

 //-----------------------------------【全局函数声明部分】--------------------------------------
    //  描述:全局函数声明
    //-----------------------------------------------------------------------------------------------
    bool  ROI_AddImage();
    bool  LinearBlending();
    bool  ROI_LinearBlending();

    //-----------------------------------【main( )函数】--------------------------------------------
    //  描述:控制台应用程序的入口函数,我们的程序从这里开始
    //-----------------------------------------------------------------------------------------------
    int main(   )
    {

        if(ROI_AddImage( )&& LinearBlending( )&&ROI_LinearBlending( ))
        {
             qDebug() << QString::fromLocal8Bit("输出貌似成功了!");
        }

        waitKey();
        return ;
    }

    //----------------------------------【ROI_AddImage( )函数】----------------------------------
    // 函数名:ROI_AddImage()
    //  描述:利用感兴趣区域ROI实现图像叠加
    //----------------------------------------------------------------------------------------------
    bool  ROI_AddImage()
    {

        // 【1】读入图像
        Mat srcImage1= imread("dota_pa.jpg");
        Mat logoImage= imread("dota_logo.jpg");
        if( !srcImage1.data ) { printf("  读取srcImage1错误~! \n"); return false; }
        if( !logoImage.data ) { printf("  读取logoImage错误~! \n"); return false; }

        // 【2】定义一个Mat类型并给其设定ROI区域
        Mat imageROI= srcImage1(Rect(,,logoImage.cols,logoImage.rows));

        // 【3】加载掩模(必须是灰度图)
        Mat mask= imread("dota_logo.jpg",);

        //【4】将掩膜拷贝到ROI
        logoImage.copyTo(imageROI,mask);

        // 【5】显示结果
        namedWindow("<1>利用ROI实现图像叠加示例窗口",WINDOW_NORMAL);
        imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);

        return true;
    }


    //---------------------------------【LinearBlending()函数】-------------------------------------
    // 函数名:LinearBlending()
    // 描述:利用cv::addWeighted()函数实现图像线性混合
    //--------------------------------------------------------------------------------------------
    bool  LinearBlending()
    {
        //【0】定义一些局部变量
        double alphaValue = ;
        double betaValue;
        Mat srcImage2, srcImage3, dstImage;

        // 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )
        srcImage2 = imread("mogu.jpg");
        srcImage3 = imread("rain.jpg");

        if( !srcImage2.data ) { printf("  读取srcImage2错误~! \n"); return false; }
        if( !srcImage3.data ) { printf("  读取srcImage3错误~! \n"); return false; }

        // 【2】进行图像混合加权操作
        betaValue = (  - alphaValue );
        addWeighted( srcImage2, alphaValue, srcImage3, betaValue, , dstImage);

        // 【3】创建并显示原图窗口
        namedWindow("<2>线性混合示例窗口【原图】  ", WINDOW_NORMAL);
        imshow( "<2>线性混合示例窗口【原图】  ", srcImage2 );

        namedWindow("<3>线性混合示例窗口【效果图】  ", WINDOW_NORMAL);
        imshow( "<3>线性混合示例窗口【效果图】  ", dstImage );

        return true;

    }

    //---------------------------------【ROI_LinearBlending()】-------------------------------------
    // 函数名:ROI_LinearBlending()
    // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义
    //            感兴趣区域ROI,实现自定义区域的线性混合
    //--------------------------------------------------------------------------------------------
    bool  ROI_LinearBlending()
    {

        //【1】读取图像
        Mat srcImage4= imread("dota_pa.jpg",);
        Mat logoImage= imread("dota_logo.jpg");

        if( !srcImage4.data ) { printf("  读取srcImage4错误~! \n"); return false; }
        if( !logoImage.data ) { printf("  读取logoImage错误~! \n"); return false; }

        //【2】定义一个Mat类型并给其设定ROI区域
        Mat imageROI;
            //方法一
        imageROI= srcImage4(Rect(,,logoImage.cols,logoImage.rows));
        //方法二
        //imageROI= srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));

        //【3】将logo加到原图上
        addWeighted(imageROI,,logoImage,,,imageROI);

        //【4】显示结果
        namedWindow("<4>区域线性图像混合示例窗口  " ,WINDOW_NORMAL);
        imshow("<4>区域线性图像混合示例窗口  ",srcImage4);

         return true;
      }
           

MIX1 无ui界面版

UI输出源代码

3个文件

- mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <qdebug.h>
#include <qlabel.h>

using namespace cv;
using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = );
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    Mat srcImage1;
    Mat logoImage;
    Mat imageROI;
    Mat mask;
    Mat srcImage2, srcImage3, dstImage;
    Mat srcImage4;
    QImage img1,img2,img2_1,img2_2,img4;
};

#endif // MAINWINDOW_H
           
  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <qdebug.h>
#include <qlabel.h>

using namespace cv;
using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    srcImage1= imread("dota_pa.jpg");
    logoImage= imread("dota_logo.jpg");

    // 【】定义一个Mat类型并给其设定ROI区域
    imageROI= srcImage1(Rect(,,logoImage.cols,logoImage.rows));

    // 【】加载掩模(必须是灰度图)
    mask= imread("dota_logo.jpg",);

    //【】将掩膜拷贝到ROI
    logoImage.copyTo(imageROI,mask);

    cvtColor(srcImage1,srcImage1,CV_BGR2RGB);
    img1=QImage((const unsigned char*)(srcImage1.data),srcImage1.cols,srcImage1.rows,QImage::Format_RGB888);
    ui->label->setPixmap(QPixmap::fromImage(img1));
    ui->label->setScaledContents(true);
    ui->label->resize(ui->label->width(),ui->label->height());
    //ui->label->resize(ui->label->pixmap()->size());





    // 【】读取图像 ( 两幅图片需为同样的类型和尺寸 )
    srcImage2 = imread("mogu.jpg");
    srcImage3 = imread("rain.jpg");

    // 【】进行图像混合加权操作

    addWeighted( srcImage2, , srcImage3, , , dstImage);

    cvtColor(dstImage,dstImage,CV_BGR2RGB);
    img2=QImage((const unsigned char*)(dstImage.data),dstImage.cols,dstImage.rows,QImage::Format_RGB888);
    ui->label_2->setPixmap(QPixmap::fromImage(img2));
    ui->label_2->setScaledContents(true);
    ui->label_2->resize(ui->label->width(),ui->label->height());

    cvtColor(srcImage2,srcImage2,CV_BGR2RGB);
    img2_1=QImage((const unsigned char*)(srcImage2.data),srcImage2.cols,srcImage2.rows,QImage::Format_RGB888);
    ui->label_3->setPixmap(QPixmap::fromImage(img2_1));
    ui->label_3->setScaledContents(true);
    ui->label_3->resize(ui->label->width(),ui->label->height());

    cvtColor(srcImage3,srcImage3,CV_BGR2RGB);
    img2_2=QImage((const unsigned char*)(srcImage3.data),srcImage3.cols,srcImage3.rows,QImage::Format_RGB888);
    ui->label_5->setPixmap(QPixmap::fromImage(img2_2));
    ui->label_5->setScaledContents(true);
    ui->label_5->resize(ui->label->width(),ui->label->height());





    srcImage4= imread("dota_pa.jpg",);
    logoImage= imread("dota_logo.jpg");

        //方法一
    imageROI= srcImage4(Rect(,,logoImage.cols,logoImage.rows));


    //【】将logo加到原图上
    addWeighted(imageROI,,logoImage,,,imageROI);

    cvtColor(srcImage4,srcImage4,CV_BGR2RGB);
    img4=QImage((const unsigned char*)(srcImage4.data),srcImage4.cols,srcImage4.rows,QImage::Format_RGB888);
    ui->label_4->setPixmap(QPixmap::fromImage(img4));
    ui->label_4->setScaledContents(true);
    ui->label_4->resize(ui->label->width(),ui->label->height());




}

MainWindow::~MainWindow()
{
    delete ui;
}
           
  • main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <qdebug.h>
#include <qlabel.h>
using namespace cv;
using namespace std;


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

         qDebug() << QString::fromLocal8Bit("输出貌似成功了!");

    waitKey();
    return a.exec();
}
           

MIX2 ui界面版