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

这篇具有很好参考价值的文章主要介绍了基于qt+halcon实现视觉定位模板匹配【附部分源码】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

本文主要实现基于qt5.3做一个视觉定位识别的功能,halcon版本使用的是halcon12.0,调用halcon的dll来实现二次开发,下边从头开始设置。
与前面的python版、MFC版、Qt版一样,可供不同的开发者进行学习使用。
编程环境:qt5.3
halcon12.0
IDE: VisualStudio 2010


演示视频

本次项目的效果视频:

基于qt调用halcon实现图像定位,模板匹配


一、项目文件目录讲解

qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
本解决方案有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界面详解

先上图,只需要按照这个来设置即可:
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
从主界面上可以看出,本视觉软件所具有的功能。

2.CameraSetting.ui的设置

先上图,只需要按照这个来设置即可:
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
从界面上可以看出,本相机设置具有的功能。

3.Calibration.ui的设置

先上图,只需要按照这个来设置即可:
qt视觉分析源码解析,机器视觉-halcon,qt,ui,计算机视觉
从界面上可以看出,本标定设置具有的功能。

4.Helper.ui的设置

先上图,只需要按照这个来设置即可:
qt视觉分析源码解析,机器视觉-halcon,qt,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";
	}
}


总结

该工程篇幅比较多,不过具体的函数在文章中已经表标明,具体的查看源码使用。文章来源地址https://www.toymoban.com/news/detail-821384.html

到了这里,关于基于qt+halcon实现视觉定位模板匹配【附部分源码】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Halcon基于形状的模板匹配

    基于形状的模板匹配,也称为基于边缘方向梯度的匹配,是一种最常用也最前沿的模板匹配算法。该算法以物体边缘的梯度相关性作为匹配标准,原理是提取ROI中的边缘特征,结合灰度信息创建模板,并根据模板的大小和清晰度的要求生成多层级的图像金字塔模型。接着在图

    2024年01月19日
    浏览(30)
  • Halcon基于形变的模板匹配

    形变分为两种,一种是基于目标局部的形变,另一种是由于透视关系而产生的形变。基于形变的模板匹配也是一种基于形状的匹配方法,但不同的是,其返回结果中不仅包括轻微形变的形状.形变的位置和参数,还有描述形变的参数,如旋转角度、缩放倍数等。 基于透视的形

    2024年01月19日
    浏览(33)
  • 【OpenCV入门】第九部分——模板匹配

    模板是被查找的图像。模板匹配是指查找模板在原始图像中的哪个位置的过程。 image: 原始图像 templ: 模板图像,尺寸必须小于或等于原始图像 method: 匹配的方法 mask: (可选)掩模,只有 cv2.TM_SQDIFF和 c2.TM_CCORR_NORMED 支持此参数,建议采用默认值 result: 计算得出的匹配结

    2024年02月09日
    浏览(25)
  • 机器视觉初步7:模板匹配专题

    今天端午,祝各位端午安康! 今天来说说模板匹配这个专题。 模板匹配(Template Matching)是一种图像处理技术,用于在一幅图像上查找与另一幅模板图像相同的区域。模板图像和待匹配图像的大小相同。模板匹配的目的是在待检测图像中找到与模板图像最匹配的区域。 在机

    2024年02月10日
    浏览(30)
  • 【传统视觉】模板匹配和卡尺圆检测

    模板匹配 粗定位 1、原理:模板匹配是指在当前图像A中匹配与图像B最相似的部分,那么A为输入图像,B为模板图像。 2、匹配方法:B在A上华东,逐个遍历所有像素完成匹配。 3、函数: 参数值 对应数值 解释 cv2.TM_SQDIFF 0 以方差为依据,进行匹配,result值为0表示匹配度最好,

    2024年02月15日
    浏览(27)
  • 【计算机视觉、关键点检测、特征提取和匹配】基于SIFT、PCA-SIFT和GLOH算法在不同图像之间建立特征对应关系,并实现点匹配算法和图像匹配(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、数据、文章

    2024年03月14日
    浏览(38)
  • 使用halcon实现3维点云物体与模型的匹配并显示差异

    一、读取3D模型文件,并采样生成对应的模板文件 二、一次读取3D的模型文件进行配准显示差异 三、效果展示 蓝色为模型相对于3D模板多出的部分 红色为模型相对于3D模板缺少的部分

    2024年02月16日
    浏览(24)
  • Qt + OpenCV + Halcon + QScintilla 实现Halcon的脚本引擎功能 (源码)

    在工业领域中,缺陷检测、目标计数等功能的应用,其过程基本都是见招拆招,没有一个具体的标准,把输入输出接口标准化,过程用脚本引擎代替就可以实现功能的标准模块。 输入输出接口采用Qt + OpenCV来实现,OpenCV需要将采集到的图片转为Halcon的图像接口用于脚本检测,

    2024年02月05日
    浏览(32)
  • 基于OpenCV的模板匹配算法探索与实践

    目录 一、模板匹配能够做什么? 二、六种模板匹配算法解析 1、平方差匹配法method=TM_SQDIFF 2、归一化平方差匹配法method=TM_SQDIFF_NORMED 3、相关匹配法method=TM_CCORR 4、归一化相关匹配法method=TM_ CCORR_NORMED 5、系数匹配法method=TM_CCOEFF 6、化相关系数匹配法 method=TM_CCOEFF_NORMED 三、模板

    2024年04月13日
    浏览(38)
  • 基于形状的模板匹配(Shape-Based)

    称为基于边缘方向梯度的匹配,是一种 最常用也是最前沿的模板匹配算法 以物体边缘的梯度相关性作为匹配标准 提取ROI中的边缘特征,结合灰度信息创建模板,并根据模板的大小和清晰度的要求生成多层级的图像金字塔模型 接着在图像金字塔层中自上而下逐层搜索模板图像

    2024年02月05日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包