前言
本文主要实现基于qt5.3做一个视觉定位识别的功能,halcon版本使用的是halcon12.0,调用halcon的dll来实现二次开发,下边从头开始设置。
与前面的python版、MFC版、Qt版一样,可供不同的开发者进行学习使用。
编程环境:qt5.3
halcon12.0
IDE: VisualStudio 2010
演示视频
本次项目的效果视频:
基于qt调用halcon实现图像定位,模板匹配
一、项目文件目录讲解
本解决方案有3个项目工程,包括软件,验证加密,解密工程,本文主要讲解的是CtuImageMatching项目
1、Calibration.cpp、Calibration.h:此类主要是相机标定的逻辑
2、CameraSetting.cpp、CameraSetting.h:此类主要是相机设置的逻辑
3、CtuImageMatching.cpp、CtuImageMatching.h:整个软件的主逻辑计算
4、Helper.cpp、Helper.h:帮助页面
5、QtTcpServerLib.cpp、QtTcpServerLib.h:标准的TCP服务器类
6、QtThread.cpp、QtThread.h:标准的线程类
7、SoftEncryption.cpp、SoftEncryption.h:标准的加密算法类
注意:5、6、7是自己进行封装方便自己使用的类
二、Qt Designer设置ui界面
一下界面只需要用Qt Designer进行编辑即可,基本上不需要代码部分
1.CtuImageMatching.ui界面详解
先上图,只需要按照这个来设置即可:
从主界面上可以看出,本视觉软件所具有的功能。
2.CameraSetting.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本相机设置具有的功能。
3.Calibration.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本标定设置具有的功能。
4.Helper.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本帮助界面具有的功能,这里暂时就一个QLabel用来放了个二维码。
三、文件算法解析
1.CameraSetting.cpp重要函数解析
1.首先定义好相机设置的初始化
CameraSetting::CameraSetting(QString Path,QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
FilePath = Path;
//this->setWindowIcon(QIcon(":/CtuImageMatching/Resources/29.ico"));
ReadIni();
OpenCarmerFlag=false;
GetPictureFlag = false;
ROIFlag = false;
SetWindowAttr("background_color","black"); //设置背景颜色
Hlong winID = (Hlong) ui.Lab_HShowWindow->winId();
OpenWindow(0,0,ui.Lab_HShowWindow->geometry().width(),ui.Lab_HShowWindow->geometry().height(),winID,"","",&hv_WindowHandle); //显示那个框,获得句柄
HDevWindowStack::Push(hv_WindowHandle);
if (HDevWindowStack::IsOpen()) //判断窗口是否打开了
{
SetColor(hv_WindowHandle,"red");
SetDraw(hv_WindowHandle,"margin");
SetLineWidth(hv_WindowHandle,1);
}
workerThread = new QtThread(this);
workertimer = new QTimer(this);
connect(workertimer, SIGNAL(timeout()), this, SLOT(TenLine()));
ctu = this;
//on_Btn_SertchCarmer_clicked();
}
2.查找相机
这里有三种相机接口类型,分别是:DirectShow、GigEVision、GenICamTL
void CameraSetting::on_Btn_SertchCarmer_clicked()
{
const HTuple Name, Query;
HTuple Information,ValueList, info_BoardsList, hv_Length;
HTuple deviceNames;
switch(CarmerType.toInt())
{
case -1:
return;
case 0:
deviceNames = "DirectShow";
break;
case 1:
deviceNames = "GigEVision";
break;
case 2:
deviceNames = "GenICamTL";
break;
}
QStringList CarmerList;
try{
HalconCpp::InfoFramegrabber(deviceNames,"device",&Information,&ValueList);
HalconCpp::TupleLength(ValueList,&hv_Length);
int length1 = (int)hv_Length[0];
for(int i=0;i<length1;i++)
{
char strDevice[128];
memset(strDevice,0,128);
try{
sprintf(strDevice,HTuple(ValueList[i]).S());
}catch(HTupleAccessException e){
continue;
}
if(strcmp(strDevice,"default")==0)
{
break;
}
QString fill_name = deviceNames.ToString();// + ":" + strDevice;
fill_name.replace("\"","").append(":").append(strDevice);
CarmerList.append(fill_name);
}
}catch(...){}
ui.Com_CameraList->clear();
for each(const QString CameraMes in CarmerList)
{
ui.Com_CameraList->addItem(CameraMes);
}
}
3.连接相机
这里是根据搜索到的相机进行连接
bool CameraSetting::OpenCamera()
{
HTuple Information, ValueList;
QString str = ui.Com_CameraList->currentText();
QString ColorZone = "";
try
{
QStringList Driver = str.split(":");
if(ui.Com_ColorZone->count() <= 0)
{
if(Driver[0] == QStringLiteral("DirectShow"))
{
ColorZone = "gray";
}
else
{
ColorZone = "default";
}
}
else
{
ColorZone = ui.Com_ColorZone->currentText();
}
InfoFramegrabber(QStringToHTuple(Driver[0]), "defaults", &Information, &ValueList);
OpenFramegrabber(QStringToHTuple(Driver[0]), ValueList[0], ValueList[1], ValueList[2], ValueList[3], ValueList[4], ValueList[5], ValueList[6], ValueList[7], QStringToHTuple(ColorZone), ValueList[9], ValueList[10], ValueList[11], QStringToHTuple(Driver[1]), 0, ValueList[13], &hv_AcqHandle);
GrabImageStart(hv_AcqHandle, -1);
GrabImageAsync(&ho_Image, hv_AcqHandle, -1);
GetImageSize(ho_Image, &ho_Width, &ho_Hight);
SetPart(hv_WindowHandle,0,0,ho_Hight-1,ho_Width-1);
GetCarmerInfo(Driver[0]);
OpenCarmerFlag = true;
EnableCamera(OpenCarmerFlag);
return true;
}
catch(...)
{
CloseCamera();
return false;
}
}
4.获取相机参数
连接完相机之后,获取相机参数
void CameraSetting::GetCarmerInfo(QString CameraType)
{
//像素格式
try
{
HTuple hv_Value, hv_Length;
GetFramegrabberParam(hv_AcqHandle, "PixelFormat", &hv_Value);
TupleLength(hv_Value, &hv_Length);
int length = (int)hv_Length[0];
for(int i=0;i<length;i++)
{
QString pixformat = hv_Value[i].S();
ui.Com_PixFormat->addItem(pixformat);
}
}
catch(...)
{
}
//颜色空间
try
{
if (ui.Com_ColorZone->count() <= 0)
{
HTuple Information, ValueList, hv_Length;
InfoFramegrabber(QStringToHTuple(CameraType), "color_space", &Information, &ValueList);
TupleLength(ValueList, &hv_Length);
int length = (int)hv_Length[0];
for (int i = 0; i < length; i++)
{
QString colorspace = ValueList[i].S();
ui.Com_ColorZone->addItem(colorspace);
}
}
}
catch(...)
{
}
//曝光时间
try
{
HTuple hv_Value;
//曝光时间
if (CameraType == "DirectShow")
{
ui.Slider_ExporeTime->setMinimum(-13);
ui.Slider_ExporeTime->setMaximum(-1);
ui.Slider_ExporeTime->setValue(-1);
ui.Lab_ExporeTimeOutValue->setText(QString::number(ui.Slider_ExporeTime->value()));
ui.Check_AutoExporeTimeOut->setChecked(true);
ui.Check_AutoExporeTimeOut->setEnabled(true);
ui.Slider_ExporeTime->setEnabled(false);
SetFramegrabberParam(hv_AcqHandle, "exposure", "auto");
}
if (CameraType == "GigEVision")
{
GetFramegrabberParam(hv_AcqHandle, "ExposureTimeRaw", &hv_Value); //shuoable
int extime = hv_Value[0].D();
ui.Slider_ExporeTime->setMinimum(0);
ui.Slider_ExporeTime->setMaximum(4095);
ui.Slider_ExporeTime->setValue(extime);
ui.Lab_ExporeTimeOutValue->setText(QString(ui.Slider_ExporeTime->value()));
ui.Check_AutoExporeTimeOut->setChecked(false);
ui.Check_AutoExporeTimeOut->setEnabled(false);
ui.Slider_ExporeTime->setEnabled(true);
}
}
catch(...) {
}
//增益
try
{
HTuple hv_Value;
GetFramegrabberParam(hv_AcqHandle, "GainRaw", &hv_Value);
int gain = hv_Value[0].D();
ui.Slider_Gray->setMinimum(8);
ui.Slider_Gray->setMaximum(63);
ui.Slider_Gray->setValue(gain);
ui.Lab_GrayValue->setText(QString::number(ui.Slider_Gray->value()));
ui.Slider_Gray->setEnabled(true);
}
catch(...){
}
}
5.设置相机参数
设置曝光时间
void CameraSetting::on_Slider_ExporeTime_valueChanged(int value)
{
QStringList Driver = ui.Com_CameraList->currentText().split(":");
if(ui.Check_AutoExporeTimeOut->isChecked() == false)
{
int exposure = ui.Slider_ExporeTime->value();
ui.Lab_ExporeTimeOutValue->setText(QString::number(exposure));
try
{
if (Driver[0] == "DirectShow")
{
SetFramegrabberParam(hv_AcqHandle, "exposure", exposure);
}
if (Driver[0] == "GigEVision")
{
SetFramegrabberParam(hv_AcqHandle, "ExposureTimeRaw", exposure);
}
}
catch(...)
{
}
}
}
设置增益
void CameraSetting::on_Slider_Gray_valueChanged(int value)
{
int gain = ui.Slider_Gray->value();
ui.Lab_GrayValue->setText(QString::number(gain));
try
{
SetFramegrabberParam(hv_AcqHandle, "GainRaw", gain);
}
catch(...)
{
}
}
设置白平衡
void CameraSetting::on_Check_AutoBlanceWhite_clicked()
{
if (ui.Check_AutoBlanceWhite->isChecked())
{
try
{
SetFramegrabberParam(hv_AcqHandle, "white_balance", "auto");
}
catch(...)
{
}
}
else
{
}
}
6.获取图像,送到外部
bool CameraSetting::HDevImg(HObject* img)
{
if (hv_AcqHandle != NULL)
{
try
{
GrabImageAsync(img, hv_AcqHandle, -1);
return true;
}
catch(...)
{
img = NULL;
return false;
}
}
img = NULL;
return false;
}
2.Calibration.cpp重要函数解析
这文件主要是坐标标定
1.生成标定文件
void Calibration::AffineTran(int CurrentNum)
{
HTuple concat = NULL, concat1 = NULL, concat2 = NULL, concat3 = NULL;
try
{
concat = concat.TupleConcat(MyPoint[CurrentNum].P1_Image_X);
concat1 = concat1.TupleConcat(MyPoint[CurrentNum].P1_Image_Y);
concat2 = concat2.TupleConcat(MyPoint[CurrentNum].P1_Robot_X);
concat3 = concat3.TupleConcat(MyPoint[CurrentNum].P1_Robot_Y);
concat = concat.TupleConcat(MyPoint[CurrentNum].P2_Image_X);
concat1 = concat1.TupleConcat(MyPoint[CurrentNum].P2_Image_Y);
concat2 = concat2.TupleConcat(MyPoint[CurrentNum].P2_Robot_X);
concat3 = concat3.TupleConcat(MyPoint[CurrentNum].P2_Robot_Y);
concat = concat.TupleConcat(MyPoint[CurrentNum].P3_Image_X);
concat1 = concat1.TupleConcat(MyPoint[CurrentNum].P3_Image_Y);
concat2 = concat2.TupleConcat(MyPoint[CurrentNum].P3_Robot_X);
concat3 = concat3.TupleConcat(MyPoint[CurrentNum].P3_Robot_Y);
RobotHommat[CurrentNum].VectorToHomMat2d(concat, concat1, concat2, concat3);
MyPoint[CurrentNum].RobotHommatFlag = true;
ui.label_5->setText("OK");
}
catch(...)
{
MyPoint[CurrentNum].RobotHommatFlag = false;
ui.label_5->setText("NG");
}
}
2.根据标定文件转化数据
bool Calibration::PixelToRobot(int Num, QString img_x,QString img_y,double* robot_x,double* robot_y)
{
*robot_x = *robot_y = -1.0;
if (MyPoint[Num].RobotHommatFlag == true)
{
try
{
*robot_x = RobotHommat[Num].AffineTransPoint2d(img_x.toDouble(), img_y.toDouble(), robot_y);
return true;
}
catch(...) //(Exception e)
{
return false;
}
}
return false;
}
3.CtuImageMatching.cpp重要函数解析
1.初始化主窗体halcon
void CtuImageMatching::InitHalcon()
{
try{
CloseWindow(MyCurrentControl.hv_WindowHandle);
}catch(...){}
SetWindowAttr("background_color","white"); //设置背景颜色
Hlong winID = (Hlong) ui.ImageLab->winId();
OpenWindow(0,0,ui.ImageLab->geometry().width(),ui.ImageLab->geometry().height(),winID,"","",&MyCurrentControl.hv_WindowHandle);
HDevWindowStack::Push(MyCurrentControl.hv_WindowHandle);
if (HDevWindowStack::IsOpen()) //判断窗口是否打开了
{
SetColor(MyCurrentControl.hv_WindowHandle,"red");
SetDraw(MyCurrentControl.hv_WindowHandle,"margin");
SetLineWidth(MyCurrentControl.hv_WindowHandle,1);
}
}
2.鼠标移动到图像上获取像素和颜色
void CtuImageMatching::GetImagePixel()
{
if(HObjectIsNull(MyCurrentControl.ho_Image))
{
permanent->setText(QStringLiteral("坐标:-1,-1"));
permanent2->setText(QStringLiteral("像素值:-"));
return;
}
SetTposition(MyCurrentControl.hv_WindowHandle, 0, 0);
HTuple Row,Column,hv_Button;
hv_Button = 1;
int num = int(MyCurrentControl.hv_WindowHandle.TupleLength()[0].D());
if(num == 0)
{
return;
}
try{
GetMposition(MyCurrentControl.hv_WindowHandle, &Row, &Column, &hv_Button);
permanent->setText(QStringLiteral("坐标:") + QString("%1,%2").arg(Row[0].D()).arg(Column[0].D()));
HTuple grayval;
GetGrayval(MyCurrentControl.ho_Image, Row[0].D(), Column[0].D(), &grayval);
QString rgb = grayval.ToString();
permanent2->setText(QStringLiteral("像素值:") + rgb);
}
catch(...)
{
permanent->setText(QStringLiteral("坐标:-1,-1"));
permanent2->setText(QStringLiteral("像素值:-"));
}
}
3.载入图像
//载入图像
void CtuImageMatching::on_OpenImageAction_triggered()
{
QString path = QFileDialog::getOpenFileName(this, QStringLiteral("打开图像"), ".", QStringLiteral("Image Files(*.bmp *.jpg *.png)"));
if(path != "")
{
ClearWindow(MyCurrentControl.hv_WindowHandle);
ReadImage(&MyCurrentControl.ho_Image,QStringToHTuple(path));
try{
GetImageSize(MyCurrentControl.ho_Image, &MyCurrentControl.ho_Width, &MyCurrentControl.ho_Hight);
MySetPart();
//SetPart(MyCurrentControl.hv_WindowHandle,0,0,MyCurrentControl.ho_Hight-1,MyCurrentControl.ho_Width-1);
DispObj(MyCurrentControl.ho_Image, MyCurrentControl.hv_WindowHandle);
#ifdef VisionFunFlag
HTuple hv_Start,hv_Stop,hv_Duration;
CountSeconds(&hv_Start); //计算时间
VisionFunCode = VisionFun();
WriteString(MyCurrentControl.hv_WindowHandle,QStringToHTuple(VisionFunCode));
CountSeconds(&hv_Stop);
hv_Duration = (hv_Stop-hv_Start)*1000;
ui.statusBar->showMessage(QStringLiteral("耗时:%1 ms").arg(hv_Duration.D()));
QCoreApplication::processEvents(QEventLoop::AllEvents, 300);
#endif
}catch(...){}
}
}
4.保存图像
void CtuImageMatching::on_SaveImageAction_triggered()
{
QString fileName = QFileDialog::getSaveFileName(this, QStringLiteral("保存图像"), "", QStringLiteral("Image Files (*.bmp)"));
if(fileName != "")
{
try{
WriteImage(MyCurrentControl.ho_Image,"bmp",0,QStringToHTuple(fileName));
}catch(...){}
}
}
5.ROI绘制,以矩形为例
void CtuImageMatching::on_Rectangle1Action_triggered()
{
if(HObjectIsNull(MyCurrentControl.ho_Image))
{
return;
}
HTuple hv_Row1, hv_Column1, hv_Row2, hv_Column2;
HObject ROITemp;
SetColor(MyCurrentControl.hv_WindowHandle,"red");
DrawRectangle1(MyCurrentControl.hv_WindowHandle, &hv_Row1, &hv_Column1, &hv_Row2, &hv_Column2);
GenRectangle1(&ROITemp, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
if(HObjectIsNull(MyCurrentControl.ROITemp))
MyCurrentControl.ROITemp = ROITemp;
else
RunROI(ROITemp);
ShowRunROI();
}
6.创建模板
创建模板主入口
void CtuImageMatching::on_CreateModelAction_triggered()
{
if (MyModelCom[MyCurrentControl.ModelNum].EffectiveFlag == true)
{
if (0 != QMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("已经存在模板是否替换:模板%1?").arg(MyCurrentControl.ModelNum+1),QStringLiteral("确定"),QStringLiteral("取消")))
{
MyCurrentControl.ROITemp.GenEmptyObj();
return;
}
}
if (HObjectIsNull(MyCurrentControl.ho_Image) || HObjectIsNull(MyCurrentControl.ROITemp))
{
if (0 != QMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("无图或者无ROI"),QStringLiteral("确定"),QStringLiteral("取消")))
{
return;
}
}
//清空当前模板,相当于初始化
InitModel(MyCurrentControl.ModelNum, MyCurrentControl.ModelNum + 1); //删除当前模板
//数据保存
MyModelCom[MyCurrentControl.ModelNum].h_img = MyCurrentControl.ho_Image.Clone();
MyModelCom[MyCurrentControl.ModelNum].h_roi = MyCurrentControl.ROITemp.Clone();
MyModelCom[MyCurrentControl.ModelNum].TemplateAlgorithm = MyCurrentControl.FindModelFun;
MyModelCom[MyCurrentControl.ModelNum].modelNum = MyCurrentControl.ModelNum;
MyModelCom[MyCurrentControl.ModelNum].startAngle = ui.StartAngleBox->value();
MyModelCom[MyCurrentControl.ModelNum].endAngle = ui.AngleSizeBox->value();
MyModelCom[MyCurrentControl.ModelNum].Level = ui.AutoLeval_Check->isChecked()?-1: ui.LevalBox->value();
MyModelCom[MyCurrentControl.ModelNum].FindModelTimeOut = ui.FindModelTimeOut_Edit->text().toInt();
MyModelCom[MyCurrentControl.ModelNum].Score = ui.ScoreBox->value();
MyModelCom[MyCurrentControl.ModelNum].MatchNum = ui.MatchNum_Combo->currentIndex();
MyModelCom[MyCurrentControl.ModelNum].DeformationNum = ui.Def_ComBo->currentIndex();
bool Res = false;
if (MyCurrentControl.FindModelFun == 0)
Res = Create_ShapeModel();
else if (MyCurrentControl.FindModelFun == 1)
Res = Create_GrayModel();
else if (MyCurrentControl.FindModelFun == 2)
Res = Create_NCCModel();
else if (MyCurrentControl.FindModelFun == 3)
Res = Create_ChangeShapeModel();
else{}
if(Res ==false)
{
//模模板创建失败
InitModel(MyCurrentControl.ModelNum,MyCurrentControl.ModelNum+1);
MyCurrentControl.ROITemp.GenEmptyObj();
ui.statusBar->showMessage(QStringLiteral("模板创建失败!"));
return;
}
else
{
ui.statusBar->showMessage(QStringLiteral("模板创建成功!"));
}
WriteData(MyCurrentControl.ModelNum);
WriteImageROI(MyCurrentControl.ModelNum);
}
以灰度模板为例,创建基于灰度匹配的算法
bool CtuImageMatching::Create_GrayModel()
{
if (HObjectIsNull(MyModelCom[MyCurrentControl.ModelNum].h_img) || HObjectIsNull(MyModelCom[MyCurrentControl.ModelNum].h_roi))
return false;
HObject hv_ImageReduced;
HTuple hv_Orgin_Area;
HTuple hv_pi = HTuple(0.0).TupleAcos() * 2;
//裁减模板
ReduceDomain(MyModelCom[MyCurrentControl.ModelNum].h_img, MyModelCom[MyCurrentControl.ModelNum].h_roi, &hv_ImageReduced);
try{
CreateTemplateRot(hv_ImageReduced, 4, HTuple(MyModelCom[MyCurrentControl.ModelNum].startAngle).TupleRad(), HTuple(MyModelCom[MyCurrentControl.ModelNum].endAngle).TupleRad(), 0.0982, "sort", "original", &MyModelCom[MyCurrentControl.ModelNum].hv_ModelID);
}catch(...)
{
return false;
}
//清空显示
ClearWindow(MyCurrentControl.hv_WindowHandle);
DispObj(MyModelCom[MyCurrentControl.ModelNum].h_img,MyCurrentControl.hv_WindowHandle);
AreaCenter(MyModelCom[MyCurrentControl.ModelNum].h_roi, &hv_Orgin_Area, &MyModelCom[MyCurrentControl.ModelNum].hv_Orgin_Row, &MyModelCom[MyCurrentControl.ModelNum].hv_Orgin_Column);
SetColor(MyCurrentControl.hv_WindowHandle,"blue");
DispObj(MyModelCom[MyCurrentControl.ModelNum].h_roi,MyCurrentControl.hv_WindowHandle);
SetColor(MyCurrentControl.hv_WindowHandle,"green");
DispCross(MyCurrentControl.hv_WindowHandle, MyModelCom[MyCurrentControl.ModelNum].hv_Orgin_Row, MyModelCom[MyCurrentControl.ModelNum].hv_Orgin_Column, MyCurrentControl.ho_Width[0].I()/24, 0);
MyCurrentControl.ROITemp.GenEmptyObj();
MyModelCom[MyCurrentControl.ModelNum].EffectiveFlag = true;
return true;
}
7.查找模板结果
查找模板主入口
void CtuImageMatching::on_RunModelAction_triggered()
{
if(MyModelCom[MyCurrentControl.ModelNum].EffectiveFlag == false)
{
QMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("当前模板号无模板"),QStringLiteral("确定"));
return;
}
QVector<VisionPoint> EachRes;
if (MyModelCom[MyCurrentControl.ModelNum].TemplateAlgorithm == 0)
EachRes = FindModel_Shape(MyCurrentControl.ModelNum);
else if(MyModelCom[MyCurrentControl.ModelNum].TemplateAlgorithm == 1)
EachRes = FindModel_Gray(MyCurrentControl.ModelNum);
else if(MyModelCom[MyCurrentControl.ModelNum].TemplateAlgorithm == 2)
EachRes = FindModel_NCC(MyCurrentControl.ModelNum);
else if(MyModelCom[MyCurrentControl.ModelNum].TemplateAlgorithm == 3)
EachRes = FindModel_ChangeShape(MyCurrentControl.ModelNum);
else{}
if(EachRes.count() == 0)
{
ui.statusBar->showMessage(QStringLiteral("模板匹配失败!"));
}
else
{
VisionPoint p = EachRes.at(0);
ui.statusBar->showMessage(QString("%1,%2,%3:%4").arg(p.x).arg(p.y).arg(p.r).arg(p.score));
}
}
以灰度匹配为例,进行查找模板
QVector<VisionPoint> CtuImageMatching::FindModel_Gray(int ModelNum)
{
QVector<VisionPoint> pp;
if(HObjectIsNull(MyCurrentControl.ho_Image) || MyModelCom[ModelNum].hv_ModelID == -1)
return pp;
HTuple hv_RowCheck = NULL, hv_ColumnCheck = NULL, hv_AngleCheck = NULL, hv_Error = NULL;
HTuple hMat2D = NULL;
HObject ho_ImageAffinTrans;
double Score = MyModelCom[ModelNum].Score / 100.0;
HObject hv_img = MyCurrentControl.ho_Image;
if(MyModelCom[ModelNum].SearchROIFlag)
ReduceDomain(hv_img, MyModelCom[ModelNum].h_SearchROI, &hv_img);
BestMatchRotMg(hv_img, MyModelCom[ModelNum].hv_ModelID, HTuple(MyModelCom[ModelNum].startAngle).TupleRad(), HTuple(MyModelCom[ModelNum].endAngle).TupleRad(), 100 - Score, "true", 4, &hv_RowCheck, &hv_ColumnCheck, &hv_AngleCheck, &hv_Error);
if (int(hv_Error.TupleLength()[0].D()) > 0)
{
if (Score*100 > (100 - hv_Error[0].D()))
return pp;
if (MyModelCom[ModelNum].TargetFlag == true)
{
HTuple RowTrans = NULL, ColumnTrans = NULL;
VectorAngleToRigid(MyModelCom[ModelNum].hv_Orgin_Row, MyModelCom[ModelNum].hv_Orgin_Column, 0, hv_RowCheck[0].D(), hv_ColumnCheck[0].D(), hv_AngleCheck[0].D(), &hMat2D);
AffineTransPixel(hMat2D, MyModelCom[ModelNum].hv_Target_Row, MyModelCom[ModelNum].hv_Target_Column, &RowTrans, &ColumnTrans);
SetColor(MyCurrentControl.hv_WindowHandle,"green");
DispCross(MyCurrentControl.hv_WindowHandle, RowTrans[0].D(), ColumnTrans[0].D(), MyCurrentControl.ho_Width[0].I()/24, hv_AngleCheck[0].D());
AffineTransRegion(MyModelCom[ModelNum].h_roi, &ho_ImageAffinTrans, hMat2D, "constant");
SetColor(MyCurrentControl.hv_WindowHandle,"blue");
DispObj(ho_ImageAffinTrans,MyCurrentControl.hv_WindowHandle);
pp.append(GetPoint(RowTrans[0].D(), ColumnTrans[0].D(), hv_AngleCheck[0].D() * 57.3, 100 - hv_Error[0].D()));
}
else
{
SetColor(MyCurrentControl.hv_WindowHandle, "green");
DispCross(MyCurrentControl.hv_WindowHandle, hv_RowCheck[0].D(), hv_ColumnCheck[0].D(), MyCurrentControl.ho_Width[0].I()/24, hv_AngleCheck[0].D());
VectorAngleToRigid(MyModelCom[ModelNum].hv_Orgin_Row, MyModelCom[ModelNum].hv_Orgin_Column, 0, hv_RowCheck[0].D(), hv_ColumnCheck[0].D(), hv_AngleCheck[0].D(), &hMat2D);
AffineTransRegion(MyModelCom[ModelNum].h_roi, &ho_ImageAffinTrans, hMat2D, "constant");
SetColor(MyCurrentControl.hv_WindowHandle, "blue");
DispObj(ho_ImageAffinTrans,MyCurrentControl.hv_WindowHandle);
pp.append(GetPoint(hv_RowCheck[0].D(), hv_ColumnCheck[0].D(), hv_AngleCheck[0].D() * 57.3, 100 - hv_Error[0].D()));
}
}
//显示搜索区域
if (MyModelCom[ModelNum].SearchROIFlag)
{
SetColor(MyCurrentControl.hv_WindowHandle, "orange");
DispObj(MyModelCom[ModelNum].h_SearchROI,MyCurrentControl.hv_WindowHandle);
}
return pp;
}
8.读取条形码
这里的条形码可以理解为一维码:支持一维码类型
BarCodeType<<"2/5 Industrial"<<"2/5 Interleaved"<<"Codabar"<<"Code 39"<<"Code 32 (converted from Code 39)"<<"Code 93"<<"Code 128"<<"MSI"<<"PharmaCode"
<<""<<"EAN-8"<<"EAN-8 Add-On 2"<<"EAN-8 Add-On 5"<<"EAN-13"<<"EAN-13 Add-On 2"<<"EAN-13 Add-On 5"<<"UPC-A"<<"UPC-A Add-On 2"<<"UPC-A Add-On 5"<<"UPC-E"<<"UPC-E Add-On 2"<<"UPC-E Add-On 5"
<<""<<"GS1-128"<<"GS1 DataBar Omnidirectional"<<"GS1 DataBar Truncated"<<"GS1 DataBar Stacked"<<"GS1 DataBar Stacked Omnidirectional"<<"GS1 DataBar Limited"<<"GS1 DataBar Expanded"<<"GS1 DataBar Expanded Stacked"
<<""<<"auto";
QString CtuImageMatching::ReadBarCode()
{
if (HObjectIsNull(MyCurrentControl.ho_Image))
return "-1";
HTuple hv_BarCodeHandle = -1, hv_DecodedDataStrings = -1, hv_BarCodeResults1 = -1;
HObject ho_SymbolRegions;
HObject hv_img = MyCurrentControl.ho_Image;
if(MyCodeCom.BarCodeROIFlag)
ReduceDomain(hv_img, MyCodeCom.BarCodeROI, &hv_img);
try{
CreateBarCodeModel(HTuple(), HTuple(), &hv_BarCodeHandle);
SetBarCodeParam(hv_BarCodeHandle, "element_size_min", 1);
FindBarCode(hv_img, &ho_SymbolRegions, hv_BarCodeHandle, QStringToHTuple(BarCodeType[MyCurrentControl.CurrentBarCodeType]), &hv_DecodedDataStrings);
GetBarCodeResult(hv_BarCodeHandle, "all", "orientation", &hv_BarCodeResults1);
ClearBarCodeModel(hv_BarCodeHandle);
}catch(...)
{
return "-1";
}
if(MyCodeCom.BarCodeROIFlag)
{
SetColor(MyCurrentControl.hv_WindowHandle,"orange");
DispObj(MyCodeCom.BarCodeROI,MyCurrentControl.hv_WindowHandle);
}
SetColor(MyCurrentControl.hv_WindowHandle,"green");
DispObj(ho_SymbolRegions,MyCurrentControl.hv_WindowHandle);
QString Code = "";
int num = int(hv_DecodedDataStrings.TupleLength()[0].D());
for(int i=0;i<num;i++)
{
double Angle = hv_BarCodeResults1[0].D();
Code = Code + hv_DecodedDataStrings[i].S() + ":"+ QString::number(Angle) + " ";
}
窗口显示条码内容
//SetFont(MyCurrentControl.hv_WindowHandle, "-Courier New-40-*-*-*-*-1-");
//SetColor(MyCurrentControl.hv_WindowHandle,"green");
//SetTposition(MyCurrentControl.hv_WindowHandle, 0,0-(int)MyCurrentControl.setPartPosition);
//QString mes = QStringLiteral("Code: ") + Code;
//WriteString(MyCurrentControl.hv_WindowHandle,QStringToHTuple(mes));
if(Code == "")
Code = "-1";
return Code;
}
9.读取二维码
支持二维码的类型为:文章来源:https://www.toymoban.com/news/detail-821384.html
DataCodeType <<"QR Code"<<"Aztec Code"<<"Micro QR Code"<<"Data Matrix ECC 200"<<"GS1 Aztec Code"<<"GS1 DataMatrix"<<"GS1 QR Code"<<"PDF417";
QString CtuImageMatching::ReadQRCode()
{
if(HObjectIsNull(MyCurrentControl.ho_Image))
return "-1";
HObject hv_img = MyCurrentControl.ho_Image;
if(MyCodeCom.QRCodeROIFlag)
ReduceDomain(hv_img, MyCodeCom.QRCodeROI, &hv_img);
try
{
HObject ho_SymbolXLDs;
HTuple hv_DataCodeHandle, hv_ResultHandles, hv_DecodedDataStrings;
CreateDataCode2dModel(QStringToHTuple(DataCodeType[MyCurrentControl.CurrentDataCodeType]), HTuple(), HTuple(), &hv_DataCodeHandle);
FindDataCode2d(hv_img, &ho_SymbolXLDs, hv_DataCodeHandle, HTuple(), HTuple(), &hv_ResultHandles, &hv_DecodedDataStrings);
ClearDataCode2dModel(hv_DataCodeHandle);
if(MyCodeCom.QRCodeROIFlag)
{
SetColor(MyCurrentControl.hv_WindowHandle,"orange");
DispObj(MyCodeCom.QRCodeROI,MyCurrentControl.hv_WindowHandle);
}
SetColor(MyCurrentControl.hv_WindowHandle,"green");
DispObj(ho_SymbolXLDs,MyCurrentControl.hv_WindowHandle);
QString Code = "";
int num = int(hv_DecodedDataStrings.TupleLength()[0].D());
for(int i=0;i<num;i++)
{
Code = Code + hv_DecodedDataStrings[i].S() + " ";
}
if(Code == "")
Code = "-1";
return Code;
}
catch(...)
{
return "-1";
}
}
10.读取OCR
QString CtuImageMatching::ReadOCRCode()
{
if (HObjectIsNull(MyCurrentControl.ho_Image))
return "-1";
try{
HObject ho_Region2, ho_ConnectedRegions1,ho_SelectedRegions1,ho_SortedRegions;
HTuple hv_UsedThreshold2, hv_OCRHandle,hv_Class,hv_Confidence;
HObject hv_img = MyCurrentControl.ho_Image;
if(MyCodeCom.OCRCodeROIFlag)
ReduceDomain(hv_img, MyCodeCom.OCRCodeROI, &hv_img);
BinaryThreshold(hv_img, &ho_Region2, "max_separability", "dark", &hv_UsedThreshold2);
Connection(ho_Region2, &ho_ConnectedRegions1);
SelectShape(ho_ConnectedRegions1, &ho_SelectedRegions1, "area", "and", 150, 99999);
SortRegion(ho_SelectedRegions1, &ho_SortedRegions, "character", "true", "row");
ReadOcrClassMlp("./genicam/Industrial.omc", &hv_OCRHandle);
DoOcrMultiClassMlp(ho_SortedRegions, hv_img, hv_OCRHandle, &hv_Class, &hv_Confidence);
ClearOcrClassMlp(hv_OCRHandle);
if(MyCodeCom.OCRCodeROIFlag)
{
SetColor(MyCurrentControl.hv_WindowHandle,"orange");
DispObj(MyCodeCom.OCRCodeROI,MyCurrentControl.hv_WindowHandle);
}
int num = int(hv_Class.TupleLength()[0].D());
QString Code = "";
for(int i=0;i<num;i++)
{
Code = Code + hv_Class[i].S() +" ";
}
if(Code == "")
Code = "-1";
return Code;
}
catch(...)
{
return "-1";
}
}
总结
该工程篇幅比较多,不过具体的函数在文章中已经表标明,具体的查看源码使用。文章来源地址https://www.toymoban.com/news/detail-821384.html
到了这里,关于基于qt+halcon实现视觉定位模板匹配【附部分源码】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!