ubuntu中QT+opencv在QLable上显示摄像头
ubuntu中QT+opencv在QLable上显示摄像头
饭前的一篇文章吧,写完吃饭走
图像在机器视觉中的重要性是不可忽视的。机器视觉是指计算机利用图像处理技术进行图像识别、分析和理解的科学与技术领域。图像是机器视觉的输入数据,通过分析和处理图像,计算机可以实现对图像中物体、场景等信息的提取和理解。
以下是图像在机器视觉中的重要性的几个方面:
1. 物体识别和分类:图像可以提供丰富的视觉信息,包括物体的形状、颜色、纹理等特征。通过对图像进行分析和处理,机器可以识别和分类不同的物体,实现自动化的物体检测和识别。
2. 场景分析和理解:通过对图像进行分析,可以理解图像所代表的场景。例如,机器可以通过图像识别出室内、室外、城市、乡村等不同的场景,从而为场景的分析和理解提供基础。
3. 图像检索和搜索:通过对图像进行特征提取和相似度计算,机器可以实现对图像的检索和搜索。例如,在图像数据库中搜索与输入图像相似的图像,或者通过输入图像进行目标物体的搜索和定位。
4. 视觉导航和定位:图像可以提供导航和定位所需的视觉信息。通过对图像进行分析,机器可以识别出环境中的特征点或标志物,从而实现室内、室外等不同环境下的定位和导航。
综上所述,图像在机器视觉中具有重要的作用,是实现机器视觉的关键输入数据。通过对图像进行分析和理解,机器可以实现对物体、场景等信息的自动化识别、分类和理解,从而实现各种应用,如智能监控、智能驾驶等。
那么这一切的开始呢,就是使用opencv来实现摄像头的采集
废话不多,我们直接上代码
UI文件的编写
一个开始一个结束,还有一个摄像头参数的显示,但是写出来有BUG(对程序运行没影响)所以就不实现了,都是原名,没有修改对象名
代码编写
.pro文件
我们 要导入我们的opencv的库
INCLUDEPATH += /usr/local/include/usr/local/include/opencv/usr/local/include/opencv2LIBS += /usr/local/lib/libopencv_*
.h文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <QTimer>
#include<QComboBox>
using namespace cv;
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);//QImage MatImageToQt(const Mat &src);~Widget();private slots:void readFarme();void on_pushButton_clicked();void on_pushButton_2_clicked();private:Ui::Widget *ui;VideoCapture cap;Mat src_image;QTimer *timer;QImage *image;};
#endif // WIDGET_H
.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <opencv2/core.hpp>
#include<opencv2/opencv.hpp>
#include <QPixmap>
#include <QTimer>
using namespace cv;
using namespace std;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// Mat mypicture = imread("/home/yyy/图片/aa.jpg");// imshow("open",mypicture);// Mat Medianfiltering;// cv::medianBlur(mypicture,Medianfiltering,7);// imshow("new open",Medianfiltering);timer = new QTimer(this);image = new QImage();connect(timer,SIGNAL(timeout()),this,SLOT(readFarme()));}Widget::~Widget()
{delete ui;
}void Widget::readFarme()
{cap.read(src_image);QImage imag = MatImageToQt(src_image);ui->label->setPixmap(QPixmap::fromImage(imag));
}void Widget::on_pushButton_clicked()
{cap.open(0);timer->start(33);
}void Widget::on_pushButton_2_clicked()
{timer->stop();cap.release();ui->label->clear();
}//Mat转成QImage
QImage Widget::MatImageToQt(const Mat &src)
{//CV_8UC1 8位无符号的单通道---灰度图片if(src.type() == CV_8UC1){//使用给定的大小和格式构造图像//QImage(int width, int height, Format format)QImage qImage(src.cols,src.rows,QImage::Format_Indexed8);//扩展颜色表的颜色数目qImage.setColorCount(256);//在给定的索引设置颜色for(int i = 0; i < 256; i ++){//得到一个黑白图qImage.setColor(i,qRgb(i,i,i));}//复制输入图像,data数据段的首地址uchar *pSrc = src.data;//for(int row = 0; row < src.rows; row ++){//遍历像素指针uchar *pDest = qImage.scanLine(row);//从源src所指的内存地址的起始位置开始拷贝n个//字节到目标dest所指的内存地址的起始位置中memcmp(pDest,pSrc,src.cols);//图像层像素地址pSrc += src.step;}return qImage;}//为3通道的彩色图片else if(src.type() == CV_8UC3){//得到图像的的首地址const uchar *pSrc = (const uchar*)src.data;//以src构造图片QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);//在不改变实际图像数据的条件下,交换红蓝通道return qImage.rgbSwapped();}//四通道图片,带Alpha通道的RGB彩色图像else if(src.type() == CV_8UC4){const uchar *pSrc = (const uchar*)src.data;QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);//返回图像的子区域作为一个新图像return qImage.copy();}else{return QImage();}
}
重要代码块讲解
//Mat转成QImage
QImage Widget::MatImageToQt(const Mat &src)
{//CV_8UC1 8位无符号的单通道---灰度图片if(src.type() == CV_8UC1){//使用给定的大小和格式构造图像//QImage(int width, int height, Format format)QImage qImage(src.cols,src.rows,QImage::Format_Indexed8);//扩展颜色表的颜色数目qImage.setColorCount(256);//在给定的索引设置颜色for(int i = 0; i < 256; i ++){//得到一个黑白图qImage.setColor(i,qRgb(i,i,i));}//复制输入图像,data数据段的首地址uchar *pSrc = src.data;//for(int row = 0; row < src.rows; row ++){//遍历像素指针uchar *pDest = qImage.scanLine(row);//从源src所指的内存地址的起始位置开始拷贝n个//字节到目标dest所指的内存地址的起始位置中memcmp(pDest,pSrc,src.cols);//图像层像素地址pSrc += src.step;}return qImage;}//为3通道的彩色图片else if(src.type() == CV_8UC3){//得到图像的的首地址const uchar *pSrc = (const uchar*)src.data;//以src构造图片QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);//在不改变实际图像数据的条件下,交换红蓝通道return qImage.rgbSwapped();}//四通道图片,带Alpha通道的RGB彩色图像else if(src.type() == CV_8UC4){const uchar *pSrc = (const uchar*)src.data;QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);//返回图像的子区域作为一个新图像return qImage.copy();}else{return QImage();}
}
这段代码的目的是将OpenCV的Mat
(矩阵)对象转换为Qt的QImage
对象,以便在Qt框架中使用图像数据,如显示在QLabel
、QPixmap
或其他Qt的图形显示组件中。由于OpenCV和Qt处理图像数据的方式有所不同(例如,内存布局、颜色空间等),因此需要进行适当的转换。下面是这段代码的详细讲解:
1. 灰度图像 (CV_8UC1
)
- 构造QImage:对于灰度图像,使用
QImage::Format_Indexed8
格式构造QImage
对象。这种格式使用8位索引到颜色表来存储每个像素的颜色,适用于灰度图像,因为灰度图像可以看作是从黑色到白色的256级颜色深度。 - 设置颜色表:通过
setColorCount(256)
和setColor(i, qRgb(i,i,i))
为QImage
设置一个包含256个条目的颜色表,每个条目对应一个灰度值(从黑到白)。 - 数据复制:使用循环遍历
Mat
对象的每一行,并将灰度数据复制到QImage
的相应行中。这里使用memcpy
而不是memcmp
(memcmp
用于比较内存区域,而不是复制)。然而,原代码中错误地使用了memcmp
,应该替换为memcpy
。
2. 彩色图像 (CV_8UC3
)
- 构造QImage:对于三通道(RGB)彩色图像,使用
QImage::Format_RGB888
格式直接通过Mat
对象的数据指针构造QImage
。注意,OpenCV默认使用BGR顺序,而Qt的QImage
使用RGB顺序,因此需要使用rgbSwapped()
方法来交换红色和蓝色通道。
3. 带Alpha通道的彩色图像 (CV_8UC4
)
- 构造QImage:对于四通道(RGBA)图像,使用
QImage::Format_ARGB32
格式直接通过Mat
对象的数据指针构造QImage
。这里不需要交换颜色通道,因为OpenCV的RGBA顺序与Qt的ARGB顺序相匹配(除了最后一个通道的位置,但这不影响颜色显示)。 - 复制图像:虽然这里直接使用
Mat
的数据指针构造了QImage
,但出于安全和稳定性的考虑,使用copy()
方法创建了一个QImage
的副本。这是因为原始的Mat
数据可能会在将来的某个时间点被修改或释放,而复制的图像则不受这些变化的影响。
好了,下机!!恰饭