基础学习笔记之opencv(10):Mat mask操作

  本文主要讲讲怎样对Mat矩阵进行mask操作,其实也就是对Mat矩阵的滤波操作,俗称卷积,参考文献为opencv自带的tutiol及其code.

  开发环境:ubuntu12.04+opencv2.4.2+Qt4.8.2+QtCreator2.5.

 

  实验功能:

  单击Open image按钮,手动选择所需滤波的原图片。

  单击Setting按钮,弹出对话框,选择滤波所用的模式,这里有2种模式,分别为自己实现滤波功能和采用opencv自带的滤波函数filter2D实现。

  单击Process按钮,实现图片滤波过程,并将滤波结果显示在图片窗口中。

  滤波完成后,图片下方法显示滤波所采用的模式及其花耗的时间。可以方便对2种模式的效率进行对比。

 

  实验说明:

  这次实验图片的显示与前几篇博客中采用的方法不同,前几次是将图片显示在QLabel中,这次是显示在QTextBrowser中。当在QLabel中显示时,直接SetPixmap将图片内容显示上去;而在QTextBrowser中,是加载图片路径名,然后直接挂载的(不需要使用opencv中的imread函数)

  opencv中的saturate_cast函数,其实就是一个类型转换函数,将圆弧括号中的类型转换成尖括号中的类型。

  opencv中的setTo函数是将指定的元素设置为指定的值,可以使用mask矩阵掩码。

  在Qt中,如果第1个窗口类要调用第2个窗口类,且我们需要在进行第2个窗口操作时改变第1个窗口类中某些变量,这时我们不能直接改变,因为是第1个类调用第2个类,所以不能由第2个类反过来改变第1个类的值,当遇到这种情况时,我们只需要将第2个类中改变的值保存在其public中即可。然后当第1个类的某个变量需要改变时,直接用第2个类中对应的public变量赋值即可,具体可见下面给出的代码。

  在类的构造函数中建立的变量,该变量的生命周期是整个类的生命周期,所以该类中其它所有函数都可以使用该变量。

 

  实验结果:

  打开原始图片后:

  

  模式设置对话框:

  

 

  自己实现mask结果:

  

  用opencv自带filter2D实现结果:

  

  

实验主要部分代码及注释(附录有工程code下载链接)

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QtGui>
#include <QTextDocument>
#include <iostream>

using namespace std;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    mask_mode = 1;
    ui->textBrowser->setStyleSheet( "background-color:black" );//这种参数更简单
    ui->textBrowser->setTextColor( Qt::green );
    set = new setting( this );//在构造函数中开辟的内存作用与该类的所有函数
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_closeButton_clicked()
{
    close();
}

void MainWindow::on_openButton_clicked()
{
    QString img_name = QFileDialog::getOpenFileName( this, "Open Image", "../mask/", tr("Image Naems( *.png *.jpeg *.jpg *.bmp )"));
    img = imread( img_name.toAscii().data() );
    img1 = img.clone();
    cvtColor( img1, img1, CV_BGR2RGB );
    QImage qimg = QImage( (const unsigned char*)img1.data, img1.cols, img1.rows, QImage::Format_RGB888 );

    //这是在textBrowser里显示图片的另一种方法。<img src='***'>这些都是固定的.
    //如果是string后要接arg,则不能直接""后面接,可以采用tr或QString括起来。
 //   ui->textBrowser->append( tr("<img src='%1'>").arg(img_name );
    ui->textBrowser->clear();
    ui->textBrowser->append( tr("<img src='%1'>").arg( img_name ) );
    ui->textBrowser->append( tr("the mask mode is realize by myself......") );

}

int MainWindow::on_settingButton_clicked()
{
   // set = new setting( this );//如果在这个地方进行new的话,则不能保存上次设置的结果,因此应该在构造函数中new
    set->show();
}

void MainWindow::on_processButton_clicked()
{

    mask_mode = set->set_mask_mode;
    img1 = img.clone();
    Mat img2;
    img2.create( img1.size(), img1.type() );
    CV_Assert( img1.depth() == CV_8U );
    if( 1 == mask_mode )
        {
           double t = getTickCount();
           int rows = img1.rows;
           int cols = img1.cols;
           int channels = img1.channels();
           for( int i = 1; i < rows-1; i++ )
               {
                     uchar *current = img1.ptr<uchar>( i );
                     uchar *previous = img1.ptr<uchar>( i-1 );
                     uchar *next = img1.ptr<uchar>( i+1 );
                     uchar *output = img2.ptr<uchar>( i );
                     for( int j = channels; j < channels*(cols-1); j++ )
                         {
                            *output++ = saturate_cast<uchar>( 5*current[j]-current[j-channels]-current[j+channels]
                                                              -previous[j]-next[j]);
                         }
               }
           img2.row(0).setTo(Scalar(0));
           img2.row(rows-1).setTo(Scalar(0));
           img2.col(0).setTo(Scalar(0));
           img2.col(cols-1).setTo(Scalar(0));
           t = (getTickCount()-t)/getTickFrequency()*1000;
           imwrite( "lena1.jpg", img2 );
           ui->textBrowser->clear();
           ui->textBrowser->append(tr("<img src=./lena1.jpg>"));
           ui->textBrowser->append( tr("the mask mode is realize by myself......") );
           ui->textBrowser->append( tr("the time running cost %1ms").arg(t) );
        }

    else if( 2 == mask_mode )
        {
            double t = getTickCount();
            Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
            filter2D( img1, img2, -1, kernel );
            t = (getTickCount()-t)/getTickFrequency()*1000;
            imwrite( "lena2.jpg", img2 );
            ui->textBrowser->clear();
            ui->textBrowser->append(tr("<img src=./lena2.jpg>"));
            ui->textBrowser->append( tr("the mask mode is filter2D of the opencv......") );
            ui->textBrowser->append( tr("the time running cost %1ms").arg(t) );
        }
}

 

 

setting.cpp:

#include "setting.h"
#include "ui_setting.h"

setting::setting(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::setting)
{
    ui->setupUi(this);

    set_mask_mode = 1;
}

setting::~setting()
{
    delete ui;
}

void setting::on_closeButton_clicked()
{
    close();
    ui->~setting();
}

void setting::on_realizeButton_clicked()
{
    if( ui->realizeButton->isChecked() )
        {
            set_mask_mode = 1;
        }

}

void setting::on_filter2dButton_clicked()
{
    if( ui->filter2dButton->isChecked() )
        {
            set_mask_mode = 2;
        }
}

 

  实验总结:

  通过本次实验可以看到,虽然上面2种模式都实现了滤波功能,不过opencv自带的filter2Dlena这张图片才用3ms,而自己实现的函数用了7.5ms,差不多慢了1倍。由此可见,opencv中很多函数是进行了优化的。

 

  附:工程code下载。

 

 

 

 

 

posted on 2012-07-23 18:21  tornadomeet  阅读(14378)  评论(0编辑  收藏  举报

阿萨德发斯蒂芬