發布日期:2022-04-25 點擊率:75
關鍵詞:正運動技術,機器視覺,運動控制
摘要:QT是目前眾多軟件開發工程師使用的C++應用程序開發框架。QT具有完整的GUI圖形庫,界面控件的樣式和布局可直接通過控件屬性進行設置,簡化了代碼的使用。對于需要人機界面操作的機器視覺程序而言,QT強大的界面設計功能很大程度地減少了視覺軟件開發工程師設計操作界面的開發難度。正運動技術VPLC系列控制器可搭載Linux系統,且支持QT調用正運動軟件的ZBasic指令。
QT是目前眾多軟件開發工程師使用的C++應用程序開發框架。QT具有完整的GUI圖形庫,界面控件的樣式和布局可直接通過控件屬性進行設置,簡化了代碼的使用。對于需要人機界面操作的機器視覺程序而言,QT強大的界面設計功能很大程度地減少了視覺軟件開發工程師設計操作界面的開發難度。正運動技術VPLC系列控制器可搭載Linux系統,且支持QT調用正運動軟件的ZBasic指令。
本節課程我們將和大家一起分享ZBasic結合QT實現圖像采集功能的方法。
一認識QT
Qt是一個1991年由Qt Company開發的跨平臺C++圖形用戶界面應用程序開發框架。它既可以開發GUI程序,也可用于開發非GUI程序,比如控制臺工具和服務器。Qt是面向對象的框架,使用特殊的代碼生成擴展(稱為元對象編譯器“meta Object Compiler, moc”)以及一些宏,Qt很容易擴展,并且允許真正地組件編程。
二ZBasic and QT
正運動技術將ZDevelop軟件主要使用的ZBasic語言封裝成C++動態鏈接庫,QT可以通過調用動態庫的形式調用ZBasic指令。
三軟件實現
(一)準備
(二)實例演示
1.打開QTCreator軟件,新建QT項目:點擊“New Project”→項目選擇“Application”→選擇“QT Widgets Application”→點擊“Choose...”按鈕進入下一步→輸入項目名稱“ZVision_QT_1”,選擇項目存儲的路徑(路徑不能包含中文),點擊“下一步”按鈕→默認選擇“下一步”,最后點擊“完成”按鈕,完成項目的建立。
2.添加庫相關文件:將相關庫文件拷貝到項目所在文件夾下→鼠標左鍵點擊項目名稱,再點擊鼠標右鍵彈出快捷菜單,選擇“添加現有文件”→依次將“zaux.h”文件、“zmotion.h”文件、“zaux.cpp”文件添加到項目→雙擊“.pro”文件,手動添加動態鏈接庫代碼“win32: LIBS += -L$$PWD/ -lzmotion”→在“mainwindow.cpp”文件中定義調用庫相關頭文件,即添加代碼:#include “zmotion.h”和#include “zaux.h”。
3.在mainwindow.cpp文件中定義程序中使用到的全局變量。
ZMC_HANDLE g_handle;//控制器句柄
int Times=0;
uint8 zv0_pBuff[400*300*2]={0};//鎖存0緩存大小
int ContinuousGetImgFlag=0; //連續采集標志
4.設計UI界面。
5.添加界面初始化代碼。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->ZV0->setText("");//清空字體
ui->ZV0->setStyleSheet("QLabel{background-color:rgb(0, 0, 100);}"); //設置樣式表
ui->Exposurevalue->setText("5000");
}
6.添加【掃描控制器IP】槽函數:選擇【掃描控制器IP】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//掃描控制器IP
void MainWindow::on_Scan_Control_IP_clicked()
{
char buffer[10240];
int32 iresult;
const char *ipaddress;
iresult = ZMC_SearchEth(buffer, 10230, 100);//掃描控制器IP,返回錯誤碼信息
if(ERR_OK != iresult)
{
return ; //錯誤
//將掃描到的所有IP地址進行分割,并按照IP地址格式顯示在下拉列表中
int ipos =0;
const char * pstring;
pstring = buffer;
for(int j= 0; j< 100;j++) //最多100個IP列表
{
char buffer2[256];
buffer2[0] = '?';
while(' ' == pstring[0])
{
pstring++;
}
ipos = sscanf(pstring , "%s", &buffer2);
if(EOF == ipos)
{
break;
}
//跳過字符
while((' ' != pstring[0]) && (' ' != pstring[0]) && ('?' != pstring[0]))
{
pstring++;
}
if(0 == strcmp(buffer2, ipaddress))
{
return ;
}
ui->ComboBoxIP->addItem(buffer2);
}
}
7.添加【連接】槽函數:選擇【連接】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//連接控制器
void MainWindow::on_link_Control_clicked()
{
//get ip from current list
int32 iresult;//錯誤碼
int nIndex = 0;
char * tmp_buff = new char[16];
char str1[64];
QString str;
str = ui->ComboBoxIP->currentText();//獲取IP列表里的IP地址數據
qDebug()<<"current ip"<<str;//打印當前選擇的IP地址數據
QByteArray ba = str.toLatin1();//將IP的字符串格式轉到char * 格式
tmp_buff = ba.data();
if(0 != g_handle)//如果控制器句柄不為0
{
ZAux_Close(g_handle);//關閉控制器鏈接
}
iresult=ZAux_OpenEth(tmp_buff,&g_handle);//根據獲取的IP地址與控制器建立鏈接,返回錯誤碼
if (iresult==0)
{
sprintf(str1, "控制器連接成功,當前IP:%s", tmp_buff);
setWindowTitle(str1);
qDebug()<<"link Success! ip:"<<tmp_buff;
}
else
{
qDebug()<<"link Fail!";
setWindowTitle("控制器已斷開");
}
}
8.添加【斷開】槽函數:選擇【斷開】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//斷開連接控制器
void MainWindow::on_Disconnect_clicked()
{
if(0 != g_handle)
{
ZAux_Close(g_handle);//關閉控制器鏈接
g_handle = NULL;//清空句柄
setWindowTitle("控制器已斷開");
}
}
9.添加【掃描相機】槽函數:選擇【掃描相機】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//掃描相機
void MainWindow::on_Scan_Camera_clicked()
{
float CamNum=0;
int32 iresult;//錯誤碼
QString str;
char buffer[2048];
iresult=ZAux_RunTask(g_handle,0,"cam_scan_all()");//運行控制器里面指定的SUB
if (iresult==0)
{
qDebug()<<"run cam_scan_all() success";
}
else
{
qDebug()<<"run cam_scan_all() fail !!"<<iresult;
}
ZAux_Direct_GetTable(g_handle,0,1,&CamNum);//讀取控制器table變量
str = QString("掃描到的相機個數:%1").arg(CamNum);
ui->CamNum->setText(str);//顯示掃描到的相機數量
}
10.添加【采集圖像】槽函數:選擇【采集圖像】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容(此前需要在頭文件中定義使用到的QPixmap fPixmap 變量)。
//單次采集
void MainWindow::on_Camera_Grab_clicked()
{
int32 iresult;//錯誤碼
iresult=ZAux_RunTask(g_handle,0,"btn_grab()");//運行控制器里面指定的SUB
if (iresult==0)
{
qDebug()<<"run btn_grab() success";
}
else
{
qDebug()<<"run btn_grab() fail !!"<<iresult;
}
ZV0_Show();//將控制器獲取到的圖像轉換成Qt可顯示的圖片格式,并顯示圖像
}
//將獲取到的圖像顯示到ZV0控件中
void MainWindow::ZV0_Show()
{
int latin=0,buffsize=400*300*2;
int width, height,bite,WrTimes;
int flag=1, count=0;
//獲取zvlatch的信息
ZMC_ZVLatinImgGetInfo(g_handle, latin, &width, &height, &bite, &WrTimes);//獲取圖像信息
if(WrTimes==0)
{
return;//時間沒有改變退出函數
}
//獲取到的鎖存0的緩存數據
buffsize = width*height*2;
ZMC_ZVLatinImgGet(g_handle, latin, &width, &height, &bite, zv0_pBuff, buffsize);//獲取圖像數據
//將獲取到的鎖存0的緩存數據在qt中顯示出來
QImage Image((uchar *)zv0_pBuff,width, height,QImage::Format_RGB555);
Image = Image.mirrored(false,true);
QPixmap Pixmap = QPixmap:: fromImage (Image);
fPixmap = Pixmap.scaled(width, height);
ui->ZV0->clear();
ui->ZV0->setPixmap(fPixmap);
}
11.添加顯示函數ZV0_Show()的定義和聲明函數。
private slots:
void on_Scan_Control_IP_clicked();
void on_link_Control_clicked();
void on_Disconnect_clicked();
void on_Scan_Camera_clicked();
void on_Camera_Grab_clicked();
void on_Contiue_Grab_clicked();
void on_Stop_Grab_clicked();
void on_Set_Exposure_clicked();
void ZV0_Show(); //鎖存0顯示
//將獲取到的圖像顯示到ZV0控件中
void MainWindow::ZV0_Show()
{
int latin=0,buffsize=400*300*2;
int width, height,bite,WrTimes;
int count=0;
int flag=0;
ZMC_ZVLatinImgGetInfo(g_handle, latin, &width, &height, &bite, &WrTimes);
qDebug()<<WrTimes;
if(Times == WrTimes)
{
return;//時間沒有改變退出函數
}
else
{
Times = WrTimes;
}
QThread::msleep(100);
while(0 == flag)//等待
{
ZAux_Direct_GetVariableInt(g_handle,"CamGetPhotoFlag",&flag);
QThread::msleep(10);
count++;
if(1000 < count)//等待時間大于10s
{
break;//退出循環
}
}
flag=0;
//獲取zvlatch的信息
ZAux_Direct_SetVariableInt(g_handle,"CamGetPhotoFlag",flag);
//獲取到的鎖存0的緩存數據
buffsize = width*height*2;
ZMC_ZVLatinImgGet(g_handle, latin, &width, &height, &bite, zv0_pBuff, buffsize);//獲取圖像數據
//將獲取到的鎖存0的緩存數據在qt中顯示出來
flag=1;
//獲取zvlatch的信息
ZAux_Direct_SetVariableInt(g_handle,"CamGetPhotoFlag",flag);
QImage Image((uchar *)zv0_pBuff,width, height,QImage::Format_RGB555);
Image = Image.mirrored(false,true);
QPixmap Pixmap = QPixmap:: fromImage (Image);
fPixmap = Pixmap.scaled(width, height);
ui->ZV0->clear();
ui->ZV0->setPixmap(fPixmap);
}
12.添加【連續采集】槽函數:選擇【連續采集】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//連續采集
void MainWindow::on_Contiue_Grab_clicked()
{
int32 iresult;//錯誤碼
iresult=ZAux_RunTask(g_handle,0,"btn_cgrab()");//運行控制器里面指定的SUB
if (iresult==0)
{
qDebug()<<"run btn_cgrab() success";
}
else
{
qDebug()<<"run btn_cgrab() fail !!"<<iresult;
}
ContinuousGetImgFlag=1;//連續采集標志置1
}
13.添加定時刷新函數:在“mainwindow.h”文件中添加包含QTimer定時器的類型庫,并定義“QTimer UpZV_0”定時器變量→在界面初始化函數中添加定時器觸發條件和信號與槽連接函數→添加定時采集圖像的定義和聲明函數,并在聲明函數中添加具體的實現代碼內容。
#include
#include
void ZV0_Show(); //鎖存0顯示
void UpZV_0show();
private:
Ui::MainWindow *ui;
QPixmap fPixmap;
QTimer UpZV_0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->ZV0->setText(""); //清空字體
ui->ZV0->setStyleSheet("QLabel{background-color:rgb(0, 0, 100);}"); //設置樣式表
ui->Exposurevalue->setText("5000");
UpZV_0.start(20);//200ms定時判斷采集并顯示圖像
connect(&UpZV_0, SIGNAL(timeout()), this, SLOT(UpZV_0show()));
}
//定時器開啟連續采集
void MainWindow::UpZV_0show()
{
if(1 == ContinuousGetImgFlag)
{
ZV0_Show();
}
}
14.添加【停止采集】槽函數:選擇【停止采集】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//停止采集
void MainWindow::on_Stop_Grab_clicked()
{
int32 iresult;//錯誤碼
iresult=ZAux_RunTask(g_handle,0,"btn_stopCgrab()");//運行控制器里面指定的SUB
if (iresult==0)
{
qDebug()<<"run btn_stopCgrab() success";
}
else
{
qDebug()<<"run btn_stopCgrab() fail !!"<<iresult;
}
ContinuousGetImgFlag=0;//連續采集標志置0
}
15.添加【設置】槽函數:選擇【設置】按鈕,右擊彈出快捷菜單欄,選擇“轉到槽”選項→彈出“轉到槽”窗口,選擇對應的信號源“clicked()”,點擊“OK”確認,即可完成槽函數的定義和聲明→在槽函數的聲明函數中添加函數實現的具體代碼內容。
//設置曝光時間
void MainWindow::on_Set_Exposure_clicked()
{
int32 iresult;//錯誤碼
QString str_tmp;
float Exposurevalue;
str_tmp = ui->Exposurevalue->text();//獲取QLineEdit控件顯示的曝光值
Exposurevalue = str_tmp.toFloat();//字符串轉成浮點數
ZAux_Direct_SetTable(g_handle,1,1,&Exposurevalue);//設置控制器的table變量
iresult=ZAux_RunTask(g_handle,0,"Camera_Exposure()");//運行控制器里面指定的SUB
if (iresult==0)
{
qDebug()<<"run Camera_Exposure() success";
}
else
{
qDebug()<<"run Camera_Exposure() fail !!"<<iresult;
}
}
16.查看運行效果:將控制器接入電源,使用網線將控制器與PC連接,將相機通電并接入控制器→使用ZDevelop軟件打開ZBasic指令編寫包含采集函數的項目文件,將該項目下載到控制器→運行QT程序,并連接到控制器,進行對應采集操作。
完整代碼獲取地址
▼
本次,正運動技術ZBasic結合Qt實現機器視覺圖像采集,就分享到這里。
更多精彩內容請關注“正運動小助手”公眾號,需要相關開發環境與例程代碼,請咨詢正運動技術銷售工程師:400-089-8936。
本文由正運動技術原創,歡迎大家轉載,共同學習,一起提高中國智能制造水平。文章版權歸正運動技術所有,如有轉載請注明文章來源。
下一篇: PLC、DCS、FCS三大控
上一篇: 機器視覺運動控制一體