zoukankan      html  css  js  c++  java
  • OpenCV&Qt学习之一——打开图片文件并显示

    摸索了一段时间了,期间杂七杂八干了很多零活,花在这上面的时间不是太多,现在回头把资料简单整理。

    OpenCV和Qt学习在入门阶段最大的困惑时版本不统一所带来的影响,Qt稍微好一点,OpenCV目前的大多数资料都是基于1.0版本的,而我用的2.4.3(刚更新了2.4.4)在使用上还是有很多区别的,在使用相关的资料的时候就会带来很大的困惑。

    OpenCV的版本区别


    由于我连入门都算不上,更多的变化我也不懂,所以只能简单记录下。

    从2.2版本以后OpenCV库被划分为几个模块,这些模块就对应着相应的库目录,如下图所示。

    image

    下面简要介绍整理几个主要模块,这块主要还是根据我的理解,详细信息可以参见安装目录下The OpenCV Tutorials 文档。

    1. opencv_core模块包含了opencv的核心功能,尤其是包含了基础的数据结构和算法功能
    2. opencv_imgproc模块包含了主要的图像处理功能
    3. opencv_highgui模块图像和视频的读写以及其他用户界面
    4. opencv_features2d模块包含了特征点的探测和描述以及匹配框架
    5. opencv_calib3d模块包含了相机配准校正,双目立体视觉以及三维重建相关功能
    6. opencv_video模块包含了视频分析的相关功能,如运动估计,特征跟踪,前景提取等
    7. opencv_objdetect模块包含了例如人脸检测之类的目标检测功能

    而2.2以后的版本头文件包含也改为:

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

    而老版本中多半是这样的方式:

    #include "cv.h"
    #include "highgui.h"

    为了保持对之前版本的兼容,这些头文件仍然能够使用,但是建议使用新的包含方式,cv.h文件如下,从中可以看出本质上这个文件已经包含了对2.2以后版本的头文件包含。

    #ifndef __OPENCV_OLD_CV_H__
    #define __OPENCV_OLD_CV_H__
    
    #if defined(_MSC_VER)
        #define CV_DO_PRAGMA(x) __pragma(x)
        #define __CVSTR2__(x) #x
        #define __CVSTR1__(x) __CVSTR2__(x)
        #define __CVMSVCLOC__ __FILE__ "("__CVSTR1__(__LINE__)") : "
        #define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (__CVMSVCLOC__ _msg))
    #elif defined(__GNUC__)
        #define CV_DO_PRAGMA(x) _Pragma (#x)
        #define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (_msg))
    #else
        #define CV_DO_PRAGMA(x)
        #define CV_MSG_PRAGMA(_msg)
    #endif
    #define CV_WARNING(x) CV_MSG_PRAGMA("Warning: " #x)
    
    //CV_WARNING("This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module")
    
    #include "opencv2/core/core_c.h"
    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc_c.h"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/video/tracking.hpp"
    #include "opencv2/features2d/features2d.hpp"
    #include "opencv2/flann/flann.hpp"
    #include "opencv2/calib3d/calib3d.hpp"
    #include "opencv2/objdetect/objdetect.hpp
    #include "opencv2/legacy/compat.hpp"
    
    #if !defined(CV_IMPL)
    #define CV_IMPL extern "C"
    #endif //CV_IMPL
    
    #if defined(__cplusplus)
    #include "opencv2/core/internal.hpp"
    #endif //__cplusplus
    
    #endif // __OPENCV_OLD_CV_H_

    在更具体的接触上,细节地方还有很多,所以在网络上找参考程序的时候需要区分对待。

    Qt下的OpenCV入门例程


    一些基础性的东西可以参见之前的博客,这里贴出主要代码,这个小例子完成一个主要的功能,打开图片并显示。打开图片利用Qt的标准文件对话框,第一步是利用OpenCV创建窗口并显示。添加一个Button,转到信号槽添加代码:

    void Widget::on_openButton_clicked()
    {
        QString fileName = QFileDialog::getOpenFileName(this,tr("Open Image"),
                                    ".",tr("Image Files (*.png *.jpg *.bmp)"));
        qDebug()<<"filenames:"<<fileName;
        image = cv::imread(fileName.toAscii().data());
        cv::namedWindow(fileName.toAscii().data(),CV_WINDOW_AUTOSIZE));    //display use a new window
        cv::imshow((fileName.toAscii().data(), image);
    }

    同时还需要在对应的头文件中添加变量定义并添加对应的头文件:

    private:
        Ui::Widget *ui;
        cv::Mat image;

    这样就完成了一个基本的载入图像并显示的功能。

    单独弹出一个窗口并显示还是觉得不爽,下面实现Qt的窗体中显示图片, 显示的方法也有很多,不同显示方法存在着效率等各方面的问题,这里使用QImage转QPixmap,然后用QLabel::setPixmap()来完成显示,还有比较常用的方法是在paintEvent()中直接画,具体的差异没有去深究,这里使用第一种方式。

    图片的显示主要问题还是在于QImage与Mat格式的不同,其中QImage是RGB排列,而Mat 是 BGR,同时两者格式包含的内容页不同,因此需要经过转换才能够显示。

    下面直接给出主要文件的代码:

    widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include <QDebug>
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::on_openButton_clicked()
    {
        QString fileName = QFileDialog::getOpenFileName(this,tr("Open Image"),
                                    ".",tr("Image Files (*.png *.jpg *.bmp)"));
        qDebug()<<"filenames:"<<fileName;
        image = cv::imread(fileName.toAscii().data());
    //    cv::namedWindow((fileName.toAscii().data()),CV_WINDOW_AUTOSIZE);    //display use a new window
    //    cv::imshow((fileName.toAscii().data()), image);
        displayMat(image);                      //display by the label
    }
    
    //void Widget::displayMat(const cv::Mat &image)
    void Widget::displayMat(Mat image)
    {
        Mat rgb;
        QImage img;
        if(image.channels()==3)
        {
            //cvt Mat BGR 2 QImage RGB
            cvtColor(image,rgb,CV_BGR2RGB);
            img =QImage((const unsigned char*)(rgb.data),
                        rgb.cols,rgb.rows,
                        rgb.cols*rgb.channels(),
                        QImage::Format_RGB888);
        }
        else
        {
            img =QImage((const unsigned char*)(image.data),
                        image.cols,image.rows,
                        image.cols*image.channels(),
                        QImage::Format_RGB888);
        }
    
        ui->imagelabel->setPixmap(QPixmap::fromImage(img));
        ui->imagelabel->resize(ui->imagelabel->pixmap()->size());
    }

    widegt.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QImage>
    #include <QFileDialog>
    #include <QTimer>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    
    using namespace cv;
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
        
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
        
    private slots:
        void on_openButton_clicked();
       //void displayMat(const cv::Mat &image);
        void displayMat(Mat image);
    
    
    
    private:
        Ui::Widget *ui;
        cv::Mat image;
    };
    
    #endif // WIDGET_H

    程序运行效果如下图所示:

    image

  • 相关阅读:
    10年后编程还有意义吗?
    专访Jeffrey Richter:Windows 8是微软的重中之重
    x86汇编指令脚本虚拟机
    基于容器的持续交付管道
    NET Core 整合Autofac和Castle
    数据结构与算法1
    Redis集群
    react + iscroll5
    MongoDB
    WebComponent
  • 原文地址:https://www.cnblogs.com/emouse/p/2988717.html
Copyright © 2011-2022 走看看