ubuntu中QT+opencv在QLable上显示摄像头
饭前的一篇文章吧,写完吃饭走
图像在机器视觉中的重要性是不可忽视的。机器视觉是指计算机利用图像处理技术进行图像识别、分析和理解的科学与技术领域。图像是机器视觉的输入数据,通过分析和处理图像,计算机可以实现对图像中物体、场景等信息的提取和理解。
以下是图像在机器视觉中的重要性的几个方面:
1. 物体识别和分类:图像可以提供丰富的视觉信息,包括物体的形状、颜色、纹理等特征。通过对图像进行分析和处理,机器可以识别和分类不同的物体,实现自动化的物体检测和识别。
2. 场景分析和理解:通过对图像进行分析,可以理解图像所代表的场景。例如,机器可以通过图像识别出室内、室外、城市、乡村等不同的场景,从而为场景的分析和理解提供基础。
3. 图像检索和搜索:通过对图像进行特征提取和相似度计算,机器可以实现对图像的检索和搜索。例如,在图像数据库中搜索与输入图像相似的图像,或者通过输入图像进行目标物体的搜索和定位。
4. 视觉导航和定位:图像可以提供导航和定位所需的视觉信息。通过对图像进行分析,机器可以识别出环境中的特征点或标志物,从而实现室内、室外等不同环境下的定位和导航。
综上所述,图像在机器视觉中具有重要的作用,是实现机器视觉的关键输入数据。通过对图像进行分析和理解,机器可以实现对物体、场景等信息的自动化识别、分类和理解,从而实现各种应用,如智能监控、智能驾驶等。
那么这一切的开始呢,就是使用opencv来实现摄像头的采集
废话不多,我们直接上代码
UI文件的编写
一个开始一个结束,还有一个摄像头参数的显示,但是写出来有BUG(对程序运行没影响)所以就不实现了,都是原名,没有修改对象名
代码编写
.pro文件
我们 要导入我们的opencv的库
INCLUDEPATH += /usr/local/include
/usr/local/include/opencv
/usr/local/include/opencv2
LIBS += /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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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
数据可能会在将来的某个时间点被修改或释放,而复制的图像则不受这些变化的影响。
好了,下机!!恰饭