备注:
两天,找了各种资料和其他大佬的笔记,终于能在QT下进行摄像头调用并进行Opencv图像处理,本文中程序只是开头,调用canny算子进行边缘采集。文章重点是Mat数据和QImage数据的转换。canny边缘处理程序请参考我以前学opencv时写的程序:
https://blog.csdn.net/w5875895/article/details/108267984
一、程序
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QImageReader>
#include <QLabel>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
// image = new QImage();
connect(timer,SIGNAL(timeout()),this,SLOT(readFarme()));
connect(ui->open,SIGNAL(clicked()),this,SLOT(on_Open_triggered()));
connect(ui->stop,SIGNAL(clicked()),this,SLOT(on_Stop_triggered()));
connect(ui->open_picture,SIGNAL(clicked()),this,SLOT(on_open_picture_triggered));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_open_triggered()
{
cap.open(1);
timer->start(33);
}
void MainWindow::on_stop_triggered()
{
// 停止读取数据。
timer->stop();
cap.release();
ui->cameraView->clear();
}
void MainWindow::readFarme()
{
cap.read(src_image);
// qDebug()<<src_image.channels();
// qDebug()<<src_image.type();
cvtColor(src_image, src_image, CV_BGR2GRAY);
// Canny_Demo(0,0);
QImage imag = MatImageToQt(src_image);
//imag = imag.scaled(300, 300); //缩放图像
// QImage image2 = imag.convertToFormat(QImage::Format_Indexed8); //灰度图转换 --将QT类型的图转换
// image2.setColorCount(256);
// for(int i = 0; i < 256; i++)
// {
// image2.setColor(i, qRgb(i, i, i));
// }
// Mat dst = QtToMatImage(image2);
// QImage imag3 = MatImageToQt(dst);
ui->cameraView->setPixmap(QPixmap::fromImage(imag));
}
//Mat转成QImage
QImage MainWindow::MatImageToQt(const Mat &src)
{
//CV_8UC1 8位无符号的单通道---灰度图片
QImage qImage;
if(src.type() == CV_8UC1)
{
qImage =QImage((const unsigned char*)(src.data),
src.cols,src.rows,
src.cols*src.channels(),
QImage::Format_Indexed8);
// //使用给定的大小和格式构造图像
// //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 MainWindow::QtToMatImage(QImage & qim)
{
Mat mat;
switch(qim.format())
{
case QImage::Format_RGB888:
mat = Mat(qim.height(), qim.width(),
CV_8UC3,(void*)qim.constBits(),qim.bytesPerLine());
break;
case QImage::Format_ARGB32_Premultiplied:
mat = Mat(qim.height(), qim.width(),
CV_8UC4,(void*)qim.constBits(),qim.bytesPerLine());
break;
}
return mat;
}
void MainWindow::Canny_Demo(int,void*)
{
int threshold_value = 50;
blur(src_image, src, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
Canny(src, src, threshold_value, threshold_value*2,3,false);
}
void MainWindow::on_open_picture_triggered()
{
QImage *imgReader =new QImage; //("D:\tutu1.jpg");
imgReader->load("D:\\tutu2.jpg");
ui->label->setPixmap(QPixmap::fromImage(*imgReader));
// QPixmap img;
// img.load("D:\\tutu2.jpg"); // D:\tutu2.jpg 这种错误 \\绝对路径
// ui->label->clear();
// ui->label->setPixmap(img);
}
运行结果: