OPENCV学习笔记3-4_使用模型-视图-控制器设计应用程序

  此节介绍的架构模式(MVC),将联合使用模型-视图-控制器(Model-View-Controller)三个模式以及其他的类。其清晰地分离程序中的逻辑部分与用户交互部分。此节将使用MVC模式构建一个基于QT的图形界面应用程序。

  模型包含关于应用程序的信息,它拥有所有由应用程序处理的数据。当出现新的数据,它将告知控制器,后者要求视图来显示结果。通常模型将集合多个算法,它们很有可能按照策略模式进行实现。

  视图职责之一是发送用户的命令到控制器。当新数据可用时,它会刷新自己以显示新的信息。

  控制器将视图和模型桥接在一起。接收视图的请求,并转化为模型中的合适方法。它也会在模型更改状态时,得到通知,并请求视图刷新以显示新的信息。

  本模型使用ColorDetector类,包含应用程序的逻辑和底层数据。然后实现一个控制器即ColorDetectController类。MVC架构下,用户界面只是简单地调用控制器方法,不包含任何应用数据,也没实现任何应用逻辑。因此,容易替换接口。

#include <QApplication>

#include "mainwindow.h"

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

main.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    //select color
    connect(ui->pushButton_color, SIGNAL(clicked()), this, SLOT(setColor()));
    connect(ui->actionChoose_Color, SIGNAL(triggered()), this, SLOT(setColor()));

    //open image
    connect(ui->pushButton_openImage, SIGNAL(clicked()), this, SLOT(setImage()));
    connect(ui->actionOpen_Image, SIGNAL(triggered()), this, SLOT(setImage()));

    //process Color Detection
    connect(ui->pushButton_process, SIGNAL(clicked()), this, SLOT(processColorDetection()));
    connect(ui->actionProcess, SIGNAL(triggered()), this, SLOT(processColorDetection()));

}

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

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void MainWindow::setImage()
{
    QFileDialog::Options options;
    QString selectedFilter;
    QString fileName = QFileDialog::getOpenFileName(this,
                                tr("Open Image Files"),
                                "",
                                tr("Image files (*.jpg *.jpeg *.png *.gif *.bmp)"),
                                &selectedFilter,
                                options);
    if (!fileName.isEmpty()){
        //在Qt的应用程序中定义的fileName是QString类型,而cout只能输出String类型
        //要将QString类型转换为String类型

        cv::Mat img_mat = cv::imread(fileName.toStdString(),1); //0 for grayscale
        displayMat(img_mat);
    }
    //Set Filename
    ColorDetectController::getInstance()->setInputImage(fileName.toStdString());
}

//Convert cv::Mat to QImage and display
void MainWindow::displayMat(const cv::Mat& image){

    //BGR openCV Mat to QImage
    QImage img_qt = QImage((const unsigned char*)image.data,image.cols, image.rows, image.step, QImage::Format_RGB888);

    //For Binary Images
    if (img_qt.isNull()){
        //ColorTable for Binary Images
        QVector<QRgb> colorTable;
        for (int i = 0; i < 256; i++)
            colorTable.push_back(qRgb(i, i, i));

        img_qt = QImage((const unsigned char*)image.data,image.cols, image.rows, QImage::Format_Indexed8);
        img_qt.setColorTable(colorTable);
        }

    //Display the QImage in the Label
    //简单地转换一下为Image对象,rgbSwapped是为了显示效果色彩好一些。
    QPixmap img_pix = QPixmap::fromImage(img_qt.rgbSwapped()); //BGR to RGB
    //  pix = pix.scaled(width*2,height*2,Qt::KeepAspectRatio);
    //  将图片的宽和高都扩大两倍,并且在给定的矩形内保持宽高的比值

    this->ui->label->setPixmap(img_pix.scaled(ui->label->size(), Qt::KeepAspectRatio));
}

void MainWindow::on_verticalSlider_Threshold_valueChanged(int value)
{
    QString cdt("Color Distance Threshold: ");
    cdt.append(QString::number(value));
    this->ui->label_2->setText(cdt);
}

void MainWindow::setColor()
{
    QColor color = QColorDialog::getColor(Qt::green, this); //打开颜色对话框时,默认是Qt::white
    if (color.isValid()) {
       ColorDetectController::getInstance()->setTargetColor(color.red(),color.green(),color.blue());
    }
}

void MainWindow::processColorDetection()
{
    ColorDetectController::getInstance()->setColorDistanceThreshold(ui->verticalSlider_Threshold->value());
    ColorDetectController::getInstance()->process();

    cv::Mat resulting = ColorDetectController::getInstance()->getLastResult();
    if (!resulting.empty())
        displayMat(resulting);

}

mainwindow.cpp

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QColorDialog>

//OpenCV
#include "cv.h"
#include "highgui.h"

//color detector, controller
#include "colorDetectController.h"
#include "colordetector.h"

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void changeEvent(QEvent *e);
    void displayMat(const cv::Mat& img);

    //Main Image
    //cv::Mat img_mat;

private:
    Ui::MainWindow *ui;

private slots:
    void on_pushButton_color_clicked();
    void processColorDetection();
    void on_verticalSlider_Threshold_valueChanged(int value);

    void setColor();
    void setImage();

};

#endif // MAINWINDOW_H

mainwindow.h

#include "colorDetectController.h"

ColorDetectController *ColorDetectController::singleton=0; 

colorDetectController.cpp

#if !defined CD_CNTRLLR
#define CD_CNTRLLR

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "colordetector.h"

class ColorDetectController {

  private:

     static ColorDetectController *singleton; // pointer to the singleton

    ColorDetector *cdetect;

    // The image to be processed
    cv::Mat image;
    cv::Mat result;

  public:
    ColorDetectController() { // private constructor

          //setting up the application
          cdetect= new ColorDetector();
    }

      // Sets the color distance threshold
      void setColorDistanceThreshold(int distance) {

          cdetect->setColorDistanceThreshold(distance);
      }

      // Gets the color distance threshold
      int getColorDistanceThreshold() const {

          return cdetect->getColorDistanceThreshold();
      }

      // Sets the color to be detected
      void setTargetColor(unsigned char red, unsigned char green, unsigned char blue) {

          cdetect->setTargetColor(red,green,blue);
      }

      // Gets the color to be detected
      void getTargetColor(unsigned char &red, unsigned char &green, unsigned char &blue) const {

          cv::Vec3b color= cdetect->getTargetColor();

          red= color[2];
          green= color[1];
          blue= color[0];
      }

      // Sets the input image. Reads it from file.
      bool setInputImage(std::string filename) {

          image= cv::imread(filename);

          if (!image.data)
              return false;
          else
              return true;
      }

      // Returns the current input image.
      const cv::Mat getInputImage() const {

          return image;
      }

      // Performs image processing.
      void process() {

          result= cdetect->process(image);
      }

      // Returns the image result from the latest processing.
      const cv::Mat getLastResult() const {

          return result;
      }

      // Deletes all processor objects created by the controller.
      ~ColorDetectController() {

          delete cdetect;
      }

      // Singleton static members
      static ColorDetectController *getInstance() {

          if (singleton == 0)
            singleton= new ColorDetectController;

          return singleton;
      }

      // Releases the singleton instance of this controller.
      static void destroy() {

          if (singleton != 0) {
              delete singleton;
              singleton= 0;
          }
      }
};

colorDetectController.h

#include "colordetector.h"

cv::Mat ColorDetector::process(const cv::Mat &image) {

      // re-allocate binary map if necessary
      // same size as input image, but 1-channel
      result.create(image.rows,image.cols,CV_8U);

      // re-allocate intermediate image if necessary
      converted.create(image.rows,image.cols,image.type());

      // Converting to Lab color space
      cv::cvtColor(image, converted, CV_BGR2Lab);

      // get the iterators
      cv::Mat_<cv::Vec3b>::iterator it= converted.begin<cv::Vec3b>();
      cv::Mat_<cv::Vec3b>::iterator itend= converted.end<cv::Vec3b>();
      cv::Mat_<uchar>::iterator itout= result.begin<uchar>();

      // for each pixel
      for ( ; it!= itend; ++it, ++itout) {

        // process each pixel ---------------------

          // compute distance from target color
          if (getDistance(*it)<minDist) {

              *itout= 255;

          } else {

              *itout= 0;
          }

        // end of pixel processing ----------------
      }

      return result;
}

colordetector.cpp

#if !defined COLORDETECT
#define COLORDETECT

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

class ColorDetector {

  private:

      // minimum acceptable distance
      int minDist; 

      // target color
      cv::Vec3b target; 

      // image containing resulting binary map
      cv::Mat result;

      // image containing color converted image
      cv::Mat converted;

      // inline private member function
      // Computes the distance from target color.
      int getDistance(const cv::Vec3b& color) const {
         // return static_cast<int>(cv::norm<int,3>(cv::Vec3i(color[0]-target[0],color[1]-target[1],color[2]-target[2])));
          return abs(color[0]-target[0])+
                    abs(color[1]-target[1])+
                    abs(color[2]-target[2]);
      }

  public:

      // empty constructor
      ColorDetector() : minDist(100) { 

          // default parameter initialization here
          target[0]= target[1]= target[2]= 0;
      }

      // Getters and setters

      // Sets the color distance threshold.
      // Threshold must be positive, otherwise distance threshold
      // is set to 0.
      void setColorDistanceThreshold(int distance) {

          if (distance<0)
              distance=0;
          minDist= distance;
      }

      // Gets the color distance threshold
      int getColorDistanceThreshold() const {

          return minDist;
      }

      // Sets the color to be detected
      void setTargetColor(unsigned char red, unsigned char green, unsigned char blue) {

          cv::Mat tmp(1,1,CV_8UC3);              //创建一个一行一列有三通道像素
          tmp.at<cv::Vec3b>(0,0)[0]= blue;
          tmp.at<cv::Vec3b>(0,0)[1]= green;
          tmp.at<cv::Vec3b>(0,0)[2]= red;

            // Converting the target to Lab color space
          cv::cvtColor(tmp, tmp, CV_BGR2Lab);    //使用/usr/local/lib/libopencv_imgproc.so

          target= tmp.at<cv::Vec3b>(0,0);
      }

      // Sets the color to be detected
      void setTargetColor(cv::Vec3b color) {

          cv::Mat tmp(1,1,CV_8UC3);
          tmp.at<cv::Vec3b>(0,0)= color;

            // Converting the target to Lab color space
          cv::cvtColor(tmp, tmp, CV_BGR2Lab);

          target= tmp.at<cv::Vec3b>(0,0);
      }

      // Gets the color to be detected
      cv::Vec3b getTargetColor() const {

          return target;
      }

      // Processes the image. Returns a 1-channel binary image.
      cv::Mat process(const cv::Mat &image);
};

#endif

colordetector.h

时间: 2024-10-01 19:42:33

OPENCV学习笔记3-4_使用模型-视图-控制器设计应用程序的相关文章

Django学习笔记(三)—— 模型 model

疯狂的暑假学习之 Django学习笔记(三)-- 模型 model 参考:<The Django Book> 第5章 1.setting.py 配置 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', # 用什么数据库管理系统 'NAME': '', # 数据库名称,如果用sqlite,要写完整路径 'USER': '', # 如果用sqlite,这个不用写 'PASSWORD': '', # 如果用sqlite,这个不用写

OpenCV学习笔记[5]FLANN特征匹配

OpenCV学习笔记:FLANN特征匹配 本次给出FLANN特征匹配的Java实现. [简介] 特征匹配记录下目标图像与待匹配图像的特征点(KeyPoint),并根据特征点集合构造特征量(descriptor),对这个特征量进行比较.筛选,最终得到一个匹配点的映射集合.我们也可以根据这个集合的大小来衡量两幅图片的匹配程度. 特征匹配与模板匹配不同,由于是计算特征点集合的相关度,转置操作对匹配影响不大,但它容易受到失真.缩放的影响. [特征匹配] FeatureMatching.java: imp

opencv学习笔记(七)SVM+HOG

opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的梯度直方图来构成特征.Hog特征结合SVM分类器已经被广泛用于图像识别中,尤其在行人检测中获得了极大的成功.需要提醒的是,HOG+SVM进行行人检测的方法是法国研究院Dalal在2005的CVPR上提出的. 最近在做车标识别相关的研究,用到了SVM+HOG的方法进行识

angular学习笔记(十七)-路由和切换视图

本篇介绍angular中如何通过判断url的hash值来显示不同的视图模板,并使用不同的控制器: 下面,通过一个例子,来一步一步说明它的用法: 我们要做一个邮箱应用,打开的时候显示的是邮件列表: 然后点击邮件主题,可以查看该邮件的详细内容: 点击返回列表,再回到列表页 一. 创建index页面: <!DOCTYPE html> <html> <head> <title>14.1路由和视图切换</title> <meta charset=&q

ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习

一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留下来的ASPX引擎或者第三方的NVelocity模板引擎. Razor在减少代码冗余.增强代码可读性和Visual Studio智能感知方面,都有着突出的优势.Razor一经推出就深受广大ASP.Net开发者的喜爱. 1.2 Razor的语法 (1)Razor文件类型:Razor支持两种文件类型,分

Opencv学习笔记(六)SURF学习笔记

原创文章,转载请注明出处:http://blog.csdn.net/crzy_sparrow/article/details/7392345 本人挺菜的,肯定有非常多错误纰漏之处 ,希望大家不吝指正. 看了harris角点检測之后,開始研究SURF角点检測,发现挺复杂的,一时也仅仅了解了大概,把了解的东西总结下,以便下次深入学习. SURF角点检測算法是对SIFT的一种改进,主要体如今速度上,效率更高.它和SIFT的主要差别是图像多尺度空间的构建方法不同. 在计算视觉领域,尺度空间被象征性的表述

最大熵学习笔记(四)模型求解

  生活中我们经常听到人们说"不要把鸡蛋放到一个篮子里",这样可以降低风险.深究一下,这是为什么呢?其实,这里边包含了所谓的最大熵原理(The Maximum Entropy Principle).本文为一则读书笔记,将对最大熵原理以及由此导出的最大熵模型进行介绍,重点给出其中所涉及数学公式的理解和详细推导. 相关链接 最大熵学习笔记(零)目录和引言 最大熵学习笔记(一)预备知识 最大熵学习笔记(二)最大熵原理 最大熵学习笔记(三)最大熵模型 最大熵学习笔记(四)模型求解 最大熵学习笔

opencv学习笔记(四)投影

opencv学习笔记(四)投影 任选了一张图片用于测试,图片如下所示: 1 #include <cv.h> 2 #include <highgui.h> 3 using namespace std; 4 using namespace cv; 5 int main() 6 { 7 IplImage * src = cvLoadImage("cat.png", 0); //强制转化读取图像为灰度图 8 cvShowImage("灰度图像", s

OpenCV学习笔记(01)我的第一个OpenCV程序(环境配置)

昨天刚刚考完编译原理,私心想着可以做一些与考试无关的东西了.一直想做和图像处理相关的东西,趁这段时间有空学习一下OpenCV,搭建环境真是一件麻烦的事情,搞了近三个小时终于OK了.先来张图: 大致描述一下步骤吧: 一.安装前准备 1.VS2012(网上看到很多用的VS2010,但是基本不影响) 2.OpenCV 安装包(我下载的是最新的2.4.9) 二.安装OpenCV 1.解压OPenCV 说是安装,其实就是解压,OpenCV的Windows安装程序就是一个自解压程序: 这里我解压到C:\Pr