需求

  做算法过程中,需要一个平台来实时查看效果,记录处理过程,可以一键查看效果;
  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);
}
 

项目实战:Qt+OpenCV图像处理与识别算法平台的更多相关文章

  1. 基于Qt的图像处理技术和算法

    https://blog.csdn.net/silangquan/article/details/41008183

  2. 【项目实战】CNN手写识别复杂模型的构造

    感谢视频教程:https://www.bilibili.com/video/BV1Y7411d7Ys?p=11 这里开一篇新博客不仅仅是因为教程视频单独出了1p,也是因为这是一种代码编写的套路,特在此 ...

  3. 【项目实战】CNN手写识别

    由于只需要修改之前基于ANN模型代码的模型设计部分所以篇幅较短,简单的加点注释给自己查看即可 视频链接:https://www.bilibili.com/video/BV1Y7411d7Ys?p=10 ...

  4. 项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)

    前言   本项目的出现理由只是笔者的一个念头,于是利用专业Qt和Opencv相关的知识开发一个辅助工具,本文章仅用于Qt和Opencv结合的学习.   Demo演示效果          运行包下载地 ...

  5. 项目实战:Qt+Ffmpeg+OpenCV相机程序(打开摄像头、支持多种摄像头、分辨率调整、翻转、旋转、亮度调整、拍照、录像、回放图片、回放录像)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  6. (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

  7. (3两个例子)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

  8. 转:基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】

    文章来自于:http://blog.renren.com/share/246648717/8171467499 基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴 ...

  9. (6综合实验)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

  10. (4程序框架)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

随机推荐

  1. [转帖]解析Linux gcore: 揭示程序内存捕获的秘密(linuxgcore)

    https://www.dbs724.com/133618.html Linux gcore 是一种在Linux系统中使用命令行工具捕获进程内存内容的方法.它允许程序员制定程序的一个内存快照,从而帮助 ...

  2. [转帖]一次fork引发的惨案!

    https://www.cnblogs.com/xuanyuan/p/15502289.html "你还有什么要说的吗?没有的话我就要动手了",kill程序最后问道. 这一次,我没 ...

  3. [转帖]一个故事看懂CPU的TLB

    https://www.cnblogs.com/xuanyuan/p/15347054.html Hi,我是CPU一号车间的阿Q,还记得我吗,真是好久不见了- 我所在的CPU是一个八核CPU,就有八个 ...

  4. 使用rpm打包nacos然后部署为systemd服务开机自动启动的方法

    背景 Nacos是阿里开源的服务注册组件,能够简单的实现微服务的注册与发现机制. 但是官方并没有提供 sytemd的服务脚本, 也没有提供rpm包的方式. 公司里面使用 nacos的场景越来越多, 部 ...

  5. 2022 倒带 - NutUI

    作者:京东零售 于明明 前言 时光飞逝,流年似水,让我们倒带 2022,回首这跌宕起伏一年走过的 "升级之路". NutUI 表现如何? 成绩单等着您打分! 2022 是 NutU ...

  6. vue中使用Object.assign导致视图不响应

    可以正常响应的 <template> <div> <ul> <li class="li-item" v-for="(item,i ...

  7. 开源OpenIM:高性能、可伸缩、易扩展的即时通讯架构

    网上有很多关于IM的教程和技术博文,有亿级用户的IM架构,有各种浅谈原创自研IM架构,也有微信技术团队分享的技术文章,有些开发者想根据这些资料自研IM.理想很丰满,现实很骨感,最后做出来的产品很难达到 ...

  8. 从零开始的知识图谱生活,构建一个百科知识图谱,完成基于Deepdive的知识抽取、基于ES的简单语义搜索、基于 REfO 的简单KBQA

    从零开始的知识图谱生活,构建一个百科知识图谱,完成基于Deepdive的知识抽取.基于ES的简单语义搜索.基于 REfO 的简单KBQA 个人入门知识图谱过程中的学习笔记,算是半教程类的,指引初学者对 ...

  9. 19.4 Boost Asio 远程命令执行

    命令执行机制的实现与原生套接字通信一致,仅仅只是在调用时采用了Boost通用接口,在服务端中我们通过封装实现一个run_command函数,该函数用于发送一个字符串命令,并循环等待接收客户端返回的字符 ...

  10. 8.10 TLS线程局部存储反调试

    TLS(Thread Local Storage)用来在进程内部每个线程中存储私有的数据.每个线程都会拥有独立的TLS存储空间,可以在TLS存储空间中保存线程的上下文信息.变量.函数指针等.TLS其目 ...