win11 电脑 使用 python 连接USB 海康工业相机 运行示例程序 BasicDemo.py
1.下载海康的mvs客户端和mvs_sdk驱动
官网链接:
https://www.hikrobotics.com/cn/machinevision/service/download?module=0 下载这两个东西,然后安装
1.1 我的mvs安装在
F:\APP\haikang20230906\MVS
注意,这个文件夹中自带了一个BasicDemo.py程序
位置在:
F:\APP\haikang20230906\MVS\Development\Samples
我使用的是python语言,所以位置是
F:\APP\haikang20230906\MVS\Development\Samples\Python\BasicDemo
其他语言可以自己参考
1.2 我的MVS_SDK安装在默认的c盘
注意:一定用管理员权限安装,否则会出错
2.修改MvImport路径
修改F:\APP\haikang20230906\MVS\Development\Samples\Python\BasicDemo\BasicDemo.py第10行为自己安装的mvs的路径
sys.path.append("F:\\APP\\haikang20230906\\MVS\\Development\\Samples\\Python\\MvImport")
4.修改MvCamera.dll路径
F:\APP\haikang20230906\MVS\Development\Samples\Python\MvImport\MvCameraControl_class.py
第15行
MvCamCtrldll = WinDLL("C:\\Program Files (x86)\\Common Files\\MVS\\Runtime\\Win64_x64\\MvCameraControl.dll")
5.补全运行所需的库
使用conda创建一个新的环境
conda create -n hik python==3.8
conda activate hik
pip install numpy==1.18.0
pip install opencv-python
pip install pillow==9.0
#注意,使用pillow务必小于等于9.0,不然会报错
6.运行demo
cd APP\haikang20230906\MVS\Development\Samples\Python\BasicDemo
python BasicDemo.py
会弹出这个对话框
点击 enum devices获取设备
点击open device启动设备
点击start garbbing获取图像
7.添加两个按钮,连续捕捉图像
如果嫌麻烦,直接跳过7.1,7.2,看7.3的代码,替换两个文件,但是记得在basicdemo.py目录创建mp4文件夹
1.修改BasicDemo/BasicDemo.py文件:
在BasicDemo.py第182行左右,插入两个函数:
def MP4_Save():
global obj_cam_operation
obj_cam_operation.b_save_MP4 = True
def MP4_Stop():
global obj_cam_operation
obj_cam_operation.b_stop_MP4 = True
在260行附近,插入两个显示按钮的元素:
btn_Save_MP4 = tk.Button(window, text='Save as MP4', width=15, height=1, command=MP4_Save)
btn_Save_MP4.place(x=20, y=550)
btn_Stop_MP4 = tk.Button(window, text='Stop MP4', width=15, height=1, command=MP4_Stop)
btn_Stop_MP4.place(x=160, y=550)
2.修改BasicDemo/CamOperation_class.py文件
首先修改函数的初始化类的函数
要修改init里传入的参数和初始幅值变量
class CameraOperation():
#这里添加b_save_MP4=False,b_stop_MP4=False
def __init__(self,obj_cam,st_device_list,n_connect_num=0,b_open_device=False,b_start_grabbing = False,h_thread_handle=None,\
b_thread_closed=False,st_frame_info=None,b_exit=False,b_save_bmp=False,b_save_jpg=False,b_save_MP4=False,b_stop_MP4=False,buf_save_image=None,\
n_save_image_size=0,n_win_gui_id=0,frame_rate=0,exposure_time=0,gain=0):
self.obj_cam = obj_cam
self.st_device_list = st_device_list
self.n_connect_num = n_connect_num
self.b_open_device = b_open_device
self.b_start_grabbing = b_start_grabbing
self.b_thread_closed = b_thread_closed
self.st_frame_info = st_frame_info
self.b_exit = b_exit
self.b_save_bmp = b_save_bmp
self.b_save_jpg = b_save_jpg
self.b_save_MP4 = b_save_MP4 # 这里添加
self.b_stop_MP4 = b_stop_MP4 # 这里添加
self.buf_save_image = buf_save_image
self.h_thread_handle = h_thread_handle
self.n_win_gui_id = n_win_gui_id
self.n_save_image_size = n_save_image_size
self.b_thread_closed
self.frame_rate = frame_rate
self.exposure_time = exposure_time
self.gain = gain
然后在370行附近,插入这两个函数:
注意~!!!!
我的Save_MP4函数,存放的位置是BasicDemo.py同目录下的mp4文件夹,需要自己手动创建,否则图片会保存失败
def Save_MP4(self,buf_cache):
if(None == buf_cache):
return
self.buf_save_image = None
file_path = "./mp4/"+str(self.st_frame_info.nFrameNum) + ".jpg"
self.n_save_image_size = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3 + 2048
if self.buf_save_image is None:
self.buf_save_image = (c_ubyte * self.n_save_image_size)()
stParam = MV_SAVE_IMAGE_PARAM_EX()
stParam.enImageType = MV_Image_Jpeg; # ch:需要保存的图像类型 | en:Image format to save
stParam.enPixelType = self.st_frame_info.enPixelType # ch:相机对应的像素格式 | en:Camera pixel type
stParam.nWidth = self.st_frame_info.nWidth # ch:相机对应的宽 | en:Width
stParam.nHeight = self.st_frame_info.nHeight # ch:相机对应的高 | en:Height
stParam.nDataLen = self.st_frame_info.nFrameLen
stParam.pData = cast(buf_cache, POINTER(c_ubyte))
stParam.pImageBuffer= cast(byref(self.buf_save_image), POINTER(c_ubyte))
stParam.nBufferSize = self.n_save_image_size # ch:存储节点的大小 | en:Buffer node size
stParam.nJpgQuality = 80; # ch:jpg编码,仅在保存Jpg图像时有效。保存BMP时SDK内忽略该参数
return_code = self.obj_cam.MV_CC_SaveImageEx2(stParam)
if return_code != 0:
tkinter.messagebox.showerror('show error','save mp4 fail! ret = '+self.To_hex_str(return_code))
#xcb注释掉
# self.b_save_MP4 = False
return
file_open = open(file_path.encode('ascii'), 'wb+')
img_buff = (c_ubyte * stParam.nImageLen)()
try:
cdll.msvcrt.memcpy(byref(img_buff), stParam.pImageBuffer, stParam.nImageLen)
file_open.write(img_buff)
# self.b_save_MP4 = False
# tkinter.messagebox.showinfo('show info','save mp4 success!')
except:
# xcb注释掉
# self.b_save_MP4 = False
raise Exception("get one frame failed:%s" % e.message)
if None != img_buff:
del img_buff
if None != self.buf_save_image:
del self.buf_save_image
def Stop_MP4(self,):
self.b_save_MP4 = False
然后修改work_thred函数里
def Work_thread(self,root,panel):
XXXXXXXXXXXXXXXXXX
#大概第250行,添加两个if判断
if True == self.b_save_jpg:
self.Save_jpg(buf_cache) #ch:保存Jpg图片 | en:Save Jpg
if True == self.b_save_bmp:
self.Save_Bmp(buf_cache) #ch:保存Bmp图片 | en:Save Bmp
if True == self.b_save_MP4: # 这里是添加的
self.b_save_MP4 = True
self.Save_MP4(buf_cache)
if True == self.b_stop_MP4: # 这里是添加的
self.Stop_MP4()
self.b_stop_MP4 = False
然后就可以运行了,点击Save as MP4就开始在mp4文件夹保存图像,处理速度取决于你电脑的运行速度,点击stop暂停,如果保存视频,可以把图像合成视频(偷懒),或者自己再取imgbuff另外修改(正儿八经)
3.BasicDemo.py和CamOperation_class.py代码
BasicDemo.py
# -- coding: utf-8 --
import sys
from tkinter import *
from tkinter.messagebox import *
import _tkinter
import tkinter.messagebox
import tkinter as tk
import sys, os
from tkinter import ttk
sys.path.append("F:\\APP\\haikang20230906\\MVS\\Development\\Samples\\Python\\MvImport")
from MvCameraControl_class import *
from CamOperation_class import *
from PIL import Image,ImageTk
#获取选取设备信息的索引,通过[]之间的字符去解析
def TxtWrapBy(start_str, end, all):
start = all.find(start_str)
if start >= 0:
start += len(start_str)
end = all.find(end, start)
if end >= 0:
return all[start:end].strip()
#将返回的错误码转换为十六进制显示
def ToHexStr(num):
chaDic = {10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f'}
hexStr = ""
if num < 0:
num = num + 2**32
while num >= 16:
digit = num % 16
hexStr = chaDic.get(digit, str(digit)) + hexStr
num //= 16
hexStr = chaDic.get(num, str(num)) + hexStr
return hexStr
if __name__ == "__main__":
global deviceList
deviceList = MV_CC_DEVICE_INFO_LIST()
global tlayerType
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
global cam
cam = MvCamera()
global nSelCamIndex
nSelCamIndex = 0
global obj_cam_operation
obj_cam_operation = 0
global b_is_run
b_is_run = False
#界面设计代码
window = tk.Tk()
window.title('BasicDemo')
window.geometry('1150x650')
model_val = tk.StringVar()
global triggercheck_val
triggercheck_val = tk.IntVar()
page = Frame(window,height=400,width=60,relief=GROOVE,bd=5,borderwidth=4)
page.pack(expand=True, fill=BOTH)
panel = Label(page)
panel.place(x=190, y=10,height=600,width=1000)
#绑定下拉列表至设备信息索引
def xFunc(event):
global nSelCamIndex
nSelCamIndex = TxtWrapBy("[","]",device_list.get())
#ch:枚举相机 | en:enum devices
def enum_devices():
global deviceList
global obj_cam_operation
deviceList = MV_CC_DEVICE_INFO_LIST()
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
if ret != 0:
tkinter.messagebox.showerror('show error','enum devices fail! ret = '+ ToHexStr(ret))
if deviceList.nDeviceNum == 0:
tkinter.messagebox.showinfo('show info','find no device!')
print ("Find %d devices!" % deviceList.nDeviceNum)
devList = []
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)
chUserDefinedName = ""
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chUserDefinedName:
if 0 == per:
break
chUserDefinedName = chUserDefinedName + chr(per)
print ("device model name: %s" % chUserDefinedName)
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))
devList.append("["+str(i)+"]GigE: "+ chUserDefinedName +"("+ str(nip1)+"."+str(nip2)+"."+str(nip3)+"."+str(nip4) +")")
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
print ("\nu3v device: [%d]" % i)
chUserDefinedName = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chUserDefinedName:
if per == 0:
break
chUserDefinedName = chUserDefinedName + chr(per)
print ("device model name: %s" % chUserDefinedName)
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print ("user serial number: %s" % strSerialNumber)
devList.append("["+str(i)+"]USB: "+ chUserDefinedName +"(" + str(strSerialNumber) + ")")
device_list["value"] = devList
device_list.current(0)
#ch:打开相机 | en:open device
def open_device():
global deviceList
global nSelCamIndex
global obj_cam_operation
global b_is_run
if True == b_is_run:
tkinter.messagebox.showinfo('show info','Camera is Running!')
return
obj_cam_operation = CameraOperation(cam,deviceList,nSelCamIndex)
ret = obj_cam_operation.Open_device()
if 0!= ret:
b_is_run = False
else:
model_val.set('continuous')
b_is_run = True
# ch:开始取流 | en:Start grab image
def start_grabbing():
global obj_cam_operation
obj_cam_operation.Start_grabbing(window,panel)
# ch:停止取流 | en:Stop grab image
def stop_grabbing():
global obj_cam_operation
obj_cam_operation.Stop_grabbing()
# ch:关闭设备 | Close device
def close_device():
global b_is_run
global obj_cam_operation
obj_cam_operation.Close_device()
b_is_run = False
#清除文本框的数值
text_frame_rate.delete(1.0, tk.END)
text_exposure_time.delete(1.0, tk.END)
text_gain.delete(1.0, tk.END)
#ch:设置触发模式 | en:set trigger mode
def set_triggermode():
global obj_cam_operation
strMode = model_val.get()
obj_cam_operation.Set_trigger_mode(strMode)
#ch:设置触发命令 | en:set trigger software
def trigger_once():
global triggercheck_val
global obj_cam_operation
nCommand = triggercheck_val.get()
obj_cam_operation.Trigger_once(nCommand)
#ch:保存bmp图片 | en:save bmp image
def bmp_save():
global obj_cam_operation
obj_cam_operation.b_save_bmp = True
#ch:保存jpg图片 | en:save jpg image
def jpg_save():
global obj_cam_operation
obj_cam_operation.b_save_jpg = True
def MP4_Save():
global obj_cam_operation
obj_cam_operation.b_save_MP4 = True
def MP4_Stop():
global obj_cam_operation
obj_cam_operation.b_stop_MP4 = True
def get_parameter():
global obj_cam_operation
obj_cam_operation.Get_parameter()
text_frame_rate.delete(1.0, tk.END)
text_frame_rate.insert(1.0,obj_cam_operation.frame_rate)
text_exposure_time.delete(1.0, tk.END)
text_exposure_time.insert(1.0,obj_cam_operation.exposure_time)
text_gain.delete(1.0, tk.END)
text_gain.insert(1.0, obj_cam_operation.gain)
def set_parameter():
global obj_cam_operation
obj_cam_operation.exposure_time = text_exposure_time.get(1.0,tk.END)
obj_cam_operation.exposure_time = obj_cam_operation.exposure_time.rstrip("\n")
obj_cam_operation.gain = text_gain.get(1.0,tk.END)
obj_cam_operation.gain = obj_cam_operation.gain.rstrip("\n")
obj_cam_operation.frame_rate = text_frame_rate.get(1.0,tk.END)
obj_cam_operation.frame_rate = obj_cam_operation.frame_rate.rstrip("\n")
obj_cam_operation.Set_parameter(obj_cam_operation.frame_rate,obj_cam_operation.exposure_time,obj_cam_operation.gain)
xVariable = tkinter.StringVar()
device_list = ttk.Combobox(window, textvariable=xVariable,width=30)
device_list.place(x=20, y=20)
device_list.bind("<<ComboboxSelected>>", xFunc)
label_exposure_time = tk.Label(window, text='Exposure Time',width=15, height=1)
label_exposure_time.place(x=20, y=350)
text_exposure_time = tk.Text(window,width=15, height=1)
text_exposure_time.place(x=160, y=350)
label_gain = tk.Label(window, text='Gain', width=15, height=1)
label_gain.place(x=20, y=400)
text_gain = tk.Text(window,width=15, height=1)
text_gain.place(x=160, y=400)
label_frame_rate = tk.Label(window, text='Frame Rate', width=15, height=1)
label_frame_rate.place(x=20, y=450)
text_frame_rate = tk.Text(window,width=15, height=1)
text_frame_rate.place(x=160, y=450)
btn_enum_devices = tk.Button(window, text='Enum Devices', width=35, height=1, command = enum_devices )
btn_enum_devices.place(x=20, y=50)
btn_open_device = tk.Button(window, text='Open Device', width=15, height=1, command = open_device)
btn_open_device.place(x=20, y=100)
btn_close_device = tk.Button(window, text='Close Device', width=15, height=1, command = close_device)
btn_close_device.place(x=160, y=100)
radio_continuous = tk.Radiobutton(window, text='Continuous',variable=model_val, value='continuous',width=15, height=1,command=set_triggermode)
radio_continuous.place(x=20,y=150)
radio_trigger = tk.Radiobutton(window, text='Trigger Mode',variable=model_val, value='triggermode',width=15, height=1,command=set_triggermode)
radio_trigger.place(x=160,y=150)
model_val.set(1)
btn_start_grabbing = tk.Button(window, text='Start Grabbing', width=15, height=1, command = start_grabbing )
btn_start_grabbing.place(x=20, y=200)
btn_stop_grabbing = tk.Button(window, text='Stop Grabbing', width=15, height=1, command = stop_grabbing)
btn_stop_grabbing.place(x=160, y=200)
checkbtn_trigger_software = tk.Checkbutton(window, text='Tigger by Software', variable=triggercheck_val, onvalue=1, offvalue=0)
checkbtn_trigger_software.place(x=20,y=250)
btn_trigger_once = tk.Button(window, text='Trigger Once', width=15, height=1, command = trigger_once)
btn_trigger_once.place(x=160, y=250)
btn_save_bmp = tk.Button(window, text='Save as BMP', width=15, height=1, command = bmp_save )
btn_save_bmp.place(x=20, y=300)
btn_save_jpg = tk.Button(window, text='Save as JPG', width=15, height=1, command = jpg_save)
btn_save_jpg.place(x=160, y=300)
btn_get_parameter = tk.Button(window, text='Get Parameter', width=15, height=1, command = get_parameter)
btn_get_parameter.place(x=20, y=500)
btn_set_parameter = tk.Button(window, text='Set Parameter', width=15, height=1, command = set_parameter)
btn_set_parameter.place(x=160, y=500)
btn_Save_MP4 = tk.Button(window, text='Save as MP4', width=15, height=1, command=MP4_Save)
btn_Save_MP4.place(x=20, y=550)
btn_Stop_MP4 = tk.Button(window, text='Stop MP4', width=15, height=1, command=MP4_Stop)
btn_Stop_MP4.place(x=160, y=550)
window.mainloop()
CamOperation_class.py
# -- coding: utf-8 --
import sys
import threading
import msvcrt
import _tkinter
import tkinter.messagebox
from tkinter import *
from tkinter.messagebox import *
import tkinter as tk
import numpy as np
import cv2
import time
import sys, os
import datetime
import inspect
import ctypes
import random
from PIL import Image,ImageTk
from ctypes import *
from tkinter import ttk
sys.path.append("../MvImport")
from MvCameraControl_class import *
def Async_raise(tid, exctype):
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
def Stop_thread(thread):
Async_raise(thread.ident, SystemExit)
class CameraOperation():
def __init__(self,obj_cam,st_device_list,n_connect_num=0,b_open_device=False,b_start_grabbing = False,h_thread_handle=None,\
b_thread_closed=False,st_frame_info=None,b_exit=False,b_save_bmp=False,b_save_jpg=False,b_save_MP4=False,b_stop_MP4=False,buf_save_image=None,\
n_save_image_size=0,n_win_gui_id=0,frame_rate=0,exposure_time=0,gain=0):
self.obj_cam = obj_cam
self.st_device_list = st_device_list
self.n_connect_num = n_connect_num
self.b_open_device = b_open_device
self.b_start_grabbing = b_start_grabbing
self.b_thread_closed = b_thread_closed
self.st_frame_info = st_frame_info
self.b_exit = b_exit
self.b_save_bmp = b_save_bmp
self.b_save_jpg = b_save_jpg
self.b_save_MP4 = b_save_MP4
self.b_stop_MP4 = b_stop_MP4
self.buf_save_image = buf_save_image
self.h_thread_handle = h_thread_handle
self.n_win_gui_id = n_win_gui_id
self.n_save_image_size = n_save_image_size
self.b_thread_closed
self.frame_rate = frame_rate
self.exposure_time = exposure_time
self.gain = gain
def To_hex_str(self,num):
chaDic = {10: 'a', 11: 'b', 12: 'c', 13: 'd', 14: 'e', 15: 'f'}
hexStr = ""
if num < 0:
num = num + 2**32
while num >= 16:
digit = num % 16
hexStr = chaDic.get(digit, str(digit)) + hexStr
num //= 16
hexStr = chaDic.get(num, str(num)) + hexStr
return hexStr
def Open_device(self):
if False == self.b_open_device:
# ch:选择设备并创建句柄 | en:Select device and create handle
nConnectionNum = int(self.n_connect_num)
stDeviceList = cast(self.st_device_list.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents
self.obj_cam = MvCamera()
ret = self.obj_cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
self.obj_cam.MV_CC_DestroyHandle()
tkinter.messagebox.showerror('show error','create handle fail! ret = '+ self.To_hex_str(ret))
return ret
ret = self.obj_cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
tkinter.messagebox.showerror('show error','open device fail! ret = '+ self.To_hex_str(ret))
return ret
print ("open device successfully!")
self.b_open_device = True
self.b_thread_closed = False
# ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
nPacketSize = self.obj_cam.MV_CC_GetOptimalPacketSize()
if int(nPacketSize) > 0:
ret = self.obj_cam.MV_CC_SetIntValue("GevSCPSPacketSize",nPacketSize)
if ret != 0:
print ("warning: set packet size fail! ret[0x%x]" % ret)
else:
print ("warning: set packet size fail! ret[0x%x]" % nPacketSize)
stBool = c_bool(False)
ret =self.obj_cam.MV_CC_GetBoolValue("AcquisitionFrameRateEnable", stBool)
if ret != 0:
print ("get acquisition frame rate enable fail! ret[0x%x]" % ret)
# ch:设置触发模式为off | en:Set trigger mode as off
ret = self.obj_cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
if ret != 0:
print ("set trigger mode fail! ret[0x%x]" % ret)
return 0
def Start_grabbing(self,root,panel):
if False == self.b_start_grabbing and True == self.b_open_device:
self.b_exit = False
ret = self.obj_cam.MV_CC_StartGrabbing()
if ret != 0:
tkinter.messagebox.showerror('show error','start grabbing fail! ret = '+ self.To_hex_str(ret))
return
self.b_start_grabbing = True
print ("start grabbing successfully!")
try:
self.n_win_gui_id = random.randint(1,10000)
self.h_thread_handle = threading.Thread(target=CameraOperation.Work_thread, args=(self,root,panel))
self.h_thread_handle.start()
self.b_thread_closed = True
except:
tkinter.messagebox.showerror('show error','error: unable to start thread')
False == self.b_start_grabbing
def Stop_grabbing(self):
if True == self.b_start_grabbing and self.b_open_device == True:
#退出线程
if True == self.b_thread_closed:
Stop_thread(self.h_thread_handle)
self.b_thread_closed = False
ret = self.obj_cam.MV_CC_StopGrabbing()
if ret != 0:
tkinter.messagebox.showerror('show error','stop grabbing fail! ret = '+self.To_hex_str(ret))
return
print ("stop grabbing successfully!")
self.b_start_grabbing = False
self.b_exit = True
def Close_device(self):
if True == self.b_open_device:
#退出线程
if True == self.b_thread_closed:
Stop_thread(self.h_thread_handle)
self.b_thread_closed = False
ret = self.obj_cam.MV_CC_CloseDevice()
if ret != 0:
tkinter.messagebox.showerror('show error','close deivce fail! ret = '+self.To_hex_str(ret))
return
# ch:销毁句柄 | Destroy handle
self.obj_cam.MV_CC_DestroyHandle()
self.b_open_device = False
self.b_start_grabbing = False
self.b_exit = True
print ("close device successfully!")
def Set_trigger_mode(self,strMode):
if True == self.b_open_device:
if "continuous" == strMode:
ret = self.obj_cam.MV_CC_SetEnumValue("TriggerMode",0)
if ret != 0:
tkinter.messagebox.showerror('show error','set triggermode fail! ret = '+self.To_hex_str(ret))
if "triggermode" == strMode:
ret = self.obj_cam.MV_CC_SetEnumValue("TriggerMode",1)
if ret != 0:
tkinter.messagebox.showerror('show error','set triggermode fail! ret = '+self.To_hex_str(ret))
ret = self.obj_cam.MV_CC_SetEnumValue("TriggerSource",7)
if ret != 0:
tkinter.messagebox.showerror('show error','set triggersource fail! ret = '+self.To_hex_str(ret))
def Trigger_once(self,nCommand):
if True == self.b_open_device:
if 1 == nCommand:
ret = self.obj_cam.MV_CC_SetCommandValue("TriggerSoftware")
if ret != 0:
tkinter.messagebox.showerror('show error','set triggersoftware fail! ret = '+self.To_hex_str(ret))
def Get_parameter(self):
if True == self.b_open_device:
stFloatParam_FrameRate = MVCC_FLOATVALUE()
memset(byref(stFloatParam_FrameRate), 0, sizeof(MVCC_FLOATVALUE))
stFloatParam_exposureTime = MVCC_FLOATVALUE()
memset(byref(stFloatParam_exposureTime), 0, sizeof(MVCC_FLOATVALUE))
stFloatParam_gain = MVCC_FLOATVALUE()
memset(byref(stFloatParam_gain), 0, sizeof(MVCC_FLOATVALUE))
ret = self.obj_cam.MV_CC_GetFloatValue("AcquisitionFrameRate", stFloatParam_FrameRate)
if ret != 0:
tkinter.messagebox.showerror('show error','get acquistion frame rate fail! ret = '+self.To_hex_str(ret))
self.frame_rate = stFloatParam_FrameRate.fCurValue
ret = self.obj_cam.MV_CC_GetFloatValue("ExposureTime", stFloatParam_exposureTime)
if ret != 0:
tkinter.messagebox.showerror('show error','get exposure time fail! ret = '+self.To_hex_str(ret))
self.exposure_time = stFloatParam_exposureTime.fCurValue
ret = self.obj_cam.MV_CC_GetFloatValue("Gain", stFloatParam_gain)
if ret != 0:
tkinter.messagebox.showerror('show error','get gain fail! ret = '+self.To_hex_str(ret))
self.gain = stFloatParam_gain.fCurValue
tkinter.messagebox.showinfo('show info','get parameter success!')
def Set_parameter(self,frameRate,exposureTime,gain):
if '' == frameRate or '' == exposureTime or '' == gain:
tkinter.messagebox.showinfo('show info','please type in the text box !')
return
if True == self.b_open_device:
ret = self.obj_cam.MV_CC_SetFloatValue("ExposureTime",float(exposureTime))
if ret != 0:
tkinter.messagebox.showerror('show error','set exposure time fail! ret = '+self.To_hex_str(ret))
ret = self.obj_cam.MV_CC_SetFloatValue("Gain",float(gain))
if ret != 0:
tkinter.messagebox.showerror('show error','set gain fail! ret = '+self.To_hex_str(ret))
ret = self.obj_cam.MV_CC_SetFloatValue("AcquisitionFrameRate",float(frameRate))
if ret != 0:
tkinter.messagebox.showerror('show error','set acquistion frame rate fail! ret = '+self.To_hex_str(ret))
tkinter.messagebox.showinfo('show info','set parameter success!')
def Work_thread(self,root,panel):
stOutFrame = MV_FRAME_OUT()
img_buff = None
buf_cache = None
numArray = None
while True:
ret = self.obj_cam.MV_CC_GetImageBuffer(stOutFrame, 1000)
if 0 == ret:
if None == buf_cache:
buf_cache = (c_ubyte * stOutFrame.stFrameInfo.nFrameLen)()
#获取到图像的时间开始节点获取到图像的时间开始节点
self.st_frame_info = stOutFrame.stFrameInfo
cdll.msvcrt.memcpy(byref(buf_cache), stOutFrame.pBufAddr, self.st_frame_info.nFrameLen)
print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (self.st_frame_info.nWidth, self.st_frame_info.nHeight, self.st_frame_info.nFrameNum))
self.n_save_image_size = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3 + 2048
if img_buff is None:
img_buff = (c_ubyte * self.n_save_image_size)()
if True == self.b_save_jpg:
self.Save_jpg(buf_cache) #ch:保存Jpg图片 | en:Save Jpg
if True == self.b_save_bmp:
self.Save_Bmp(buf_cache) #ch:保存Bmp图片 | en:Save Bmp
if True == self.b_save_MP4:
self.b_save_MP4 = True
self.Save_MP4(buf_cache)
if True == self.b_stop_MP4:
self.Stop_MP4()
self.b_stop_MP4 = False
else:
print("no data, nret = "+self.To_hex_str(ret))
continue
#转换像素结构体赋值
stConvertParam = MV_CC_PIXEL_CONVERT_PARAM()
memset(byref(stConvertParam), 0, sizeof(stConvertParam))
stConvertParam.nWidth = self.st_frame_info.nWidth
stConvertParam.nHeight = self.st_frame_info.nHeight
stConvertParam.pSrcData = cast(buf_cache, POINTER(c_ubyte))
stConvertParam.nSrcDataLen = self.st_frame_info.nFrameLen
stConvertParam.enSrcPixelType = self.st_frame_info.enPixelType
mode = None # array转为Image图像的转换模式
# RGB8直接显示
if PixelType_Gvsp_RGB8_Packed == self.st_frame_info.enPixelType :
numArray = CameraOperation.Color_numpy(self,buf_cache,self.st_frame_info.nWidth,self.st_frame_info.nHeight)
mode = "RGB"
# Mono8直接显示
elif PixelType_Gvsp_Mono8 == self.st_frame_info.enPixelType :
numArray = CameraOperation.Mono_numpy(self,buf_cache,self.st_frame_info.nWidth,self.st_frame_info.nHeight)
mode = "L"
# 如果是彩色且非RGB则转为RGB后显示
elif self.Is_color_data(self.st_frame_info.enPixelType):
nConvertSize = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3
stConvertParam.enDstPixelType = PixelType_Gvsp_RGB8_Packed
stConvertParam.pDstBuffer = (c_ubyte * nConvertSize)()
stConvertParam.nDstBufferSize = nConvertSize
time_start=time.time()
ret = self.obj_cam.MV_CC_ConvertPixelType(stConvertParam)
time_end=time.time()
print('MV_CC_ConvertPixelType to RGB:',time_end - time_start)
if ret != 0:
tkinter.messagebox.showerror('show error','convert pixel fail! ret = '+self.To_hex_str(ret))
continue
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pDstBuffer, nConvertSize)
numArray = CameraOperation.Color_numpy(self,img_buff,self.st_frame_info.nWidth,self.st_frame_info.nHeight)
mode = "RGB"
# 如果是黑白且非Mono8则转为Mono8后显示
elif self.Is_mono_data(self.st_frame_info.enPixelType):
nConvertSize = self.st_frame_info.nWidth * self.st_frame_info.nHeight
stConvertParam.enDstPixelType = PixelType_Gvsp_Mono8
stConvertParam.pDstBuffer = (c_ubyte * nConvertSize)()
stConvertParam.nDstBufferSize = nConvertSize
time_start=time.time()
ret = self.obj_cam.MV_CC_ConvertPixelType(stConvertParam)
time_end=time.time()
print('MV_CC_ConvertPixelType to Mono8:',time_end - time_start)
if ret != 0:
tkinter.messagebox.showerror('show error','convert pixel fail! ret = '+self.To_hex_str(ret))
continue
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pDstBuffer, nConvertSize)
numArray = CameraOperation.Mono_numpy(self,img_buff,self.st_frame_info.nWidth,self.st_frame_info.nHeight)
mode = "L"
#合并OpenCV到Tkinter界面中
current_image = Image.frombuffer(mode, (self.st_frame_info.nWidth,self.st_frame_info.nHeight), numArray.astype('uint8')).resize((800, 600), Image.ANTIALIAS)
imgtk = ImageTk.PhotoImage(image=current_image, master=root)
panel.imgtk = imgtk
panel.config(image=imgtk)
root.obr = imgtk
nRet = self.obj_cam.MV_CC_FreeImageBuffer(stOutFrame)
if self.b_exit == True:
if img_buff is not None:
del img_buff
if buf_cache is not None:
del buf_cache
break
def Save_jpg(self,buf_cache):
if(None == buf_cache):
return
self.buf_save_image = None
file_path = str(self.st_frame_info.nFrameNum) + ".jpg"
self.n_save_image_size = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3 + 2048
if self.buf_save_image is None:
self.buf_save_image = (c_ubyte * self.n_save_image_size)()
stParam = MV_SAVE_IMAGE_PARAM_EX()
stParam.enImageType = MV_Image_Jpeg; # ch:需要保存的图像类型 | en:Image format to save
stParam.enPixelType = self.st_frame_info.enPixelType # ch:相机对应的像素格式 | en:Camera pixel type
stParam.nWidth = self.st_frame_info.nWidth # ch:相机对应的宽 | en:Width
stParam.nHeight = self.st_frame_info.nHeight # ch:相机对应的高 | en:Height
stParam.nDataLen = self.st_frame_info.nFrameLen
stParam.pData = cast(buf_cache, POINTER(c_ubyte))
stParam.pImageBuffer= cast(byref(self.buf_save_image), POINTER(c_ubyte))
stParam.nBufferSize = self.n_save_image_size # ch:存储节点的大小 | en:Buffer node size
stParam.nJpgQuality = 80; # ch:jpg编码,仅在保存Jpg图像时有效。保存BMP时SDK内忽略该参数
return_code = self.obj_cam.MV_CC_SaveImageEx2(stParam)
if return_code != 0:
tkinter.messagebox.showerror('show error','save jpg fail! ret = '+self.To_hex_str(return_code))
self.b_save_jpg = False
return
file_open = open(file_path.encode('ascii'), 'wb+')
img_buff = (c_ubyte * stParam.nImageLen)()
try:
cdll.msvcrt.memcpy(byref(img_buff), stParam.pImageBuffer, stParam.nImageLen)
file_open.write(img_buff)
self.b_save_jpg = False
tkinter.messagebox.showinfo('show info','save jpg success!')
except:
self.b_save_jpg = False
raise Exception("get one frame failed:%s" % e.message)
if None != img_buff:
del img_buff
if None != self.buf_save_image:
del self.buf_save_image
def Save_MP4(self,buf_cache):
if(None == buf_cache):
return
self.buf_save_image = None
file_path = "./mp4/"+str(self.st_frame_info.nFrameNum) + ".jpg"
self.n_save_image_size = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3 + 2048
if self.buf_save_image is None:
self.buf_save_image = (c_ubyte * self.n_save_image_size)()
stParam = MV_SAVE_IMAGE_PARAM_EX()
stParam.enImageType = MV_Image_Jpeg; # ch:需要保存的图像类型 | en:Image format to save
stParam.enPixelType = self.st_frame_info.enPixelType # ch:相机对应的像素格式 | en:Camera pixel type
stParam.nWidth = self.st_frame_info.nWidth # ch:相机对应的宽 | en:Width
stParam.nHeight = self.st_frame_info.nHeight # ch:相机对应的高 | en:Height
stParam.nDataLen = self.st_frame_info.nFrameLen
stParam.pData = cast(buf_cache, POINTER(c_ubyte))
stParam.pImageBuffer= cast(byref(self.buf_save_image), POINTER(c_ubyte))
stParam.nBufferSize = self.n_save_image_size # ch:存储节点的大小 | en:Buffer node size
stParam.nJpgQuality = 80; # ch:jpg编码,仅在保存Jpg图像时有效。保存BMP时SDK内忽略该参数
return_code = self.obj_cam.MV_CC_SaveImageEx2(stParam)
if return_code != 0:
tkinter.messagebox.showerror('show error','save mp4 fail! ret = '+self.To_hex_str(return_code))
#xcb注释掉
# self.b_save_MP4 = False
return
file_open = open(file_path.encode('ascii'), 'wb+')
img_buff = (c_ubyte * stParam.nImageLen)()
try:
cdll.msvcrt.memcpy(byref(img_buff), stParam.pImageBuffer, stParam.nImageLen)
file_open.write(img_buff)
# self.b_save_MP4 = False
# tkinter.messagebox.showinfo('show info','save mp4 success!')
except:
# xcb注释掉
# self.b_save_MP4 = False
raise Exception("get one frame failed:%s" % e.message)
if None != img_buff:
del img_buff
if None != self.buf_save_image:
del self.buf_save_image
def Stop_MP4(self,):
self.b_save_MP4 = False
def Save_Bmp(self,buf_cache):
if(0 == buf_cache):
return
self.buf_save_image = None
file_path = str(self.st_frame_info.nFrameNum) + ".bmp"
self.n_save_image_size = self.st_frame_info.nWidth * self.st_frame_info.nHeight * 3 + 2048
if self.buf_save_image is None:
self.buf_save_image = (c_ubyte * self.n_save_image_size)()
stParam = MV_SAVE_IMAGE_PARAM_EX()
stParam.enImageType = MV_Image_Bmp; # ch:需要保存的图像类型 | en:Image format to save
stParam.enPixelType = self.st_frame_info.enPixelType # ch:相机对应的像素格式 | en:Camera pixel type
stParam.nWidth = self.st_frame_info.nWidth # ch:相机对应的宽 | en:Width
stParam.nHeight = self.st_frame_info.nHeight # ch:相机对应的高 | en:Height
stParam.nDataLen = self.st_frame_info.nFrameLen
stParam.pData = cast(buf_cache, POINTER(c_ubyte))
stParam.pImageBuffer= cast(byref(self.buf_save_image), POINTER(c_ubyte))
stParam.nBufferSize = self.n_save_image_size # ch:存储节点的大小 | en:Buffer node size
return_code = self.obj_cam.MV_CC_SaveImageEx2(stParam)
if return_code != 0:
tkinter.messagebox.showerror('show error','save bmp fail! ret = '+self.To_hex_str(return_code))
self.b_save_bmp = False
return
file_open = open(file_path.encode('ascii'), 'wb+')
img_buff = (c_ubyte * stParam.nImageLen)()
try:
cdll.msvcrt.memcpy(byref(img_buff), stParam.pImageBuffer, stParam.nImageLen)
file_open.write(img_buff)
self.b_save_bmp = False
tkinter.messagebox.showinfo('show info','save bmp success!')
except:
self.b_save_bmp = False
raise Exception("get one frame failed:%s" % e.message)
if None != img_buff:
del img_buff
if None != self.buf_save_image:
del self.buf_save_image
def Is_mono_data(self,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(self,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
def Mono_numpy(self,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
def Color_numpy(self,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