当前位置: 首页 > article >正文

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

已经可以用了 界面啥都有,当然还有很多优化空间 那天心情好在去完善吧


http://www.kler.cn/a/505628.html

相关文章:

  • Kylin Linux V10 替换安装源,并在服务器上启用 EPEL 仓库
  • Mysql--运维篇--备份和恢复(逻辑备份,mysqldump,物理备份,热备份,温备份,冷备份,二进制文件备份和恢复等)
  • 代码随想录算法训练营第十二天|第18题. 四数之和
  • vscode 扩展Cline、Continue的差别?
  • 神经网络
  • 基于微信小程序的智能停车场管理系统设计与实现(LW+源码+讲解)
  • 一文了解如何使用 DBeaver 管理 DolphinDB
  • 1_CSS3 边框 --[CSS3 进阶之路]
  • 计算机网络-数据链路层(虚拟局域网VLAN)
  • git管理源码之git安装和使用
  • 1月14学习
  • 数据结构与算法之二叉树: LeetCode 654. 最大二叉树 (Ts版)
  • 【Linux】Linux命令:traceroute
  • apache-skywalking-apm-10.1.0使用
  • 讲一些算法的知识点——(1)
  • Linux TA_Lib安装
  • 智能科技与共情能力加持,哈曼重新定义驾乘体验
  • TCP/IP协议簇及封装与解封装
  • C#中的Span
  • 代码随想录算法训练营第 8 天(字符串1)| 344.反转字符串 541. 反转字符串II 卡码网54.替换数字
  • HTML5 网站模板
  • 2025-1-15-十大经典排序算法 C++与python
  • 网络安全10大漏洞
  • 超燃预告!Origin百图绘制系列即将登场
  • 不同的embedding技术效果评价
  • kafka的listeners和advertised.listeners,配置内外网分流