基礎學習筆記之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下載。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM