基于qt+halcon实现视觉定位模板匹配【附部分源码】


前言

本文主要实现基于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.读取二维码

支持二维码的类型为:

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";
	}
}


总结

该工程篇幅比较多,不过具体的函数在文章中已经表标明,具体的查看源码使用。

  • 15
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
### 回答1: VS (Visual Studio) 和 QT(HALCON) 是两种不同的软件开发工具。 VS 是微软开发的集成开发环境,主要用于开发 Windows 操作系统和应用程序。它提供了一系列的工具和组件,例如代码编辑器、调试器、图形化界面设计工具等,使开发者能够方便地进行软件开发和调试。VS支持多种编程语言,如C++、C#等,可以满足不同开发需求。 QT(HALCON) 是一种跨平台的开发框架,主要用于开发图形化界面和多媒体应用。它提供了丰富的工具和组件,支持多种操作系统,如Windows、Linux、macOS等,使开发者能够轻松地开发不同平台的应用程序。QT还提供了Qt Creator集成开发环境,方便开发者进行代码编写和调试。 VS 和 QT 在应用开发方面有各自的优势。VS 在 Windows 平台上的开发经验丰富,支持多种编程语言,并提供了强大的调试功能,适用于开发各类 Windows 应用程序。而QT则提供了一整套的跨平台解决方案,开发者可以使用相同的代码在不同平台上进行开发,避免了重复编写代码的繁琐工作。 总而言之,VS 适用于主要在 Windows 平台进行开发的开发者,而QT 则适用于需要在多个平台上开发应用程序的开发者。开发者可以根据自己的需求选择适合的开发工具来进行应用开发。 ### 回答2: VS和Qt是两种不同的开发工具,分别用于不同的应用领域。 VS是微软开发的一款集成开发环境(IDE),主要用于Windows平台上的软件开发。它提供了丰富的功能和工具,可以用于开发各种类型的应用程序,包括桌面应用、Web应用、移动应用等。VS具有良好的集成能力,可以与其他微软产品(如.NET、Azure等)无缝连接,同时也支持多种编程语言(如C++、C#等)。 Qt是一种跨平台的应用程序开发框架,主要用于开发图形界面应用。它提供了丰富的UI组件和类库,可以简化用户界面开发的工作。Qt支持多种编程语言,包括C++、Python等,可以运行在多个操作系统上,如Windows、Linux、Mac等。Qt还提供了一系列的工具和功能,用于处理图像、网络、数据库等方面的开发。 Halcon是一种专业的机器视觉软件库,主要用于开发机器视觉应用。它提供了丰富的图像处理和分析算法,可以用于解决各种视觉相关的问题。Halcon具有良好的性能和稳定性,可以运行在多个平台上,并且支持多种编程语言。Halcon在工业自动化、品质控制、医学影像等领域得到广泛应用。 总结来说,VS适用于开发各种类型的应用程序,Qt适用于开发图形界面应用,而Halcon适用于开发机器视觉应用。在具体选择时,需要根据实际需求和开发环境来决定使用哪个工具。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的广东仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值