项目实战:Qt+OpenCV图像处理与识别算法平台

摘要:
该原理基于Qt的OpenCV开发。以Qt为接口,OpenCV执行图像处理。

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107090002
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)

Qt开发专栏:项目实战(点击传送门)
OpenCV开发专栏(点击传送门)
 
需求

  做算法过程中,需要一个平台来实时查看效果,记录处理过程,可以一键查看效果;
  OpenCV的各种算法在Qt效果调试;
  持续升级版本,敬请期待…

 
原理

  基于Qt的OpenCV开发,依托Qt作为界面,OpenCV进行图像处理。

 
涉及技术博文

  《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)
  《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储
  《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整
  《OpenCV开发笔记(十四):算法基础之线性滤波-方框滤波
  《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波
  《OpenCV开发笔记(十六):算法基础之线性滤波-高斯滤波
  《OpenCV开发笔记(十八):算法基础之非线性滤波-中值滤波
  《OpenCV开发笔记(十九):算法基础之非线性滤波-双边滤波
  《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀
  《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀

 
Demo:Qt+OpenCV算法平台 v1.4.0

下载地址

  CSDN:https://download.csdn.net/download/qq21497936/12570673
  QQ群:1047134658(点击“文件”搜索“qtOpenCVTools”,群内与博文同步更新)

腐蚀

  在这里插入图片描述

膨胀

  在这里插入图片描述

双边滤波

  在这里插入图片描述

中值滤波

  在这里插入图片描述

高斯滤波

  在这里插入图片描述

均值滤波

  在这里插入图片描述

方框滤波

  在这里插入图片描述

对比度与亮度

  在这里插入图片描述

图片打开与保存

  在这里插入图片描述

 
核心代码

common.h

#ifndef COMMON_H
#define COMMON_H

#include <QImage>
#include <QDebug>
#include <QFileDialog>
#include <QColorDialog>
#include <QMessageBox>
#include <QHash>
// opencv
#include "opencv/highgui.h"
#include "opencv/cxcore.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/xphoto.hpp"
// opencv_contrib
#include <opencv2/xphoto.hpp>
#include <opencv2/ximgproc.hpp>
#include <opencv2/calib3d.hpp>

cv::Mat image2Mat(QImage image);    // Qimage 转 cv::Mat
QImage mat2Image(cv::Mat mat);      // cv::Mat 转 QImage

#endif // COMMON_H

common.cpp

#include "common.h"

cv::Mat image2Mat(QImage image)
{
    cv::Mat mat;
    switch(image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGRA2BGR);
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}

QImage mat2Image(cv::Mat mat)
{
    if(mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)
        image.setColorCount(256);
        for(int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row ++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    else if(mat.type() == CV_8UC3)
    {
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if(mat.type() == CV_8UC4)
    {
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        return QImage();
    }
}

DemoContrastAndBrightnessWidget.h

#ifndef DEMOCONTRASTANDBRIGHTNESSWIDGET_H
#define DEMOCONTRASTANDBRIGHTNESSWIDGET_H

#include <QWidget>
#include "common.h"

namespace Ui {
class DemoContrastAndBrightnessWidget;
}

class DemoContrastAndBrightnessWidget : public QWidget
{
    Q_OBJECT

public:
    explicit DemoContrastAndBrightnessWidget(QWidget *parent = 0);
    ~DemoContrastAndBrightnessWidget();

public:
    void setFilePath(QString filePath);

protected:
    void updateInfo();
    void updateImage();

private slots:
    void on_pushButton_openFile_clicked();
    void on_horizontalSlider_beta_sliderMoved(int position);
    void on_horizontalSlider_alpha_sliderMoved(int position);
    void on_pushButton_broswer_clicked();
    void on_spinBox_beta_valueChanged(int arg1);
    void on_doubleSpinBox_alpha_valueChanged(double arg1);
    void on_pushButton_showFile_clicked();
    void on_pushButton_backgroundColor_clicked();

private:
    Ui::DemoContrastAndBrightnessWidget *ui;

private:
    QString _filePath;

    cv::Mat _srcMat;
    QImage _srcImage;
    cv::Mat _dstMat;
    QImage _dstImage;
};
#endif // DEMOCONTRASTANDBRIGHTNESSWIDGET_H

DemoContrastAndBrightnessWidget.cpp

#include "DemoContrastAndBrightnessWidget.h"
#include "ui_DemoContrastAndBrightnessWidget.h"

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

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

void DemoContrastAndBrightnessWidget::setFilePath(QString filePath)
{
    _filePath = filePath;
    ui->lineEdit_filePath->setText(_filePath);
}

void DemoContrastAndBrightnessWidget::updateInfo()
{
    if(_srcMat.data == 0)
    {
        return;
    }
    // mat行列与图片高度是对角线反向的
    ui->label_size->setText(QString("%1 x %2").arg(_srcMat.rows).arg(_srcMat.cols));
    ui->label_channels->setText(QString("%1").arg(_srcMat.channels()));
    ui->label_depth->setText(QString("%1").arg(_srcMat.depth()));
    ui->label_type->setText(QString("%1").arg(_srcMat.type()));
}

void DemoContrastAndBrightnessWidget::updateImage()
{
    if(_srcImage.isNull())
    {
        return;
    }

    cv::Mat srcMat = image2Mat(_srcImage);

    // 增强对比度
    float r;
    float g;
    float b;
    _dstMat = cv::Mat::zeros(srcMat.size(), srcMat.type());
    int alpha = ui->horizontalSlider_alpha->value();    // 小于1,则降低对比度
    int beta = ui->horizontalSlider_beta->value();     // 负数,则降低亮度
    for(int row = 0; row < srcMat.rows; row++)
    {
        for(int col = 0; col < srcMat.cols; col++)
        {
            b = srcMat.at<cv::Vec3b>(row, col)[0];
            g = srcMat.at<cv::Vec3b>(row, col)[1];
            r = srcMat.at<cv::Vec3b>(row, col)[2];
            // 对比度、亮度计算公式 cv::saturate_cast<uchar>(value):防止溢出
            _dstMat.at<cv::Vec3b>(row, col)[0] = cv::saturate_cast<uchar>(b * alpha / 100.0f + beta);
            _dstMat.at<cv::Vec3b>(row, col)[1] = cv::saturate_cast<uchar>(g * alpha / 100.0f + beta);
            _dstMat.at<cv::Vec3b>(row, col)[2] = cv::saturate_cast<uchar>(r * alpha / 100.0f + beta);
        }
    }
    _dstImage = mat2Image(_dstMat);
    ui->widget_image->setImage(_dstImage);
}

void DemoContrastAndBrightnessWidget::on_pushButton_openFile_clicked()
{
    if(!_srcImage.load(_filePath))
    {
        qDebug() << __FILE__ << __LINE__ << "Failed to load image:" << _filePath;
        return;
    }
    qDebug() << __FILE__<< __LINE__ << (int)_srcImage.format();
    _srcMat = image2Mat(_srcImage);
    updateInfo();
    updateImage();
}

void DemoContrastAndBrightnessWidget::on_horizontalSlider_beta_sliderMoved(int position)
{
    ui->spinBox_beta->setValue(position);
    updateImage();
}

void DemoContrastAndBrightnessWidget::on_horizontalSlider_alpha_sliderMoved(int position)
{
    ui->doubleSpinBox_alpha->setValue(position / 100.0f);
    updateImage();
}

void DemoContrastAndBrightnessWidget::on_pushButton_broswer_clicked()
{
    QString dir = ui->lineEdit_filePath->text();
    dir = dir.mid(0, dir.lastIndexOf("/"));
    QString filePath = QFileDialog::getOpenFileName(0, "打开图片", dir, "PNG;JPEG;BMP(*.png;*.jpg;*.bmp);;JPEG(*.jpg);;PNG(*.png);;BMP(*.bmp)");
    if(filePath.isEmpty())
    {
        return;
    }
    _filePath = filePath;
    ui->lineEdit_filePath->setText(_filePath);

}

void DemoContrastAndBrightnessWidget::on_spinBox_beta_valueChanged(int arg1)
{
    ui->horizontalSlider_beta->setValue(arg1);
    updateImage();
}

void DemoContrastAndBrightnessWidget::on_doubleSpinBox_alpha_valueChanged(double arg1)
{
    ui->horizontalSlider_alpha->setValue(arg1 * 100);
    updateImage();
}

void DemoContrastAndBrightnessWidget::on_pushButton_showFile_clicked()
{
    if(_dstMat.data == 0)
    {
        QMessageBox::information(this, "提示", "使用opencv显示图片失败");
        return;
    }
    cv::imshow("showFile", _dstMat);
}

void DemoContrastAndBrightnessWidget::on_pushButton_backgroundColor_clicked()
{
    QColor backgroundColor = ui->widget_image->getBackgroundColor();
    backgroundColor = QColorDialog::getColor(backgroundColor, this, "底色");
    if(!backgroundColor.isValid())
    {
       return;
    }
    QColor color(backgroundColor.red(), backgroundColor.green(), backgroundColor.blue());
    ui->widget_image->setBackgroundColor(color);
}
 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/107090002

免责声明:文章转载自《项目实战:Qt+OpenCV图像处理与识别算法平台》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇@RestController的用法闲话 笔记本显卡性能排行下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

OpenCV中出现“Microsoft C++ 异常: cv::Exception,位于内存位置 0x0000005C8ECFFA80 处。”的异常

对于OpenCV的安装 要感谢网友空晴拜小白提供的教程 链接如下: https://blog.csdn.net/sinat_36264666/article/details/73135823?ref=myread#reply 教程写的十分详细 截图什么的也很好 2 问题描述今天在安装和测试OpenCV的时候遇到了这样的问题 测试代码如下 #include...

捕获海康威视IPCamera图像,转成OpenCV能够处理的图像(二)

海康威视IPCamera图像捕获 捕获海康威视IPCamera图像。转成OpenCV能够处理的IplImage图像(一) 捕获海康威视IPCamera图像。转成OpenCV能够处理的IplImage图像(二) 所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P) 海康威视IPCamera图像捕获方法有两种: (1)利用SDK...

GLCM opencv

头文件: #pragma once #include "cvaux.h" #define CV_MAX_NUM_GREY_LEVELS_8U 256 class cl_Texture { public: //定义GLCM变量 struct GLCM { int matrixSideLength; int numMatrices; doub...

车牌识别(end-to-end-for-chinese-plate-recognition)项目搭建基于Mxnet(Python 3.5)

最近看到geihub上有个车牌识别的项目,感觉很有意思,从上面fork了一下弄到本地自己跑了下。在安装过程中遇到了一些问题,记录如下。 项目github连接:https://github.com/szad670401/end-to-end-for-chinese-plate-recognition ,本机环境Win8 64bit 该项目是基于Python做...

图形学实验用的VS2017本地环境配置,VS 2017配置opencv、Eigen

最近在进行图形学相关实验时,会用到VS 2017,虚拟机里的VScode卡得小宇宙爆发,索性就在本地进行配置吧。这个过程主要需要配置 opencv 和 Eigen 线代库。下面是配置教程: 一、VS2017 配置OpenCV 这是我看到的最详细的配置教程:VS2017配置opencv教程(超详细!!!) 配置问题 在配置好后,测试运行时,我的报错“由于找不...

OpenCV 2.4.9 学习笔记(4)—— 像素类型与Templates的限制使用

限制使用templates   C++中的Templates使得接口机制非常好用,高效而且能够保证数据与算法的安全。但是过多地使用templates可能会增加计算时间和代码长度,有时候还能难区分接口和实现。在OpenCV中过多使用templates并不是一件好事,OpenCV的refman中提到OpenCV中很多的算法代码文件动不动就几千行,而且OpenC...