项目实战:Qt+OpenCV图像处理与识别算法平台(持续更新,当前v1.7.0)

若该文为原创文章,未经允许不得转载
原博主博客地址: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进行图像处理。


版本说明

  在这里插入图片描述


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

下载地址

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

版本信息

  • v1.7.0 更改子窗口的类型设计模式,加载退出之前所在的Demo例程页面,兼容单通道图像,增加霍夫线变换、开运算、闭运算、形态学梯度、顶帽(礼帽)、黑帽、漫水填充(点击图片选点填充)

演示

  在这里插入图片描述
  在这里插入图片描述


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

下载地址

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

版本信息

  • v1.5.0 增加对算法的结果进行输出、展示和保存,增加阈值化、自适应阈值化
  • v1.6.0 更改子窗口的设计模式,增加OTSU阈值化、双阈值化(中间区域、非中间区域)、半阈值化

演示

  在这里插入图片描述
  在这里插入图片描述


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

下载地址

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

版本信息

  • v1.0.0 基础框架
  • v1.1.0 增加openCV图片读取与保存
  • v1.2.0 增加对比度与亮度、方框滤波、均值滤波和高斯滤波
  • v1.3.0 增加对bmp图片的支持,增加中值滤

腐蚀

  在这里插入图片描述

膨胀

  在这里插入图片描述

双边滤波

  在这里插入图片描述

中值滤波

  在这里插入图片描述

高斯滤波

  在这里插入图片描述

均值滤波

  在这里插入图片描述

方框滤波

  在这里插入图片描述

对比度与亮度

  在这里插入图片描述

图片打开与保存

  在这里插入图片描述


涉及技术博文

  《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)
  《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储
  《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整
  《OpenCV开发笔记(十四):算法基础之线性滤波-方框滤波
  《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波
  《OpenCV开发笔记(十六):算法基础之线性滤波-高斯滤波
  《OpenCV开发笔记(十八):算法基础之非线性滤波-中值滤波
  《OpenCV开发笔记(十九):算法基础之非线性滤波-双边滤波
  《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀
  《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀
  《OpenCV开发笔记(二十八):带你学习图像识别之阈值化
  《OpenCV开发笔记(二十九):带你学习图像识别之自适应阈值
  《OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化
  《OpenCV开发笔记(三十一):红胖子8分钟带你深入了解双阈值化(图文并貌+浅显易懂+程序源码)
  《OpenCV开发笔记(三十二):红胖子8分钟带你深入了解半阈值化(图文并貌+浅显易懂+程序源码)


核心代码

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

  • 35
    点赞
  • 267
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论
### 回答1: QT是一种跨平台的开发框架,可以用来开发各种应用程序。OpenCV是一个开源的计算机视觉库,可以用来处理图像和视频等图像处理任务。OCR(Optical Character Recognition)库是一种能够读取图像中文字并将其转换为可编辑文本的技术。 在使用QTOpenCV来开发一个汉字识别的图像演示程序时,我们可以按照以下步骤进行: 1. 首先,需要创建一个QT项目,并添加OpenCV的库文件和头文件,以便在项目中使用OpenCV功能。 2. 然后,需要加载待识别的图像文件。可以使用QT图像处理功能加载图像文件,并在QT的图形界面中显示出来。 3. 接下来,我们可以使用OpenCV图像处理功能对加载的图像进行预处理,以提高识别准确度。例如,可以使用图像平滑、二值化等技术来消除噪声和增强图像的对比度。 4. 然后,我们可以使用OCR库来识别图像中的汉字。OCR库可以通过训练和学习,识别不同的汉字字符。可以使用OCR库提供的API来调用该功能,并将识别结果返回给应用程序。 5. 最后,我们可以将识别的汉字结果显示在QT的图形界面中,以便用户查看和编辑。可以使用QT的文本框组件来显示识别出的文字,并提供其他相关的编辑功能。 通过以上步骤,我们可以完成一个简单的QTOpenCV结合的汉字识别图像演示程序。用户可以通过该程序加载图像文件,并对图像中的汉字进行识别和编辑。这个演示程序可以为用户展示汉字识别的基本原理和功能,并为用户提供一个直观的界面来操作和体验。 ### 回答2: Qt是一种跨平台的C++应用程序开发框架,OpenCV是一个用于图像处理和计算机视觉的开源库,OCR(Optical Character Recognition)是光学字符识别的缩写,用于将印刷体文字转化为可编辑的电子文字。 要实现在Qt中使用OpenCV进行OCR汉字识别,可以按照以下步骤进行: 1. 准备样本数据集:收集一些包含汉字的图像样本,包括不同字体、大小和倾斜度的样本,用于训练和测试OCR模型。 2. 安装OpenCVQt:下载并安装OpenCVQt开发环境,确保能够在Qt中调用OpenCV库。 3. 加载样本数据集:使用OpenCV读取样本数据集中的图像文件,并将其转换为适合进行OCR处理的数据格式。 4. 预处理图像:对加载的图像进行预处理,例如灰度化、二值化、降噪等操作,以提高OCR的识别准确性。 5. 训练OCR模型:使用OpenCV的机器学习算法,如支持向量机(SVM)或卷积神经网络(CNN),对预处理后的图像进行训练,以建立用于识别汉字的模型。 6. 图像识别:使用训练好的OCR模型对待识别的图像进行处理,提取其中的汉字信息,并将其转化为可编辑的电子文字。 7. 在Qt界面中展示结果:将识别到的汉字结果显示在Qt的界面中,以供用户查看和编辑。 通过以上步骤,我们可以在Qt中使用OpenCV库进行OCR汉字识别的演示。用户可以加载图像,点击识别按钮后,程序将自动进行图像处理和汉字识别,并将结果显示在界面上。这样,用户可以方便地通过这个演示程序了解OCR汉字识别的基本原理和实现方式。 ### 回答3: QT是一种流行的跨平台应用程序开发框架,而OpenCV是一个广泛使用的计算机视觉库。OCR(Optical Character Recognition)库可以用于识别图像中的文字。下面是一个300字的中文回答,旨在介绍如何在QT中使用OpenCV和OCR库来实现汉字识别的演示程序。 首先,我们需要在QT项目中集成OpenCV库。可以通过在项目文件中添加OpenCV相关的库路径和头文件路径来实现。然后,在QT项目中创建一个窗口,将图像显示在窗口上。 接下来,我们需要加载要识别的图像。使用OpenCV的函数,我们可以读取图像文件,并将其转换为OpenCV的Mat对象。然后,我们可以将Mat对象转换为QT图像对象,以便在QT窗口中显示。 在加载图像后,我们可以使用OCR库来识别其中的汉字。OCR库可以读取OpenCV的Mat对象,然后将其转换为文本。 为了在QT中使用OCR库,可能需要对其进行一些设置和配置。这包括选择合适的OCR引擎,以及设置字库和语言。这些设置可能因库的不同而有所不同,可参考OCR库的文档以获取详细的配置信息。 一旦配置完毕,我们可以调用OCR库的识别函数,将图像传递给它。OCR库将扫描图像,并将识别结果返回为文本。我们可以在QT窗口中显示这些识别结果。 最后,我们可以通过增加一些用户交互功能来改进演示程序。例如,我们可以添加一个按钮,使用户能够选择不同的图像进行识别。我们还可以让用户可以调整OCR库的一些参数,以改进识别的准确性。 总之,通过集成OpenCV和OCR库,我们可以在QT中开发一个简单的汉字识别演示程序。这个演示程序可以加载图像,调用OCR库来识别汉字,并在QT窗口中显示识别结果。同时,我们可以通过增加一些用户交互功能来提高演示程序的实用性和可定制性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙红胖子Qt(长沙创微智科)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值