前言
本文主要实现基于python做一个视觉定位识别的功能,halcon版本使用的是halcon12.0,调用halcon的dll来实现二次开发,下边从头开始设置。
编程环境:python3.8
pyqt5.15
halcon12.0
IDE: VisualStudio Code
演示视频
本次项目的效果视频:
基于python+pyqt+halcon实现多算法的模板匹配
一、项目文件目录讲解
1、Resources:文件夹存放的是图片路径,一些资源文件都放在这里
2、Calibration.py、Calibration.ui:这里是视觉功能里边的qt标定界面的ui文件以及转换为py的文件。
3、CameraSetting.py、CameraSetting.ui:这里是视觉功能里边的qt相机设置界面的ui文件以及转换为py的文件。
4、CtuImageMatching.py、CtuImageMatching.ui:这里是视觉功能里边的qt视觉软件的界面的ui文件以及转换为py的文件。
5、CtuImageMatching.qrc:Qt设计的资源文件
6、CtuImageMatchingqrc.py:Qt资源文件的转化为的py文件
7、Helper.py、Helper.ui:这里是视觉功能里边的qt帮助界面的ui文件以及转换为py的文件。
8、RobotVision.py:软件主事件功能,main函数的入口位置,整个视觉软件入口位置
备注:鉴于程序写的比较仓促,因此窗体事件与窗体写在一个文件里边,与窗体事件无关的写在了RobotVision.py中,这种思路不可取,因此如果要重新设计这个目录的时候,都需要用写事件的类继承窗体类,这样改窗体就不用和修改那么多。
二、Qt Designer设置ui界面
一下界面只需要用Qt Designer进行编辑即可,基本上不需要代码部分
0.qrc资源文件的设置
这里需要把Resources文件夹里边的资源文件添加进来。
1.CtuImageMatching.ui的设置
先上图,只需要按照这个来设置即可:
从主界面上可以看出,本视觉软件所具有的功能。
2.CameraSetting.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本相机设置具有的功能。
3.Calibration.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本标定设置具有的功能。
4.Helper.ui的设置
先上图,只需要按照这个来设置即可:
从界面上可以看出,本帮助界面具有的功能,这里暂时就一个QLabel用来放了个二维码。
三、使用命令把qt文件转成py文件
在CMD命令行中输入一下命令,这里直接上命令代码:
pyrcc5 -o CtuImageMatchingqrc.py CtuImageMatching.qrc
pyuic5 -o CtuImageMatching.py CtuImageMatching.ui
pyuic5 -o CameraSetting.py CameraSetting.ui
pyuic5 -o Calibration.py Calibration.ui
pyuic5 -o Helper.py Helper.ui
四、py文件解析
1.CtuImageMatching.py重要函数解析
首先在主界面,我这里先弄了一个管理整个流程的一个变量的类,变量的意义如代码块的解释
class CurrentControl:
def __init__(self):
self.setPartPosition = 0.0 # 图片在位置的左上角的位置,为了解决图像居中界面
self.ROIRunType = 0 # 目前软件选中的ROI的计算类型:并集、交集、差集、
self.ModelNum = 0 # 当前软件使用的模板号(定位的模板号)
self.FindModelFun = 0 # 当前软件选择的模板的算法
self.CurrentBarCodeType = 6 # 当前软件识别哪种二维码
self.CurrentDataCodeType = 0 # 当前软件识别哪种一维码
self.hv_WindowHandle = None # 当前现实图片的窗体
self.ho_Image = None #当前的图像变量
self.ROITemp = None # 绘制ROI的经过运算的变量
self.ho_Width = None # 图像的宽度
self.ho_Height = None # 图像的高度
定义模板的类型,这里是以一个模板单位做一个属性变量:
class ModelCom:
def __init__(self):
self.EffectiveFlag = False # 该模板是否有效
self.modelNum = -1 # 模板号
self.TemplateAlgorithm = -1 # 匹配算法
self.h_img = None # 创建模板原图
self.h_roi = None # 创建模板ROI
self.hv_ModelID = None # 模板匹配ID
self.ShapeModelRegions = None # 模板轮廓
self.hv_Orgin_Row = HTuple(-1) # 模板锚点的行
self.hv_Orgin_Column = HTuple(-1) # 模板锚点的列
self.hv_Target_Row = HTuple(-1) # 锚点的行
self.hv_Target_Column = HTuple(-1) # 锚点的列
self.TargetFlag = False # 设置锚点的标志
self.h_SearchROI = None # 搜索区域
self.SearchROIFlag = False # 拥有搜索区域的标志
self.startAngle = -90 #模板起始角度
self.endAngle = 180 #角度范围
self.Level = -1 #对比度
self.Score = 50 #模板分数
self.DeformationNum = 0 #允许变形
self.MatchNum = 1 #匹配个数
self.FindModelTimeOut = 1000 #匹配超时事件
定义识别一维码、二维码、ocr的变量属性
class CodeModel:
def __init__(self):
self.BarCodeROI = None # 条形码搜索区域
self.BarCodeROIFlag = False # 是否已经设置条形码搜索区域
self.QRCodeROI = None # 二维码搜索区域
self.QRCodeROIFlag = False # 是否已经设置了二维码搜索区域
self.OCRCodeROI = None # OCR的搜索区域
self.OCRCodeROIFlag = False # 是否设置了OCR搜索区域
2.CameraSetting.py重要函数解析
首先设立相机设置页的事件
def CameraInit(self):
self.Btn_SertchCarmer.clicked.connect(self.on_Btn_SertchCarmer) # 查找相机
self.Btn_ConnectCarmer.clicked.connect(self.on_Btn_ConnectCarmer) # 连接相机
self.Check_AutoExporeTimeOut.clicked.connect(self.on_Check_AutoExporeTimeOut) # 自动曝光
self.Slider_ExporeTime.valueChanged.connect(self.Slider_ExporeTime_valueChange) # 曝光滑块的事件
self.Slider_Gray.valueChanged.connect(self.Slider_Gray_valueChanged) # 增益滑块事件
self.Check_AutoBlanceWhite.clicked.connect(self.Check_AutoBlanceWhite_clicked) # 是否白平衡
self.Btn_ShowImage.clicked.connect(self.on_Btn_ShowImage) # 预览相机和停止预览按钮
self.Btn_GetImage.clicked.connect(self.Btn_GetImage_clicked) # 快照按钮
self.Lab_TenLine.clicked.connect(self.Lab_TenLine_clicked) # 显示的时候是否显示十字
self.Btn_SetROI.clicked.connect(self.Btn_SetROI_clicked) # 设置ROI,这里类似放大图像
self.HalconCameraInitTimer = QTimer(self.layoutWidget) # 预览图像的定时器
self.HalconCameraInitTimer.singleShot(100, self.InitHalconCamera)
self.workerTimer1 = QTimer(self.layoutWidget) # 十字显示的定时器
self.workerTimer1.timeout.connect(self.TenLine)
#线程
self.workerThread = PyThread()
self.workerThread.Set_ThreadSleep(0.1) # 预览图像的线程
self.workerThread.threadSignal.connect(self.GetImage)
初始化显示图像的halcon窗体
def InitHalconCamera(self):
try:
HOperatorSet.CloseWindow(self.hv_WindowHandle)
except Exception as e:
pass
HOperatorSet.SetWindowAttr(HTuple("background_color"), HTuple("black"))
winID = self.Lab_HShowWindow.winId()
self.hv_WindowHandle = HOperatorSet.OpenWindow(HTuple(0), HTuple(0), HTuple(self.Lab_HShowWindow.geometry().width()), HTuple(self.Lab_HShowWindow.geometry().height()), HTuple(winID), HTuple(""), HTuple(""), self.hv_WindowHandle)
HOperatorSet.SetColor(self.hv_WindowHandle, HTuple("red"))
HOperatorSet.SetDraw(self.hv_WindowHandle, HTuple("margin"))
HOperatorSet.SetLineWidth(self.hv_WindowHandle, HTuple(1))
查找相机函数
def on_Btn_SertchCarmer(self):
conf = configparser.ConfigParser()
conf.read(self.filePath + "\\DefaultSetting.ini")
cameraType = conf.get("CameraType","CameraInterface")
conf.clear()
deviceNames = "DirectShow"
if cameraType == "0":
deviceNames = "DirectShow"
elif cameraType == "1":
deviceNames = "GigEVision2"
elif cameraType == "2":
deviceNames = "GenICamTL"
else:
pass
Name = Query = Information = ValueList = info_BoardsList = hv_Length = None
HOperatorSet.InfoFramegrabber(HTuple(deviceNames),HTuple("device"),HTuple(Information),HTuple(ValueList))
hv_Length = HOperatorSet.TupleLength(ValueList,HTuple(hv_Length))
length1 = hv_Length[0].I
self.Com_CameraList.clear()
for i in range(0,length1):
strDevice = ValueList[i].S
if deviceNames != "DirectShow":
strDevice = re.findall(r'device:(.*?) ',strDevice)[0]
if strDevice == "":
strDevice = ValueList[i].S
if strDevice == "default":
break
fill_name = deviceNames.replace("\"","") + ":" + strDevice
self.Com_CameraList.addItem(fill_name)
print(fill_name)
连接相机函数
def OpenCamera(self):
Information = ValueList = None
str = self.Com_CameraList.currentText()
ColorZone = ""
try:
Driver = str.split(":")
if self.Com_ColorZone.count() <=0:
if Driver[0] == "DirectShow":
ColorZone = "gray"
else:
ColorZone = "default"
else:
ColorZone = self.Com_ColorZone.currentText()
HOperatorSet.InfoFramegrabber(HTuple(Driver[0]), HTuple("defaults"), HTuple(Information), HTuple(ValueList))
self.hv_AcqHandle = HOperatorSet.OpenFramegrabber(HTuple(Driver[0]), HTuple(ValueList[0].I), HTuple(ValueList[1].I), HTuple(ValueList[2].I), HTuple(ValueList[3].I), HTuple(ValueList[4].I), HTuple(ValueList[5].I), HTuple(ValueList[6].S), HTuple(ValueList[7].I), HTuple(ColorZone), HTuple(-1), HTuple(ValueList[10].S), HTuple(ValueList[11].S), HTuple(Driver[1]), HTuple(0), HTuple(ValueList[13].I), self.hv_AcqHandle)
print(self.hv_AcqHandle)
HOperatorSet.GrabImageStart(self.hv_AcqHandle, HTuple(-1))
self.ho_Image = HOperatorSet.GrabImageAsync(self.ho_Image, self.hv_AcqHandle, HTuple(-1))
HOperatorSet.GetImageSize(self.ho_Image, self.ho_Width, self.ho_Height)
HOperatorSet.SetPart(self.hv_WindowHandle, HTuple(0), HTuple(0), HTuple(self.ho_Height[0].I - 1), HTuple(self.ho_Width[0].I - 1))
self.GetCameraInfo(Driver[0])
self.OpenCarmerFlag = True
self.EnableCamera(self.OpenCarmerFlag)
return True
except Exception as e:
self.CloseCamera()
return False
获取已经连接相机的属性
def GetCameraInfo(self,driverName):
# 像素格式
try:
hv_Value = hv_Length = None
hv_Value = HOperatorSet.GetFramegrabberParam(self.hv_AcqHandle,HTuple("PixelFormat"),hv_Value)
print(hv_Value)
hv_Length = HOperatorSet.TupleLength(hv_Value, HTuple(hv_Length))
length = hv_Length[0].I
for i in range(0,length):
self.Com_PixFormat.addItem(hv_Value[i].S)
except Exception as e:
pass
#颜色空间
try:
if self.Com_ColorZone.count()<=0:
Information = ValueList = hv_Length = None
HOperatorSet.InfoFramegrabber(HTuple(driverName),HTuple("color_space"),Information,ValueList)
hv_Length = HOperatorSet.TupleLength(ValueList, HTuple(hv_Length))
length = hv_Length[0].I
for i in range(0,length):
self.Com_ColorZone.addItem(ValueList[i].S)
except Exception as e:
pass
#曝光时间
try:
hv_Value = None
if driverName == 'DirectShow':
self.Slider_ExporeTime.setMinimum(-13)
self.Slider_ExporeTime.setMaximum(-1)
self.Slider_ExporeTime.setValue(-1)
self.Lab_ExporeTimeOutValue.setText(str(self.Slider_ExporeTime.value()))
self.Check_AutoExporeTimeOut.setChecked(True)
self.Check_AutoExporeTimeOut.setEnabled(True)
self.Slider_ExporeTime.setEnabled(False)
HOperatorSet.SetFramegrabberParam(self.hv_AcqHandle, HTuple("exposure"), HTuple("auto"))
else:
hv_Value = HOperatorSet.GetFramegrabberParam(self.hv_AcqHandle, HTuple("ExposureTime"), hv_Value)
extime = hv_Value[0].D
self.Slider_ExporeTime.setMinimum(0)
self.Slider_ExporeTime.setMaximum(600000)
self.Slider_ExporeTime.setValue(extime)
self.Lab_ExporeTimeOutValue.setText(str(self.Slider_ExporeTime.value()))
self.Check_AutoExporeTimeOut.setChecked(False)
self.Check_AutoExporeTimeOut.setEnabled(False)
self.Slider_ExporeTime.setEnabled(True)
except Exception as e:
pass
#增益
try:
hv_Value = None
hv_Value = HOperatorSet.GetFramegrabberParam(self.hv_AcqHandle, HTuple("Gain"), hv_Value)
gain = hv_Value[0].D
self.Slider_Gray.setMinimum(0)
self.Slider_Gray.setMaximum(24)
self.Slider_Gray.setValue(gain)
self.Lab_GrayValue.setText(str(self.Slider_Gray.value()))
self.Slider_Gray.setEnabled(True)
except Exception as e:
pass
设置相机属性
#设置白平衡
def on_Check_AutoExporeTimeOut(self):
Driver = self.Com_CameraList.currentText().split(":")
if self.Check_AutoExporeTimeOut.isChecked():
if Driver[0] == "DirectShow":
self.Slider_ExporeTime.setEnabled(False)
try:
HOperatorSet.SetFramegrabberParam(self.hv_AcqHandle, HTuple("exposure"), HTuple("auto"))
except Exception as e:
pass
else:
self.Slider_ExporeTime.setEnabled(True)
# 设置相机曝光时间
def Slider_ExporeTime_valueChange(self,value):
Driver = self.Com_CameraList.currentText().split(":")
if self.Check_AutoExporeTimeOut.isChecked() == False:
exposure = self.Slider_ExporeTime.value()
self.Lab_ExporeTimeOutValue.setText(str(exposure))
try:
if Driver[0] == "DirectShow":
HOperatorSet.SetFramegrabberParam(self.hv_AcqHandle, HTuple("exposure"), HTuple(exposure))
else:
HOperatorSet.SetFramegrabberParam(self.hv_AcqHandle, HTuple("ExposureTime"), HTuple(exposure))
except Exception as e:
pass
# 设置增益
def Slider_Gray_valueChanged(self):
gain = self.Slider_Gray.value()
self.Lab_GrayValue.setText(str(gain))
try:
HOperatorSet.SetFramegrabberParam(self.hv_AcqHandle, HTuple("Gain"), HTuple(gain))
except Exception as e:
pass
显示图像
def GetImage(self):
if self.OpenCarmerFlag == True:
try:
self.ho_Image = HOperatorSet.GrabImageAsync(self.ho_Image, self.hv_AcqHandle, HTuple(-1))
HOperatorSet.DispObj(self.ho_Image, self.hv_WindowHandle)
self.workerThread.FinishFlag = False
except Exception as e:
pass
3.Calibration.py重要函数解析
这里主要是使用仿射变换实现坐标转换,比如像素坐标转机器人坐标,首先定义坐标变量的数据,目前只写了3点标定,
class CameraCalibrationPoint:
def __init__(self):
self.P1_Image_X = -1
self.P1_Image_Y = -1
self.P1_Robot_X = -1
self.P1_Robot_Y = -1
self.P2_Image_X = -1
self.P2_Image_Y = -1
self.P2_Robot_X = -1
self.P2_Robot_Y = -1
self.P3_Image_X = -1
self.P3_Image_Y = -1
self.P3_Robot_X = -1
self.P3_Robot_Y = -1
self.RobotHommatFlag = False # 是否保存了转换数据
self.RobotHommat = None # 转换矩阵
用到的事件绑定
def BindEvent(self):
self.CalibrationNum_ComBo.currentIndexChanged.connect(self.CalibrationNum_ComBo_currentIndexChanged) # 标定的工位号
self.Btn_SaveCalib.clicked.connect(self.Btn_SaveCalib_clicked) # 保存标定数据
self.pushButton_2.clicked.connect(self.pushButton_2_clicked) # 测试转换数据
标定数据保存
def AffineTran(self,CurrentNum):
concat = concat1 = concat2 = concat3 = None
try:
concat = HOperatorSet.TupleConcat(concat, HTuple(self.MyPoint[CurrentNum].P1_Image_X), concat)
concat1 = HOperatorSet.TupleConcat(concat1, HTuple(self.MyPoint[CurrentNum].P1_Image_Y), concat1)
concat2 = HOperatorSet.TupleConcat(concat2, HTuple(self.MyPoint[CurrentNum].P1_Robot_X), concat2)
concat3 = HOperatorSet.TupleConcat(concat3, HTuple(self.MyPoint[CurrentNum].P1_Robot_Y), concat3)
concat = HOperatorSet.TupleConcat(concat, HTuple(self.MyPoint[CurrentNum].P2_Image_X), concat)
concat1 = HOperatorSet.TupleConcat(concat1, HTuple(self.MyPoint[CurrentNum].P2_Image_Y), concat1)
concat2 = HOperatorSet.TupleConcat(concat2, HTuple(self.MyPoint[CurrentNum].P2_Robot_X), concat2)
concat3 = HOperatorSet.TupleConcat(concat3, HTuple(self.MyPoint[CurrentNum].P2_Robot_Y), concat3)
concat = HOperatorSet.TupleConcat(concat, HTuple(self.MyPoint[CurrentNum].P3_Image_X), concat)
concat1 = HOperatorSet.TupleConcat(concat1, HTuple(self.MyPoint[CurrentNum].P3_Image_Y), concat1)
concat2 = HOperatorSet.TupleConcat(concat2, HTuple(self.MyPoint[CurrentNum].P3_Robot_X), concat2)
concat3 = HOperatorSet.TupleConcat(concat3, HTuple(self.MyPoint[CurrentNum].P3_Robot_Y), concat3)
self.MyPoint[CurrentNum].RobotHommat = HOperatorSet.VectorToHomMat2d(concat,concat1,concat2,concat3,self.MyPoint[CurrentNum].RobotHommat)
self.MyPoint[CurrentNum].RobotHommatFlag = True
self.label_5.setText("OK")
except Exception as e:
self.MyPoint[CurrentNum].RobotHommatFlag = False
self.label_5.setText("NG")
测试转换坐标
def PixelToRobot(self,id,x,y):
if self.MyPoint[id].RobotHommatFlag == True:
try:
Qx = Qy = None
HOperatorSet.AffineTransPoint2d(self.MyPoint[id].RobotHommat,HTuple(float(x)),HTuple(float(y)),HTuple(Qx),HTuple(Qy))
return Qx[0].D,Qy[0].D
except:
return -1,-1
return -1,-1
4.Helper.py重要函数解析
这个文件比较简单,主要就显示一张图片而已
class Ui_Helper(object):
def setupUi(self, Helper):
Helper.setObjectName("Helper")
Helper.resize(439, 438)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(":/CtuImageMatching/Resources/37.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Helper.setWindowIcon(icon)
self.gridLayout = QtWidgets.QGridLayout(Helper)
self.gridLayout.setContentsMargins(11, 11, 11, 11)
self.gridLayout.setSpacing(6)
self.gridLayout.setObjectName("gridLayout")
self.label = QtWidgets.QLabel(Helper)
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap(":/CtuImageMatching/Resources/38.png"))
self.label.setScaledContents(True)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.retranslateUi(Helper)
QtCore.QMetaObject.connectSlotsByName(Helper)
def retranslateUi(self, Helper):
_translate = QtCore.QCoreApplication.translate
Helper.setWindowTitle(_translate("Helper", "联系我们:Tel:189xxxx2753"))
5.RobotVision.py主界面重要函数
此文件绑定的函数比较多,这里主要讲解重要函数
1.初始化函数
此方法主要是对整个软件的初始化部分,包括各个变量的初始化
def __init__(self, parent=None):
super(RobotVision, self).__init__(parent)
self.ui = Ui_CtuImageMatchingClass()
self.ui.setupUi(self)
self.BindEvent()
self.RootPath = os.getcwd()
self.FilePath = self.RootPath + "\\VisionModel"
try:
os.mkdir(self.FilePath)
except:
pass
fileIni = self.FilePath + "\\DefaultSetting.ini"
if os.path.exists(fileIni) == False:
conf = configparser.ConfigParser()
conf.add_section("CameraType")
conf.set("CameraType", "CameraInterface", "0")
with open(fileIni, 'w') as conffile:
conf.write(conffile)
self.CameraWindow = CameraMainWindow()
self.Camera = Ui_CameraSetting(self.FilePath)
self.Camera.setupUi(self.CameraWindow)
self.CalibWindow = CalibrationMainWindow()
self.Calib = Ui_Calibration(self.FilePath)
self.Calib.setupUi(self.CalibWindow)
self.MyHelperWindow = HelperMainWindow()
self.MyHelp = Ui_Helper()
self.MyHelp.setupUi(self.MyHelperWindow)
self.VisionFunCode = ""
HOperatorSet.SetSystem(HTuple("clip_region"),HTuple("false"))
self.ReadCodeROI()
self.ReadModel(0,self.ui.MaxModelNum)
self.VisionFunFlag = True
self.DrawFlag = False
2.halcon窗体初始化
这里主要初始化halcon窗体,是主页面的显示位置
def InitHalcon(self):
try:
HOperatorSet.CloseWindow(self.ui.MyCurrentControl.hv_WindowHandle)
except Exception as e:
pass
HOperatorSet.SetWindowAttr(HTuple("background_color"), HTuple("white"))
winID = self.ui.ImageLab.winId()
self.ui.MyCurrentControl.hv_WindowHandle = HOperatorSet.OpenWindow(HTuple(0), HTuple(0), HTuple(self.ui.ImageLab.geometry().width()), HTuple(self.ui.ImageLab.geometry().height()), HTuple(winID), HTuple(""), HTuple(""), self.ui.MyCurrentControl.hv_WindowHandle)
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("red"))
HOperatorSet.SetDraw(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("margin"))
HOperatorSet.SetLineWidth(self.ui.MyCurrentControl.hv_WindowHandle, HTuple(1))
self.GetImagePixelTimer = QTimer(self)
self.GetImagePixelTimer.timeout.connect(self.GetImagePixel)
self.GetImagePixelTimer.start(50)
# 线程
self.workerThreadGetMore = PyThread()
self.workerThreadGetMore.Set_ThreadSleep(0.1)
self.workerThreadGetMore.threadSignal.connect(self.GetMoreImage)
3.绘制ROI区域,例子分为绘制矩形
绘制矩形ROI
def on_Rectangle1Action(self):
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image):
return
hv_Row1 = None
hv_Column1 = None
hv_Row2 = None
hv_Column2 = None
ROITemp = None
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("red"))
HOperatorSet.DrawRectangle1(self.ui.MyCurrentControl.hv_WindowHandle, HTuple(hv_Row1), HTuple(hv_Column1), HTuple(hv_Row2), HTuple(hv_Column2))
ROITemp = HOperatorSet.GenRectangle1(ROITemp,hv_Row1,hv_Column1,hv_Row2,hv_Column2)
if self.HObjectIsNull(self.ui.MyCurrentControl.ROITemp) == True:
self.ui.MyCurrentControl.ROITemp = ROITemp
else:
self.RunROI(ROITemp)
self.ShowRunROI()
4.ROI运算逻辑
这里主要是ROI的运算规则:并集、交集、差集
def RunROI(self,ROIObj):
if self.ui.MyCurrentControl.ROIRunType == 0:
self.ui.MyCurrentControl.ROITemp = HOperatorSet.Union2(self.ui.MyCurrentControl.ROITemp,ROIObj,self.ui.MyCurrentControl.ROITemp)
return
if self.ui.MyCurrentControl.ROIRunType == 1:
self.ui.MyCurrentControl.ROITemp = HOperatorSet.Intersection(self.ui.MyCurrentControl.ROITemp, ROIObj, self.ui.MyCurrentControl.ROITemp)
return
if self.ui.MyCurrentControl.ROIRunType == 2:
self.ui.MyCurrentControl.ROITemp = HOperatorSet.Difference(self.ui.MyCurrentControl.ROITemp, ROIObj, self.ui.MyCurrentControl.ROITemp)
return
5.创建模板
这里是创建模板的函数,这里以创建灰度模板为例子
# 创建模板进入的主函数
def CreateModelAction_triggered(self):
if self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].EffectiveFlag:
if QMessageBox.information(self, '提示', '已经存在模板是否替换:模板'+str(self.ui.MyCurrentControl.ModelNum+1), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == 65536:
self.ui.MyCurrentControl.ROITemp = HOperatorSet.GenEmptyObj(self.ui.MyCurrentControl.ROITemp)
return
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image) or self.HObjectIsNull(self.ui.MyCurrentControl.ROITemp):
QMessageBox.information(self, '提示','无图或者无ROI', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
return
self.InitModel(self.ui.MyCurrentControl.ModelNum,self.ui.MyCurrentControl.ModelNum+1)
#把参数保存在内存中
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_img = self.ui.MyCurrentControl.ho_Image
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_roi = self.ui.MyCurrentControl.ROITemp
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].TemplateAlgorithm = self.ui.MyCurrentControl.FindModelFun
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].modelNum = self.ui.MyCurrentControl.ModelNum
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].startAngle = self.ui.StartAngleBox.value()
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].endAngle = self.ui.AngleSizeBox.value()
if self.ui.AutoLeval_Check.isChecked():
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].Level = -1
else:
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].Level = self.ui.LevalBox.value()
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].FindModelTimeOut = int(self.ui.FindModelTimeOut_Edit.text())
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].Score = self.ui.ScoreBox.value()
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].MatchNum = self.ui.MatchNum_Combo.currentIndex()
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].DeformationNum = self.ui.Def_ComBo.currentIndex()
Res = False
if self.ui.MyCurrentControl.FindModelFun == 0:
Res = self.Create_ShapeModel()
elif self.ui.MyCurrentControl.FindModelFun == 1:
Res = self.Create_GrayModel()
elif self.ui.MyCurrentControl.FindModelFun == 2:
Res = self.Create_NCCModel()
elif self.ui.MyCurrentControl.FindModelFun == 3:
Res = self.Create_ChangeShapeModel()
else:
pass
if Res == False:
self.InitModel(self.ui.MyCurrentControl.ModelNum,self.ui.MyCurrentControl.ModelNum + 1)
self.ui.MyCurrentControl.ROITemp = HOperatorSet.GenEmptyObj(self.ui.MyCurrentControl.ROITemp)
self.ui.statusBar.showMessage("模板创建失败!")
else:
self.ui.statusBar.showMessage("模板创建成功!")
self.WriteData(self.ui.MyCurrentControl.ModelNum)
self.WriteImageROI(self.ui.MyCurrentControl.ModelNum)
# 创建灰度模板
def Create_GrayModel(self):
if self.HObjectIsNull(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_img) or self.HObjectIsNull(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_roi):
return False
hv_ImageReduced = hv_Orgin_Area = None
hv_ImageReduced = HOperatorSet.ReduceDomain(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_img, self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_roi, hv_ImageReduced)
try:
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_ModelID = HOperatorSet.CreateTemplateRot(hv_ImageReduced,HTuple(4),HTuple(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].startAngle).TupleRad(), HTuple(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].endAngle).TupleRad(),HTuple(0.0982),HTuple("sort"),HTuple("original"),self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_ModelID)
except Exception as e:
return False
HOperatorSet.ClearWindow(self.ui.MyCurrentControl.hv_WindowHandle)
HOperatorSet.DispObj(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_img, self.ui.MyCurrentControl.hv_WindowHandle)
HOperatorSet.AreaCenter(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_roi, HTuple(hv_Orgin_Area),HTuple(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_Orgin_Row),HTuple(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_Orgin_Column))
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("blue"))
HOperatorSet.DispObj(self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].h_roi,self.ui.MyCurrentControl.hv_WindowHandle)
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("green"))
HOperatorSet.DispCross(self.ui.MyCurrentControl.hv_WindowHandle,self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_Orgin_Row,self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].hv_Orgin_Column,HTuple(self.ui.MyCurrentControl.ho_Width[0].I / 24), HTuple(0))
self.ui.MyCurrentControl.ROITemp = HOperatorSet.GenEmptyObj(self.ui.MyCurrentControl.ROITemp)
self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].EffectiveFlag = True
return True
6.查找模板,实现模板匹配
这里主要实现模板匹配,根据不同的算法实现不同的模板匹配结果
# 模板匹配的总入口
def RunModelAction_triggered(self):
if self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].EffectiveFlag == False:
if QMessageBox.information(self, '提示', '当前模板号无模板', QMessageBox.Yes) == 65536:
return
EachRes = []
if self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].TemplateAlgorithm == 0:
EachRes = self.FindModel_Shape(self.ui.MyCurrentControl.ModelNum)
elif self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].TemplateAlgorithm == 1:
EachRes = self.FindModel_Gray(self.ui.MyCurrentControl.ModelNum)
elif self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].TemplateAlgorithm == 2:
EachRes = self.FindModel_NCC(self.ui.MyCurrentControl.ModelNum)
elif self.ui.MyModelCom[self.ui.MyCurrentControl.ModelNum].TemplateAlgorithm == 3:
EachRes = self.FindModel_ChangeShape(self.ui.MyCurrentControl.ModelNum)
else:
pass
if len(EachRes) == 0:
self.ui.statusBar.showMessage("模板匹配失败!")
else:
self.ui.statusBar.showMessage(EachRes[0])
以灰度匹配为例
def FindModel_Gray(self,ModelNum):
pp = []
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image) or self.ui.MyModelCom[ModelNum].hv_ModelID is None:
return pp
hv_RowCheck = hv_ColumnCheck = hv_AngleCheck = hv_Error = hMat2D = ho_ImageAffinTrans = None
Score = self.ui.MyModelCom[ModelNum].Score / 100.0
hv_img = self.ui.MyCurrentControl.ho_Image
if self.ui.MyModelCom[ModelNum].SearchROIFlag:
hv_img = HOperatorSet.ReduceDomain(hv_img, self.ui.MyModelCom[ModelNum].h_SearchROI, hv_img)
try:
HOperatorSet.BestMatchRotMg(hv_img,self.ui.MyModelCom[ModelNum].hv_ModelID,HTuple(self.ui.MyModelCom[ModelNum].startAngle).TupleRad(), HTuple(self.ui.MyModelCom[ModelNum].endAngle).TupleRad(),HTuple(100-Score),HTuple("true"),HTuple(4),hv_RowCheck,hv_ColumnCheck,hv_AngleCheck,hv_Error)
except Exception as e:
return pp
try:
length = int(hv_Error.TupleLength())
if length>0:
if (Score*100) > (100-hv_Error[0].D):
return pp
if self.ui.MyModelCom[ModelNum].TargetFlag == True:
RowTrans = ColumnTrans = None
hMat2D = HOperatorSet.VectorAngleToRigid(self.ui.MyModelCom[ModelNum].hv_Orgin_Row, self.ui.MyModelCom[ModelNum].hv_Orgin_Column, HTuple(0), HTuple(hv_RowCheck[0].D), HTuple(hv_ColumnCheck[0].D), HTuple(hv_AngleCheck[0].D), hMat2D)
HOperatorSet.AffineTransPixel(hMat2D, self.ui.MyModelCom[ModelNum].hv_Target_Row, self.ui.MyModelCom[ModelNum].hv_Target_Column, RowTrans, ColumnTrans)
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("green"))
HOperatorSet.DispCross(self.ui.MyCurrentControl.hv_WindowHandle, HTuple(RowTrans[0].D), HTuple(ColumnTrans[0].D), HTuple(self.ui.MyCurrentControl.ho_Width[0].I / 24), HTuple(hv_AngleCheck[0].D))
ho_ImageAffinTrans = HOperatorSet.AffineTransRegion(self.ui.MyModelCom[ModelNum].h_roi, ho_ImageAffinTrans, hMat2D, HTuple("constant"))
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("blue"))
HOperatorSet.DispObj(ho_ImageAffinTrans, self.ui.MyCurrentControl.hv_WindowHandle)
pp.append(str(RowTrans[0].D) + "," + str(ColumnTrans[0].D) + "," + str(hv_AngleCheck[0].D * 57.3) + "," + str(100-hv_Error[0].D))
else:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("green"))
HOperatorSet.DispCross(self.ui.MyCurrentControl.hv_WindowHandle, HTuple(hv_RowCheck[0].D), HTuple(hv_ColumnCheck[0].D), HTuple(self.ui.MyCurrentControl.ho_Width[0].I / 24), HTuple(hv_AngleCheck[0].D))
hMat2D = HOperatorSet.VectorAngleToRigid(self.ui.MyModelCom[ModelNum].hv_Orgin_Row, self.ui.MyModelCom[ModelNum].hv_Orgin_Column, HTuple(0), HTuple(hv_RowCheck[0].D), HTuple(hv_ColumnCheck[0].D), HTuple(hv_AngleCheck[0].D), hMat2D)
ho_ImageAffinTrans = HOperatorSet.AffineTransRegion(self.ui.MyModelCom[ModelNum].h_roi, ho_ImageAffinTrans, hMat2D, HTuple("constant"))
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("blue"))
HOperatorSet.DispObj(ho_ImageAffinTrans, self.ui.MyCurrentControl.hv_WindowHandle)
pp.append(str(hv_RowCheck[0].D) + "," + str(hv_ColumnCheck[0].D) + "," + str(hv_AngleCheck[0].D * 57.3) + "," + str(100-hv_Error[0].D))
if self.ui.MyModelCom[ModelNum].SearchROIFlag == True:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("orange"))
HOperatorSet.DispObj(self.ui.MyModelCom[ModelNum].h_SearchROI,self.ui.MyCurrentControl.hv_WindowHandle)
except Exception as e:
pass
return pp
7.读取条形码
这里把重要函数读取条形码示例
def ReadBarCode(self):
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image):
return "Code:-1"
hv_BarCodeHandle = hv_DecodedDataStrings = hv_BarCodeResults1 = ho_SymbolRegions = hv_DecodedDataTypes = None
hv_img = self.ui.MyCurrentControl.ho_Image
if self.ui.MyCodeCom.BarCodeROIFlag == True:
hv_img = HOperatorSet.ReduceDomain(hv_img, self.ui.MyCodeCom.BarCodeROI, hv_img)
try:
hv_BarCodeHandle = HOperatorSet.CreateBarCodeModel(HTuple(),HTuple(),hv_BarCodeHandle)
HOperatorSet.SetBarCodeParam(hv_BarCodeHandle,HTuple("element_size_min"),HTuple(1))
HOperatorSet.FindBarCode(hv_img,ho_SymbolRegions,hv_BarCodeHandle,HTuple(self.ui.BarCodeType[self.ui.MyCurrentControl.CurrentBarCodeType]),hv_DecodedDataStrings)
hv_BarCodeResults1 = HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, HTuple("all"), HTuple("orientation"), hv_BarCodeResults1)
hv_DecodedDataTypes = HOperatorSet.GetBarCodeResult(hv_BarCodeHandle, HTuple("all"), HTuple("decoded_types"), hv_DecodedDataTypes)
HOperatorSet.ClearBarCodeModel(hv_BarCodeHandle)
except Exception as e:
return "Code:-1"
if self.ui.MyCodeCom.BarCodeROIFlag == True:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("orange"))
HOperatorSet.DispObj(self.ui.MyCodeCom.BarCodeROI, self.ui.MyCurrentControl.hv_WindowHandle)
length = int(hv_DecodedDataStrings.TupleLength())
if length > 0:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("green"))
HOperatorSet.DispObj(ho_SymbolRegions, self.ui.MyCurrentControl.hv_WindowHandle)
Angle = hv_BarCodeResults1[0].D
Code = hv_DecodedDataTypes[0].S + ":" + hv_DecodedDataStrings[0].S + "," + str(Angle)
return Code
else:
return "Code:-1"
8.读取二维码
这里把重要函数读取二维码示例
def ReadQRCode(self):
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image):
return "Code:-1"
ho_SymbolXLDs = hv_DataCodeHandle = hv_ResultHandles = hv_DecodedDataStrings = None
hv_img = self.ui.MyCurrentControl.ho_Image
if self.ui.MyCodeCom.QRCodeROIFlag == True:
hv_img = HOperatorSet.ReduceDomain(hv_img, self.ui.MyCodeCom.QRCodeROI, hv_img)
if self.ui.MyCodeCom.QRCodeROIFlag == True:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("orange"))
HOperatorSet.DispObj(self.ui.MyCodeCom.QRCodeROI, self.ui.MyCurrentControl.hv_WindowHandle)
try:
hv_DataCodeHandle = HOperatorSet.CreateDataCode2dModel(HTuple(self.ui.DataCodeType[self.ui.MyCurrentControl.CurrentDataCodeType]),HTuple(),HTuple(),hv_DataCodeHandle)
HOperatorSet.FindDataCode2d(hv_img,ho_SymbolXLDs,hv_DataCodeHandle,HTuple(), HTuple(),hv_ResultHandles,hv_DecodedDataStrings)
HOperatorSet.ClearDataCode2dModel(hv_DataCodeHandle)
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("green"))
HOperatorSet.DispObj(ho_SymbolXLDs, self.ui.MyCurrentControl.hv_WindowHandle)
length = int(hv_DecodedDataStrings.TupleLength())
if length > 0:
Code = self.ui.DataCodeType[self.ui.MyCurrentControl.CurrentDataCodeType] + ":" + hv_DecodedDataStrings[0].S
return Code
except Exception as e:
pass
return "Code:-1"
9.读取OCR
这里以基本的OCR进行实验
def ReadOCRCode(self):
if self.HObjectIsNull(self.ui.MyCurrentControl.ho_Image):
return "OCR:-1"
hv_img = self.ui.MyCurrentControl.ho_Image
if self.ui.MyCodeCom.OCRCodeROIFlag == True:
hv_img = HOperatorSet.ReduceDomain(hv_img, self.ui.MyCodeCom.OCRCodeROI, hv_img)
try:
ho_Region2 = ho_ConnectedRegions1 = ho_SelectedRegions1 = ho_SortedRegions = hv_UsedThreshold2 = hv_OCRHandle = hv_Class = hv_Confidence = None
HOperatorSet.BinaryThreshold(hv_img,ho_Region2,HTuple("max_separability"),HTuple("dark"),hv_UsedThreshold2)
ho_ConnectedRegions1 = HOperatorSet.Connection(ho_Region2,ho_ConnectedRegions1)
ho_SelectedRegions1 = HOperatorSet.SelectShape(ho_ConnectedRegions1,ho_SelectedRegions1,HTuple("area"),HTuple("and"),HTuple(150.0),HTuple(99999.0))
ho_SortedRegions = HOperatorSet.SortRegion(ho_SelectedRegions1,ho_SortedRegions,HTuple("character"),HTuple("true"),HTuple("row"))
hv_OCRHandle = HOperatorSet.ReadOcrClassMlp(HTuple(self.RootPath + "\\genicam\\Industrial.omc"),hv_OCRHandle)
HOperatorSet.DoOcrMultiClassMlp(ho_SortedRegions,hv_img,hv_OCRHandle,hv_Class,hv_Confidence)
HOperatorSet.ClearOcrClassMlp(hv_OCRHandle)
if self.ui.MyCodeCom.OCRCodeROIFlag == True:
HOperatorSet.SetColor(self.ui.MyCurrentControl.hv_WindowHandle, HTuple("orange"))
HOperatorSet.DispObj(self.ui.MyCodeCom.OCRCodeROI, self.ui.MyCurrentControl.hv_WindowHandle)
length = int(hv_Class.TupleLength())
if length > 0:
Code = "OCR:"
for i in range(0,length):
Code = Code + hv_Class[i].S
return Code
except Exception as e:
pass
return "OCR:-1"
10.基于python+pyqt的通信:Tcp的服务器及客户端
服务器:
class PyTcpServer(QtCore.QThread):
TcpServerRecvEvent = QtCore.pyqtSignal(str)
def __init__(self, parent = None):
super(PyTcpServer, self).__init__(parent)
self.tcpServer = None
self.tcpServerSocket = None
self.TcpServerListenFlag = False
def SetIp(self,ip):
self.IP = ip
def SetPort(self,port):
self.PORT = port
def startListen(self):
self.tcpServer = QTcpServer()
if not self.tcpServer.listen(QHostAddress(self.IP), int(self.PORT)): # QHostAddress.LocalHost
print(self.tcpServer.errorString())
return
self.tcpServer.newConnection.connect(self.TCPServerNewConnect)
self.TcpServerListenFlag = True
def DisListen(self):
self.TcpServerListenFlag = False
if self.tcpServer:
self.tcpServer.deleteLater()
self.tcpServer.close()
self.tcpServer = None
if self.tcpServerSocket:
self.tcpServerSocket.abort()
self.tcpServerSocket.close()
self.tcpServerSocket = None
def TCPServerNewConnect(self):
self.blockSize = 0
if self.tcpServerSocket:
self.tcpServerSocket.abort()
self.tcpServerSocket = self.tcpServer.nextPendingConnection()
self.tcpServerSocket.readyRead.connect(self.TCPServerReceiveMessage)
def TCPServerReceiveMessage(self):
buf = self.tcpServerSocket.readAll()
mes = str(buf, encoding='utf-8')
self.TcpServerRecvEvent.emit(mes)
def SendData(self,mes):
if self.tcpServerSocket:
input_s = mes
input_s = str(input_s).encode('utf-8')
self.tcpServerSocket.write(input_s)
else:
pass
客户端:
class PyTcpClient(QtCore.QThread):
TcpClientRecvEvent = QtCore.pyqtSignal(str)
def __init__(self, parent = None):
super(PyTcpClient, self).__init__(parent)
self.TcpClientSocket = None
TCPClientConnectFlag = False
def SetIp(self,ip):
self.IP = ip
def SetPort(self,port):
self.PORT = port
def ConnectServer(self):
self.TcpClientSocket = QTcpSocket()
self.TcpClientSocket.connectToHost(self.IP, self.PORT)
if self.TcpClientSocket.waitForConnected(3000) == False:
return False
self.TcpClientSocket.readyRead.connect(self.TCPClientReceiveMessage)
TCPClientConnectFlag = True
return True
def DisConnectedServer(self):
self.TcpClientSocket.abort()
self.TcpClientSocket.close()
self.TcpClientSocket = None
TCPClientConnectFlag = False
def TCPClientReceiveMessage(self):
buf = self.TcpClientSocket.readAll()
mes = str(buf, encoding='utf-8')
self.TcpClientRecvEvent.emit(mes)
def SendData(self,mes):
if self.TcpClientSocket:
input_s = mes
input_s = str(input_s).encode('utf-8')
self.TcpClientSocket.write(input_s)
else:
pass
总结
该工程篇幅比较多,不过具体的函数在文章中已经表标明,具体的查看源码使用。
python调用halcon只要理解了传参和出参,算子的调用基本无问题