目录

添加外部库

添加头文件和命名空间

设计ui界面

1.打开本地图片

2.图像处理--腐蚀

封装函数

3.点击保存图片

定时器

4.打开摄像头

5.拍照

6.关闭摄像头

完整代码

可添加写入视频功能

图像处理--思维导图

​编辑视频操作--思维导图


有关OpenCV的配置可参考此篇

https://blog.csdn.net/qq_52218412/article/details/130730387

Windows系统下 在qt中 对OpenCV下载配置并简单使用


添加外部库

INCLUDEPATH += $$PWD/../../../user/apps/software/OpenCV4.5/opencv/build/includewin32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../user/apps/software/OpenCV4.5/opencv/build/x64/vc14/lib/ -lopencv_world455
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../user/apps/software/OpenCV4.5/opencv/build/x64/vc14/lib/ -lopencv_world455d

添加头文件和命名空间

#include <QWidget>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QDebug>
#include <QTimer>
#include <QDateTime>
#include <QFileDialog>using namespace cv;

设计ui界面


1.打开本地图片

打开本地文件夹选择图片、将图片放入label控件显示,以便后续操作(图像处理)

// 打开图片
void Widget::on_btn_open_clicked()
{// 打开文件 选择图片imagePath_ = QFileDialog::getOpenFileName(this,tr("选择图片"),"../../../user/picture/res",tr("Image files(*.jpg *.png *.webp);;All files(*.*)"));if(imagePath_.isEmpty()) {return;}// 读取图像 存储为cv::Mat类型对象  “QString *”转换为“const cv::String &”srcImage_ = imread(imagePath_.toStdString());//Mat转QImage 像素   oldlabel和newlabel放置图片// 将BGR颜色空间就转换为RGB空间cvtColor(srcImage_, srcImage_, COLOR_BGR2RGB);// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disImage = QImage(srcImage_.data, srcImage_.cols, srcImage_.rows,srcImage_.cols * srcImage_.channels(), QImage::Format_RGB888);// 对QImage对象进行缩放disImage = disImage.scaled(ui->old_label->width(), ui->old_label->height());// 在指定控件中放置图像ui->old_label->setPixmap(QPixmap::fromImage(disImage));ui->new_label->setPixmap(QPixmap::fromImage(disImage));
}

效果如下:

2.图像处理--腐蚀

// 腐蚀
void Widget::on_btn_corrosion_clicked()
{Mat corImage;Mat srcImage = srcImage_;// 生成矩形操作,结构元素大小5*5,MORPH_RECT指定为矩形Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 腐蚀操作  参数:输入Mat对象 输出Mat对象 腐蚀结构erode(srcImage, corImage, element);//Mat转QImage 像素   newlabel放置图像处理后图片// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disimage2 = QImage(corImage.data, corImage.cols, corImage.rows, corImage.cols*corImage.channels(), QImage::Format_RGB888);disimage2 = disimage2.scaled(ui->new_label->width(), ui->new_label->height());ui->new_label->setPixmap(QPixmap::fromImage(disimage2));
}

左边原图 右边处理后(图片可以来源本地、也可来源摄像头)


封装函数

每次打开新的图片和打开摄像头时都需要转化为RGB空间,并放入两个QLabel控件

每次处理图片也需要转化格式,放入修改后的控件

将这两步封装成以下两个函数

// 加载图片时
void Widget::setOriginalImage(Mat image)
{srcImage_ = image;// 将BGR颜色空间就转换为RGB空间cvtColor(srcImage_, srcImage_, COLOR_BGR2RGB);// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disImage = QImage(srcImage_.data, srcImage_.cols, srcImage_.rows,srcImage_.cols * srcImage_.channels(), QImage::Format_RGB888);// 对QImage对象进行缩放disImage = disImage.scaled(ui->old_label->width(), ui->old_label->height());// 在指定控件中放置图像ui->old_label->setPixmap(QPixmap::fromImage(disImage));ui->new_label->setPixmap(QPixmap::fromImage(disImage));
}// 图像处理时
void Widget::setChangedImage(Mat image)
{changedImage_ = image;//Mat转QImage 像素   newlabel放置图像处理后图片// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disimage2 = QImage(changedImage_.data, changedImage_.cols, changedImage_.rows, changedImage_.cols*changedImage_.channels(), QImage::Format_RGB888);disimage2 = disimage2.scaled(ui->new_label->width(), ui->new_label->height());ui->new_label->setPixmap(QPixmap::fromImage(disimage2));
}

3.点击保存图片

// 保存图片
void Widget::on_btn_save_clicked()
{QString saveImagePath = "../../../user/picture/opencv/";if(saveImagePath.isEmpty()) {return;}// 获取图片名称和后缀QString str = imagePath_.mid(20);QStringList imageName = str.split(".");// 保存修改后的图片到指定位置imwrite(QString("%1%2_save.%3").arg(saveImagePath).arg(imageName[0]).arg(imageName[1]).toStdString(), changedImage_);
}


定时器

摄像头取帧主要通过定时器QTimer来控制,在规定时间内反复取帧并放入界面QLabel

主要思想:在一定时间范围内不停捕捉视频帧,将视频帧Mat格式进行转化为QImage,呈现在屏幕上。

    构造函数中//超时就读取当前摄像头信息timer = new QTimer(this);connect(timer, SIGNAL(timeout()), this, SLOT(getFrame()));跳转槽生成的函数
// 从摄像头中抓取并返回每一帧
void Widget::getFrame(QPrivateSignal)
{// 视频帧保存到Mat,通过定时器刷新显示Mat frameImage;captrue_ >>frameImage;//Mat转QImage 像素   oldlabel和newlabel放置图片setOriginalImage(frameImage);
}

4.打开摄像头

// 打开摄像头
void Widget::on_btn_open_camera_clicked()
{// 打开摄像头 开始计时,超时则发出timeout()信号,200毫秒取一帧captrue_.open(0);timer->start(200);// 不可打开摄像 可关闭摄像 可拍照ui->btn_open_camera->setEnabled(false);ui->btn_close_camera->setEnabled(true);ui->btn_photograph->setEnabled(true);
}

5.拍照

// 拍照
void Widget::on_btn_photograph_clicked()
{// 视频帧保存到Mat,通过定时器刷新显示Mat frameImage;captrue_ >> frameImage;//Mat转QImage 像素   oldlabel和newlabel放置图片setOriginalImage(frameImage);// 将捕获的图片存储到本机指定位置QString saveImagePath = "../../../user/picture/photograph/";if(saveImagePath.isEmpty()) {return;}// 以当前时间给图片命名QDateTime dateTime;dateTime = QDateTime::currentDateTime();QString name = dateTime.toString("yyyyMMdd_hhmmss");// 保存修改后的图片到指定位置imwrite(QString("%1%2.png").arg(saveImagePath).arg(name).toStdString(), frameImage);
}

6.关闭摄像头

// 关闭摄像头
void Widget::on_btn_close_camera_clicked()
{// 关闭摄像头 停止取帧captrue_.release();timer->stop();// 可打开摄像 不可关闭摄像 不可拍照ui->btn_open_camera->setEnabled(true);ui->btn_close_camera->setEnabled(false);ui->btn_photograph->setEnabled(false);
}

效果如下,当关闭摄像头时,可以对最后的视频帧做图像处理。


完整代码

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QDebug>
#include <QTimer>
#include <QDateTime>
#include <QFileDialog>using namespace cv;QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private:void setChangedImage(Mat image);void setOriginalImage(Mat image);private slots:void getFrame(QPrivateSignal);void on_btn_snowflake_clicked();                // 雪花屏void on_btn_gaussian_clicked();                 // 高斯模糊void on_btn_median_filtering_clicked();         // 中值滤波void on_btn_grayscale_clicked();                // 灰度化void on_btn_xy_vague_clicked();                 // xy方向模糊void on_btn_bilateral_vague_clicked();          // 双边模糊void on_btn_corrosion_clicked();                // 腐蚀// 打开保存图片void on_btn_open_clicked();void on_btn_save_clicked();// 打开关闭摄像头,拍照void on_btn_open_camera_clicked();void on_btn_close_camera_clicked();void on_btn_photograph_clicked();private:Ui::Widget *ui;// 原图Mat srcImage_;// 修改后的图Mat changedImage_;//  图片路径QString imagePath_;QTimer *timer;VideoCapture captrue_;};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);setWindowTitle("opencv");// 不能关闭摄像头 不可拍照ui->btn_photograph->setEnabled(false);ui->btn_close_camera->setEnabled(false);//超时就读取当前摄像头信息timer = new QTimer(this);connect(timer, SIGNAL(timeout()), this, SLOT(getFrame()));
}Widget::~Widget()
{delete ui;
}void Widget::setChangedImage(Mat image)
{changedImage_ = image;//Mat转QImage 像素   newlabel放置图像处理后图片// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disimage2 = QImage(changedImage_.data, changedImage_.cols, changedImage_.rows, changedImage_.cols*changedImage_.channels(), QImage::Format_RGB888);disimage2 = disimage2.scaled(ui->new_label->width(), ui->new_label->height());ui->new_label->setPixmap(QPixmap::fromImage(disimage2));
}void Widget::setOriginalImage(Mat image)
{srcImage_ = image;// 将BGR颜色空间就转换为RGB空间cvtColor(srcImage_, srcImage_, COLOR_BGR2RGB);// 数据源为data指针,图像的宽度、高度、字节数、像素格式QImage disImage = QImage(srcImage_.data, srcImage_.cols, srcImage_.rows,srcImage_.cols * srcImage_.channels(), QImage::Format_RGB888);// 对QImage对象进行缩放disImage = disImage.scaled(ui->old_label->width(), ui->old_label->height());// 在指定控件中放置图像ui->old_label->setPixmap(QPixmap::fromImage(disImage));ui->new_label->setPixmap(QPixmap::fromImage(disImage));
}// 从摄像头中抓取并返回每一帧
void Widget::getFrame(QPrivateSignal)
{// 视频帧保存到Mat,通过定时器刷新显示Mat frameImage;captrue_ >>frameImage;//Mat转QImage 像素   oldlabel和newlabel放置图片setOriginalImage(frameImage);
}// 雪花屏
void Widget::on_btn_snowflake_clicked()
{Mat srcImage = srcImage_;//像素二维矩阵函数int rows = srcImage.rows;//像素二维矩阵列数int cols = srcImage.cols * srcImage.channels();for(int i=0;i<rows;i++){// 获取Mat对象的第i行像素的指针uchar * data = srcImage.ptr<uchar>(i);for(int j=0; j<cols; j++){//雪花屏特效int q = rand()%cols;data[q]=155;            //某些通道随机改成155}// 在Mat对象中采用二维矩阵的形式存储,而在QImage对象中则将所有像素数据序列化为一个一维数组,因此可以通过指针来访问和修改图像数据。}//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(srcImage);
}// 高斯模糊
void Widget::on_btn_gaussian_clicked()
{Mat gauImage;Mat srcImage = srcImage_;// 高斯模糊   参数:输入Mat对象 输出Mat对象 高斯核大小(矩阵) 计算标准差GaussianBlur(srcImage, gauImage, Size(5, 5), 0, 0);// 数据源为data指针,图像的宽度、高度、字节数、像素格式setChangedImage(gauImage);
}// 中值滤波
void Widget::on_btn_median_filtering_clicked()
{Mat medImage;Mat srcImage = srcImage_;//中值滤波  参数:输入Mat对象 输出Mat对象 卷积核大小(正方形边长)medianBlur(srcImage, medImage, 5);//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(medImage);}// 灰度化
void Widget::on_btn_grayscale_clicked()
{Mat graImage;Mat srcImage = srcImage_;// 彩色图像转化为灰度图像  灰度图像再转为彩色图像cvtColor(srcImage, graImage, COLOR_BGR2GRAY);cvtColor(graImage, graImage, COLOR_GRAY2BGR);//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(graImage);
}// xy方向模糊
void Widget::on_btn_xy_vague_clicked()
{Mat xyImage;Mat srcImage = srcImage_;// xy轴模糊 均值滤波  参数:输入Mat对象 输出Mat对象 均值滤波卷积核大小(矩阵)blur(srcImage, xyImage, Size(10, 10));//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(xyImage);
}// 双边模糊
void Widget::on_btn_bilateral_vague_clicked()
{Mat bilImage;Mat srcImage = srcImage_;// 双边模糊  参数:输入Mat对象 输出Mat对象 卷积核大小 灰度空间中的标准差值  坐标空间中标准差// 插值方式(为负,INTER_LINEAR;为零,INTER_NEAREST;为正,INTER_AREA、INTER_CUBIC)bilateralFilter(srcImage, bilImage, 15, 120, 10, 4);//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(bilImage);
}// 腐蚀
void Widget::on_btn_corrosion_clicked()
{Mat corImage;Mat srcImage = srcImage_;// 生成矩形操作,结构元素大小5*5,MORPH_RECT指定为矩形Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));// 腐蚀操作  参数:输入Mat对象 输出Mat对象 腐蚀结构erode(srcImage, corImage, element);//Mat转QImage 像素   newlabel放置图像处理后图片setChangedImage(corImage);
}// 打开图片
void Widget::on_btn_open_clicked()
{// 打开文件 选择图片imagePath_ = QFileDialog::getOpenFileName(this,tr("选择图片"),"../../../user/picture/res",tr("Image files(*.jpg *.png *.webp);;All files(*.*)"));if(imagePath_.isEmpty()) {return;}// 读取图像 存储为cv::Mat类型对象  “QString *”转换为“const cv::String &”srcImage_ = imread(imagePath_.toStdString());//Mat转QImage 像素   oldlabel和newlabel放置图片setOriginalImage(srcImage_);
}// 保存图片
void Widget::on_btn_save_clicked()
{QString saveImagePath = "../../../user/picture/opencv/";if(saveImagePath.isEmpty()) {return;}// 获取图片名称和后缀QString str = imagePath_.mid(20);QStringList imageName = str.split(".");// 保存修改后的图片到指定位置imwrite(QString("%1%2_save.%3").arg(saveImagePath).arg(imageName[0]).arg(imageName[1]).toStdString(), changedImage_);
}// 打开摄像头
void Widget::on_btn_open_camera_clicked()
{// 打开摄像头 开始计时,超时则发出timeout()信号,200毫秒取一帧captrue_.open(0);timer->start(200);// 不可打开摄像 可关闭摄像 可拍照ui->btn_open_camera->setEnabled(false);ui->btn_close_camera->setEnabled(true);ui->btn_photograph->setEnabled(true);
}// 关闭摄像头
void Widget::on_btn_close_camera_clicked()
{// 关闭摄像头 停止取帧captrue_.release();timer->stop();// 可打开摄像 不可关闭摄像 不可拍照ui->btn_open_camera->setEnabled(true);ui->btn_close_camera->setEnabled(false);ui->btn_photograph->setEnabled(false);
}// 拍照
void Widget::on_btn_photograph_clicked()
{// 视频帧保存到Mat,通过定时器刷新显示Mat frameImage;captrue_ >> frameImage;//Mat转QImage 像素   oldlabel和newlabel放置图片setOriginalImage(frameImage);// 将捕获的图片存储到本机指定位置QString saveImagePath = "../../../user/picture/photograph/";if(saveImagePath.isEmpty()) {return;}// 以当前时间给图片命名QDateTime dateTime;dateTime = QDateTime::currentDateTime();QString name = dateTime.toString("yyyyMMdd_hhmmss");// 保存修改后的图片到指定位置imwrite(QString("%1%2.png").arg(saveImagePath).arg(name).toStdString(), frameImage);
}

可添加写入视频功能

在打开摄像头时,将捕获到的视频帧存入容器(全局变量QList<Mat> lstFrame_);关闭摄像头时, 将容器中的视频帧通过VideoWrite对象写入视频文件avi。

具体操作为,定时器触发timeout信号时,调用getFrame槽函数(将视频帧保存到容器lstFrame_)。关闭摄影时,调用SaveVideo函数,并将容器清空clear(方便下次录制)。

// 在关闭摄像头这一瞬间 将之前的视频帧写入视频文件avi
void Widget::SaveVideo()
{// 创建VideoWriter对象VideoWriter writer;double fps = 25;Size frameSize(640, 480);// 存储到本机指定位置QString savePath = "../../mp34/video/";QDateTime dateTime = QDateTime::currentDateTime();QString name = dateTime.toString("yyyyMMdd_hhmmss");QString fileName = QString("%1%2.avi").arg(savePath).arg(name);// open()打开视频文件   文件名 编解码类型 帧率 帧大小 彩色truewriter.open(fileName.toStdString(), VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, frameSize, true);if(!writer.isOpened()) {return;}// 将视频帧写入文件write()for(int i=0; i<lstFrame_.length(); i++) {if(lstFrame_[i].empty()) {continue;}// 将BGR颜色空间就转换为RGB空间cvtColor(lstFrame_[i], lstFrame_[i], COLOR_BGR2RGB);writer.write(lstFrame_[i]);}// 写入完成 关闭视频文件writer.release();}// 从摄像头中抓取并返回每一帧
void Widget::getFrame(QPrivateSignal)
{// 视频帧保存到Mat,通过定时器刷新显示Mat frameImage;captrue_ >> frameImage;//Mat转QImage 像素   oldlabel和newlabel放置图片SetOriginalImage(frameImage);// 视频帧保存到临时容器lstFrame_.append(frameImage);
}// 关闭摄像头
void Widget::on_btn_close_camera_clicked()
{// 关闭摄像头 停止取帧captrue_.release();timer->stop();// 关闭摄像头时 写入视频文件 并存储所有视频帧的容器清空SaveVideo();lstFrame_.clear();// 可打开摄像 不可关闭摄像 不可拍照ui->btn_open_camera->setEnabled(true);ui->btn_close_camera->setEnabled(false);ui->btn_photograph->setEnabled(false);
}

图像处理--思维导图


视频操作--思维导图

03_Windows10+OpenCV4.5.5打开本地图片进行图片处理 实时摄影并抓拍图片存入本机相关推荐

  1. Python tkinter 打开本地图片进行矩形框标注

    经常会遇到json报文中有图片URL,以及ROI的坐标x.y.w.h,然后需要验证下这个框在图片的什么位置,一般时候只能根据坐标值定性目测下.最近用tkinter写了个打开本地图片并且将rect的坐标 ...

  2. iOS-打开照相机打开本地相册图片上传

    ResourceFrom:http://www.xuanyusong.com/archives/1493 Hello 大家好 IOS的文章好久都木有更新了,今天更新一篇哈. 这篇文章主要学习如何在IO ...

  3. python下载大文件mp4_Python代码打开本地.mp4格式文件的方法

    Python代码打开本地.mp4格式文件的方法 想通过编写Python代码来打开本地的.mp4格式文件,使用os模块来操作文件.我的电脑默认的是QQ影音播放器,执行Python代码打开默认播放器,播放 ...

  4. 服务器怎么打开本地电脑文件夹,如何在云服务器上打开本地文件夹

    如何在云服务器上打开本地文件夹 内容精选 换一换 Tomcat是一个被广泛使用的Java Web应用服务器.本文介绍了在华为云弹性云服务器上部署Java Web环境的操作步骤.首先需要下载部署Java ...

  5. 服务器读取本地文件,如何在云服务器上打开本地文件

    如何在云服务器上打开本地文件 内容精选 换一换 边缘节点上报应用日志和系统日志需要打开日志开关,且边缘节点的NTP与华为云一致.如果看不到日志,可能有如下原因:日志开关未打开.登录IEF控制台,在左侧 ...

  6. 【护眼阅读】PC端通过主流常用浏览器打开本地WEB页面阅读本地TXT小说

    自用-通过WEB页面阅读本地小说,生成章节导航,设置字色和背景色达到护眼目的,HTML+CSS+JS 章节导航 需求分析 HTML代码 CSS代码 JS代码 总结 章节导航 从分析需求入手,查找资料, ...

  7. vue-pc打开本地摄像头并对画面进行截图

    在vuePc端打开本地摄像头. 实现效果,在pc端项目中打开本地摄像头,然后对此画面进行截屏,并以文件的格式上传到服务器. 1.打开本地摄像头 /** 获取方法1 */ getVideo(){let ...

  8. 小程序一次性上传多个本地图片,上拉加载照片以及图片加载延迟解决之道

    一:小程序之一次性上传多个本地相片 最近由于项目需要所以学了下小程序,也做了一些东西,随后便有了以下的一些总结了,现在说说如何使用小程序一次性上传多个本地相片. 问题描述 最近做项目的时候要实现一个上 ...

  9. android本地xml文件怎么打开,android 打开本地文件

    首先要知道的是,Android 打开本地文件是根据类型打开的,也就是根据文件的 MIME 类型来确定 如果不知道是什么类型,那就是 : */* 类型匹配表: private static final ...

最新文章

  1. MATLAB生成正态样本以及正态矩阵、从文件读入矩阵
  2. 为啥八位的计算机可以用补码表示-128
  3. C语言怎样编程分子变化,C语言经典编程(一)
  4. ThinkPHP5.0.5RCE
  5. 大屏设计的视觉统一_视觉设计中的统一
  6. python 点击按钮采集图片_python多线程采集图片
  7. incc与oracle连接_Oracle 连接和会话的区别
  8. tf.contrib在tf2中无法使用
  9. Ajax实例一:利用服务器计算
  10. 对自定义SharePoint WebService的总结
  11. 核心JavaScript——词法结构
  12. JAD文件各属性解释
  13. 仓库货位 mysql_Max(TM)财务进销存管理系统
  14. 人体神经系统分类图解,人体神经系统分类图片
  15. 介绍中国传统节日的网页html,中国传统节日介绍:中秋节
  16. 广发多空杠杆浮动杠杆率计算
  17. curry化 js_JavaScript实现柯里化(curry)函数的思路和源码
  18. sqlitestudio和mysql_sqlitestudio怎么用 sqlitestudio使用方法图文详解
  19. 二阶常系数齐次线性微分方程的通解
  20. 在视频中添加图片,图片中添加视频,制作画中画效果

热门文章

  1. USB超高速3.0/3.2 USB3.0信号定义
  2. SQLSERVER储存过程批量添加10万条数据
  3. 关于爱情 懂得珍惜就好!
  4. win10永久关闭病毒防护
  5. 如何在matlab中建立水箱模型_在MATLAB中实现水箱液位控制系统的设计
  6. 软件开发项目成本控制的4大策略
  7. Action、RenderAction、Partial、RenderPartial区别
  8. java border类_Swing BorderLayout类
  9. 淘宝Tanx_bidding.proto
  10. 基于python实现利用DEM数据计算坡度、坡向