python tkinter做界面 SDK打开海康工业相机,callback取图,halcon显示
上次发那个没有界面 总是命令行用户体验也不好 也不方便自己调试,今天拙略的弄了个界面, 没心思说细节了 直接上程序 当然还有很多地方不完善 但已经可以正常取图了
# -- coding: utf-8 --
import os,sys,time,datetime,copy,inspect,random
import ctypes,msvcrt
import threading
import numpy as np
from ctypes import *
import cv2
sys.path.append("MvImport")
from MvCameraControl_class import *
import halcon as ha
user32=ctypes.windll.user32
import win32gui,win32con,win32api,win32process
point = win32api.GetCursorPos()# 获取当前鼠标【x y】坐标
def cmd(s="pause"):
os.system(s)
def open_window(width, height,row=0,column=0,father_window=0):
if os.name == 'nt':
ha.set_system('use_window_thread', 'true')
return ha.open_window(
row=row,
column=column,
width=width,
height=height,
father_window=father_window,
mode='visible',
machine=''
)
def ha_2_np(image):
before = time.time()
img=ha.himage_as_numpy_array(image)
after = time.time()
time_consuming=after-before
return time_consuming,img
def np__2_ha(img):
before = time.time()
image=ha.himage_from_numpy_array(img)
after = time.time()
time_consuming=after-before
return time_consuming,image
# 是否是Mono图像
def Is_mono_data(enGvspPixelType):
if PixelType_Gvsp_Mono8 == enGvspPixelType or PixelType_Gvsp_Mono10 == enGvspPixelType \
or PixelType_Gvsp_Mono10_Packed == enGvspPixelType or PixelType_Gvsp_Mono12 == enGvspPixelType \
or PixelType_Gvsp_Mono12_Packed == enGvspPixelType:
return True
else:
return False
# 是否是彩色图像
def Is_color_data(enGvspPixelType):
if PixelType_Gvsp_BayerGR8 == enGvspPixelType or PixelType_Gvsp_BayerRG8 == enGvspPixelType \
or PixelType_Gvsp_BayerGB8 == enGvspPixelType or PixelType_Gvsp_BayerBG8 == enGvspPixelType \
or PixelType_Gvsp_BayerGR10 == enGvspPixelType or PixelType_Gvsp_BayerRG10 == enGvspPixelType \
or PixelType_Gvsp_BayerGB10 == enGvspPixelType or PixelType_Gvsp_BayerBG10 == enGvspPixelType \
or PixelType_Gvsp_BayerGR12 == enGvspPixelType or PixelType_Gvsp_BayerRG12 == enGvspPixelType \
or PixelType_Gvsp_BayerGB12 == enGvspPixelType or PixelType_Gvsp_BayerBG12 == enGvspPixelType \
or PixelType_Gvsp_BayerGR10_Packed == enGvspPixelType or PixelType_Gvsp_BayerRG10_Packed == enGvspPixelType \
or PixelType_Gvsp_BayerGB10_Packed == enGvspPixelType or PixelType_Gvsp_BayerBG10_Packed == enGvspPixelType \
or PixelType_Gvsp_BayerGR12_Packed == enGvspPixelType or PixelType_Gvsp_BayerRG12_Packed == enGvspPixelType \
or PixelType_Gvsp_BayerGB12_Packed == enGvspPixelType or PixelType_Gvsp_BayerBG12_Packed == enGvspPixelType \
or PixelType_Gvsp_YUV422_Packed == enGvspPixelType or PixelType_Gvsp_YUV422_YUYV_Packed == enGvspPixelType:
return True
else:
return False
# Mono图像转为python数组
def Mono_numpy(data, nWidth, nHeight):
data_ = np.frombuffer(data, count=int(nWidth * nHeight), dtype=np.uint8, offset=0)
data_mono_arr = data_.reshape(nHeight, nWidth)
numArray = np.zeros([nHeight, nWidth, 1], "uint8")
numArray[:, :, 0] = data_mono_arr
return numArray
# 彩色图像转为python数组
def Color_numpy(data, nWidth, nHeight):
data_ = np.frombuffer(data, count=int(nWidth * nHeight * 3), dtype=np.uint8, offset=0)
data_r = data_[0:nWidth * nHeight * 3:3]
data_g = data_[1:nWidth * nHeight * 3:3]
data_b = data_[2:nWidth * nHeight * 3:3]
data_r_arr = data_r.reshape(nHeight, nWidth)
data_g_arr = data_g.reshape(nHeight, nWidth)
data_b_arr = data_b.reshape(nHeight, nWidth)
numArray = np.zeros([nHeight, nWidth, 3], "uint8")
numArray[:, :, 0] = data_r_arr
numArray[:, :, 1] = data_g_arr
numArray[:, :, 2] = data_b_arr
return numArray
def Write_image(file_out,img,f=".jpg"):
out = cv2.imencode(f, img) # 将图像编码到内存缓冲区中。
out[1].tofile(file_out) # 将数组中的数据以二进制格式写进文件
return 0
winfun_ctype = WINFUNCTYPE
stFrameInfo = POINTER(MV_FRAME_OUT_INFO_EX)
pData = POINTER(c_ubyte)
FrameInfoCallBack = winfun_ctype(None, pData, stFrameInfo, c_void_p)
def image_callback(pData, pFrameInfo, pUser):
r"""
[callback]
"""
stFrameInfo = cast(pFrameInfo, POINTER(MV_FRAME_OUT_INFO_EX)).contents
if stFrameInfo:
nWidth = stFrameInfo.nWidth
nHeight = stFrameInfo.nHeight
nFrameNum = stFrameInfo.nFrameNum
print(f" {nWidth} {nHeight} {nFrameNum}")
b = string_at(pData, nWidth * nHeight * 1)
nparr = np.frombuffer(b, np.uint8)
nparr = nparr.reshape(nHeight, nWidth, 1)
ty,img=np__2_ha(nparr)
ha.set_part(WindowHandle1,0,0,nHeight,nWidth)
ha.disp_obj(img, WindowHandle1);
#cv2.imshow(" dst ", nparr)
#cv2.waitKey(1)
CALL_BACK_FUN = FrameInfoCallBack(image_callback)
def 枚举相机():
# ch:枚举设备 | en:Enum device
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
if ret != 0:
print ("enum devices fail! ret[0x%x]" % ret)
#sys.exit()
if deviceList.nDeviceNum == 0:
print ("find no device!")
#sys.exit()
print ("find %d devices!" % deviceList.nDeviceNum)
for i in range(0, deviceList.nDeviceNum):
mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
print ("\ngige device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
if per == 0:
break
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8)
nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
print ("current ip: %d.%d.%d.%d\n" % (nip1, nip2, nip3, nip4))
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
print ("\nu3v device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
if per == 0:
break
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print ("user serial number: %s" % strSerialNumber)
def 探测网络最佳包大小():
# ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
nPacketSize = cam.MV_CC_GetOptimalPacketSize()
if int(nPacketSize) > 0:
ret = cam.MV_CC_SetIntValue("GevSCPSPacketSize",nPacketSize)
if ret != 0:
print ("Warning: Set Packet Size fail! ret[0x%x]" % ret)
else:
print ("Warning: Get Packet Size fail! ret[0x%x]" % nPacketSize)
r"""
"""
import os,sys,time
import tkinter as tk
from tkinter import messagebox
import win32api,win32con,win32gui
from ctypes import *
def cmd(s="pause"):os.system(s)
def p(s):print(s);return s
win = tk.Tk()
win.title("Tkinter内嵌VisionMaster:")
win.geometry('1600x1000')
win.config(background ="#ffffff")
winscrwidth=win.winfo_screenwidth()
winscrheight=win.winfo_screenheight()
try:
win.iconbitmap('logo.ico')
except:
pass
frame1width=800
frame1height=600
frame1 = tk.Frame(win,width=frame1width,height=frame1height,bg="#ff00ff")
frame1.pack()
frame1_ID=frame1.winfo_id()#获取这个frame1的id 他就是父窗口的句柄
r""" """
Width=1280/2
Height=1024/2
Width=frame1width
Height=frame1height
#frame1_ID=0 调试模式 窗口在外
WindowHandle1 =open_window(Width, Height,father_window=frame1_ID)#halcon窗口放在Frame1
r"""
"""
deviceList = MV_CC_DEVICE_INFO_LIST()
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
枚举相机()
#nConnectionNum = input("please input the number of the device to connect:")
nConnectionNum=0
if int(nConnectionNum) >= deviceList.nDeviceNum:
print ("intput error!")
#sys.exit()
cam = MvCamera()# ch:创建相机实例 | en:Creat Camera Object
# ch:选择设备并创建句柄 | en:Select device and create handle
stDeviceList = cast(deviceList.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents
ret = cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print ("create handle fail! ret[0x%x]" % ret)
sys.exit()
# ch:打开设备 | en:Open device
ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
print ("open device fail! ret[0x%x]" % ret)
sys.exit()
探测网络最佳包大小()
# 设置触发模式
cam.MV_CC_SetEnumValue("TriggerMode", 0)
# 设置曝光
exposureTime=130
cam.MV_CC_SetFloatValue("ExposureTime", float(exposureTime))
# 设置增益
gain=11
cam.MV_CC_SetFloatValue("Gain", float(gain))
#设置帧率
frameRate=1000
cam.MV_CC_SetFloatValue("AcquisitionFrameRate", float(frameRate))
#参数 采集控制 触发源 编码器控制 变频器控制
#参数 采集控制
cam.MV_CC_SetEnumValue("TriggerMode", 1)#触发模式:打开
cam.MV_CC_SetEnumValue("TriggerSource", 7)#触发线路Line0
cam.MV_CC_SetEnumValue("TriggerActivation", 0)#触发极性 上升沿
# ch:设置触发模式为off | en:Set trigger mode as off
#ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
#if ret != 0:
# print ("set trigger mode fail! ret[0x%x]" % ret)
# ch:注册抓图回调 | en:Register image callback
ret = cam.MV_CC_RegisterImageCallBackEx(CALL_BACK_FUN,None)
if ret != 0:
print ("register image callback fail! ret[0x%x]" % ret)
sys.exit()
# ch:开始取流 | en:Start grab image
ret = cam.MV_CC_StartGrabbing()
if ret != 0:
print ("start grabbing fail! ret[0x%x]" % ret)
sys.exit()
print ("press a key to stop grabbing.")
#msvcrt.getch()
def button_click_1():#按钮
#print ("click me!")
#messagebox.showinfo(title='系统提示', message='系统提示?')
cam.MV_CC_SetCommandValue("TriggerSoftware")
button = tk.Button(win,text="按钮",command=button_click_1)
button.pack()
button.config(text="软触发!")
def select_price_R(value):
#Rsend(f"SA0{value}#")
#print(value,"R")
exposureTime=value
cam.MV_CC_SetFloatValue("ExposureTime", float(exposureTime))
Scale1=tk.Scale(win,orient=tk.HORIZONTAL,
from_=100, #从0开始
to=1000, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=50, #指示刻度
label ='曝光设置' , #滑动条的标签:不写则不显示.
command=select_price_R)
Scale1.pack()
#Scale1.set(255)#初始位置100
def select_price_gain(value):
gain=value
cam.MV_CC_SetFloatValue("Gain", float(gain))
Scale1=tk.Scale(win,orient=tk.HORIZONTAL,
from_=0, #从0开始
to=12, #到255结束
resolution =1, #单步步长.
length =300, #控件长度
sliderlength= 20, #滑动块尺寸
tickinterval=1, #指示刻度
label ='增益设置' , #滑动条的标签:不写则不显示.
command=select_price_gain)
Scale1.pack()
#Scale1.set(255)#初始位置100
def QueryWindow():
if True:#messagebox.showwarning("窗口关闭?"):
ret = cam.MV_CC_StopGrabbing()# ch:停止取流 | en:Stop grab image
if ret != 0:
print ("stop grabbing fail! ret[0x%x]" % ret)
sys.exit()
# ch:关闭设备 | Close device
ret = cam.MV_CC_CloseDevice()
if ret != 0:
print ("close deivce fail! ret[0x%x]" % ret)
sys.exit()
# ch:销毁句柄 | Destroy handle
ret = cam.MV_CC_DestroyHandle()
if ret != 0:
print ("destroy handle fail! ret[0x%x]" % ret)
sys.exit()
win.destroy()#关闭窗体
win.protocol('WM_DELETE_WINDOW', QueryWindow)
win.mainloop()
if __name__ == "__main__":
pass
已经可以用了 界面啥都有,当然还有很多优化空间 那天心情好在去完善吧