调用策略:
1,相机以相机数组形式打开
2,两个线程,主线程界面显示,副线程basler相机拍摄
3,副线程发送信号,主线程槽函数显示图像,图像使用重写的QLabel类的paintevent刷上去(速度快)
4,3中信号槽的connect函数中第五个参数设置为队列阻塞链接即
QObject::connect(m_dia, &mybasler::signal_dia,this,&MainWindow::show_dia,Qt::BlockingQueuedConnection);
5,主界面显示的图像调用的是全局变量
tips 下面贴一部分代码,因为我们做的是一个表面瑕疵检测软件,所以里面会模拟一些信号来不及删除,大家可以自行删除后使用。
相机类 mybasler.cpp
#include "mybasler.h"
#include <QThread>
#include <QDebug>
QPixmap *pix_ex1 = Q_NULLPTR;
QPixmap *pix_ex2 = Q_NULLPTR;
QPixmap *pix_ex3 = Q_NULLPTR;
QPixmap *pix_ex4 = Q_NULLPTR;
QPixmap *pix_ex5 = Q_NULLPTR;
QPixmap *pix_ex6 = Q_NULLPTR;
//ID 0 6次全拍
//ID 1 2号相机的再次拍照
//ID 2 4号相机外表瑕疵的旋转后拍照
//ID 3 算法 直径
//ID 4 算法 确定旋转角度
//ID 5 算法 外径
//ID 6 算法 外部瑕疵
//ID 7 算法 球窝毛刺
//ID 8 算法 孔内毛刺
mybasler::mybasler(int ID,QObject *parent) : QObject(parent)
{
state_thread = false;
IDN = ID;
//相机数组生成方法+
if(ID == 0)
{
PylonInitialize();
CTlFactory& TLFactory = CTlFactory::GetInstance();
ITransportLayer * pTl = TLFactory.CreateTl("BaslerGigE");
DeviceInfoList_t devices;
n = pTl->EnumerateDevices(devices);
CInstantCameraArray cameraArray(devices.size());
if(n == 0) {
qDebug() << "Cannot find Any camera!";
//QMessageBox::warning(this, "Error", QString::fromLocal8Bit("Can't connect camera"));
return;
}
CTlFactory& tlFactory = CTlFactory::GetInstance(); //建立相机工厂
if ( tlFactory.EnumerateDevices(devices) == 0 )
{
throw RUNTIME_EXCEPTION( "No camera present.");
}
cameras.Initialize(n);
for ( size_t i = 0; i < cameras.GetSize(); ++i)
{
cameras[i].Attach( tlFactory.CreateDevice( devices[ i ]));
cout << "Using device " << cameras[ i ].GetDeviceInfo().GetModelName() << endl;
m_cameralist.append(QString(cameras[ i ].GetDeviceInfo().GetModelName()));
}
}
else if(ID == 1)
{
CTlFactory& TLFactory = CTlFactory::GetInstance();
ITransportLayer * pTl = TLFactory.CreateTl("BaslerGigE");
DeviceInfoList_t devices;
n = pTl->EnumerateDevices(devices);
CInstantCameraArray cameraArray(devices.size());
if(n == 0) {
qDebug() << "Cannot find Any camera!";
//QMessageBox::warning(this, "Error", QString::fromLocal8Bit("Can't connect camera"));
return;
}
CTlFactory& tlFactory = CTlFactory::GetInstance(); //建立相机工厂
if ( tlFactory.EnumerateDevices(devices) == 0 )
{
throw RUNTIME_EXCEPTION( "No camera present.");
}
cameras.Initialize(1);
cameras[0].Attach( tlFactory.CreateDevice( devices[2])); //直接连接2号相机
}
else if(ID == 2)
{
CTlFactory& TLFactory = CTlFactory::GetInstance();
ITransportLayer * pTl = TLFactory.CreateTl("BaslerGigE");
DeviceInfoList_t devices;
n = pTl->EnumerateDevices(devices);
CInstantCameraArray cameraArray(devices.size());
if(n == 0) {
qDebug() << "Cannot find Any camera!";
//QMessageBox::warning(this, "Error", QString::fromLocal8Bit("Can't connect camera"));
return;
}
CTlFactory& tlFactory = CTlFactory::GetInstance(); //建立相机工厂
if ( tlFactory.EnumerateDevices(devices) == 0 )
{
throw RUNTIME_EXCEPTION( "No camera present.");
}
cameras.Initialize(1);
cameras[0].Attach( tlFactory.CreateDevice( devices[3])); //直接连接4号相机
}
}
void mybasler::RunMyThread()
{
if(IDN == 0)
{
bool state = true;
emit singal_tomainString(m_cameralist); //发送相机列表 若相机不足 则搜索不到相机
if(n < 6){
emit singal_tomainstate(state); //发送相机状态 若相机数量小于6 则显示警告框
}
else if(n == 6)
{
while(isStop == false)
{
if(state_thread == false)
{
//QMutexLocker locker(&mute);
cameras.StartGrabbing();
for(int j = 0;j < 6;j ++)
{
CGrabResultPtr ptrGrabResult;
for( uint32_t i = 0; i < c_countOfImagesToGrab && cameras.IsGrabbing(); ++i)
{
cameras[j].RetrieveResult( 5000, ptrGrabResult, TimeoutHandling_ThrowException);
if (ptrGrabResult->GrabSucceeded())
{
//图像大小
qDebug() << "SizeX: " << ptrGrabResult->GetWidth() << endl;
qDebug() << "SizeY: " << ptrGrabResult->GetHeight() << endl;
const uint8_t *pImageBuffer = (uint8_t *) ptrGrabResult->GetBuffer();
qDebug() << "Gray value of first pixel: " << (uint32_t) pImageBuffer[0] << endl << endl;
}
uchar* buff = (uchar*)ptrGrabResult->GetBuffer();
int nHeight = ptrGrabResult->GetHeight();
int nWidth = ptrGrabResult->GetWidth();
QImage imgBuff(buff, nWidth, nHeight, QImage::Format_Indexed8);
QPixmap pix = QPixmap::fromImage(imgBuff);
//传递指针必须一个变量 一个地址 要不然会传错
if(j == 0)
{
pix1 = pix;
pix_ex1 = &pix1;
}
else if(j == 1)
{
pix2 = pix;
pix_ex2 = &pix2;
}
else if(j == 2)
{
pix3 = pix;
pix_ex3 = &pix3;
}
else if(j == 3)
{
pix4 = pix;
pix_ex4 = &pix4;
}
else if(j == 4)
{
pix5 = pix;
pix_ex5 = &pix5;
}
else if(j == 5)
{
pix6 = pix;
pix_ex6 = &pix6;
}
};
}
cameras.StopGrabbing();
qDebug() << QThread::currentThreadId() << endl;
QPixmap pix;
emit singal_tomainthread(pix);
qDebug() << "send signal" << endl;
//QThread::msleep(25);
}
if(isStop == true)
{
break;
}
}
}
}
else if(IDN == 1)
{
cameras[0].MaxNumBuffer = 1000;
cameras.StartGrabbing(GrabStrategy_OneByOne);
while(state_thread == false)
{
{
//QMutexLocker locker(&mute);
CGrabResultPtr ptrGrabResult;
cameras[0].RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);
if (ptrGrabResult->GrabSucceeded())
{
//图像大小
qDebug() << "SizeX: " << ptrGrabResult->GetWidth() << "SizeY: " << ptrGrabResult->GetHeight() << endl;
const uint8_t *pImageBuffer = (uint8_t *) ptrGrabResult->GetBuffer();
//qDebug() << "Gray value of first pixel: " << (uint32_t) pImageBuffer[0] << endl << endl;
}
uchar* buff = (uchar*)ptrGrabResult->GetBuffer();
int nHeight = ptrGrabResult->GetHeight();
int nWidth = ptrGrabResult->GetWidth();
QImage imgBuff(buff, nWidth, nHeight, QImage::Format_Indexed8);
QString fileName = QString("%1.png").arg(i);
i++;
qDebug() << fileName << endl;
emit signal_ang2(imgBuff);
//cameras.StopGrabbing();
qDebug() << QThread::currentThreadId() << endl;
}
}
QThread::msleep(25);
}
else if(IDN == 3)
{
while(isStop == false)
{
if(state_thread == false)
{
qDebug() << QThread::currentThread() << ":" << pix_ex1->size() << &pix_ex1 << endl;
//算法部分
QThread::msleep(1000);
double dia = 1.3;
emit signal_dia(dia);
qDebug() << "use dia" << endl;
}
if(isStop == true)
{
qDebug() << "quit dia" << endl;
break;
}
}
qDebug() << "out dia" << endl;
}
else if(IDN == 4)
{
while(isStop == false)
{
if(state_thread == false)
{
qDebug() << QThread::currentThread() << ":" << pix_ex2->size() << &pix_ex2 << endl;
double ang = 1.5;
QThread::msleep(350);
emit signal_ang(ang);
}
if(isStop == true)
{
break;
}
}
}
else if(IDN == 5)
{
while(isStop == false)
{
if(state_thread == false)
{
qDebug() << QThread::currentThread() << ":" << pix_ex3->size() << &pix_ex3 <<endl;
double kongjing = 1.5;
QThread::msleep(550);
emit signal_kong(kongjing);
}
if(isStop == true)
{
break;
}
}
}
}
void mybasler::change_pix(QPixmap pix)
{
pix_pub = pix;
}
QLable重写类
#include "showpicwidget.h"
#include <QDebug>
ShowPicWidget::ShowPicWidget(QWidget *parent) : QLabel(parent)
{
}
void ShowPicWidget::setmyimg(QPixmap mypix)
{
pix = mypix;
update();
}
void ShowPicWidget::paintEvent(QPaintEvent *event)
{
QLabel::paintEvent(event);
QPainter painter(this);
painter.drawPixmap(QRect(0, 0, 421, 279), pix);
qDebug() << pix.size() << endl;
}
主界面槽函数
void MainWindow::show_image(QPixmap pix)
{
if(cishu == false)
{
t_dia->start();
emit start_dia();
t_ang->start();
emit start_ang();
t_kongjing->start();
emit start_kongjing();
cishu = true;
}
else
{
m_dia->state_thread = false;
m_ang->state_thread = false;
m_kongjing->state_thread = false;
}
//开启线程后 主界面显示照片
ui->label_camera1->setmyimg(*pix_ex1);
ui->label_camera2->setmyimg(*pix_ex2);
ui->label_camera3->setmyimg(*pix_ex3);
ui->label_camera4->setmyimg(*pix_ex4);
ui->label_camera5->setmyimg(*pix_ex5);
ui->label_camera6->setmyimg(*pix_ex6);
m_control->state_thread = true;
}
因为图像发送信号后要开一些算法的线程,所以会发送其他信号,大家可以不用在意这些。