python 用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=0,
        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)
Width=1280/2
Height=1024/2
WindowHandle1 =open_window(Width, Height)
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)

if __name__ == "__main__":

    deviceList = MV_CC_DEVICE_INFO_LIST()
    tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
    
    # 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)

    nConnectionNum = input("please input the number of the device to connect:")

    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()
    
    # 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)

    # 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)
        sys.exit()

    # 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()
    
    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()

官方Grab_Callback 改的,因官方例子不太完善, 这里用halcon做显示.

这个只能打开灰度相机.彩色相机么

        if stFrameInfo:
            nWidth  = stFrameInfo.nWidth ;nHeight = stFrameInfo.nHeight ;nFrameNum = stFrameInfo.nFrameNum ;
            print(f"  {nWidth}  {nHeight}  {nFrameNum}    {stFrameInfo.enPixelType}   ")
            b = string_at(pData, nWidth * nHeight * 3)
            nparr = np.frombuffer(b, np.uint8)
            nparr = nparr.reshape(nHeight, nWidth, 3)

            ty,img=np__2_ha(nparr)
            ha.set_part(WindowHandle1,0,0,nHeight,nWidth)
            ha.disp_obj(img, WindowHandle1);
            

    # ch:注册抓图回调 | en:Register image callback
    ret = cam.MV_CC_RegisterImageCallBackForBGR(CALL_BACK_FUN,None)
    if ret != 0:
        print ("register image callback fail! ret[0x%x]" % ret)
        sys.exit()

先暂时这样吧. 能用了已经  可以打开虚拟相机和真实的物理相机

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用PythonOpenCV调用海康工业相机显示的步骤: 1.安装海康SDK并配置环境变量。 2.安装PythonOpenCV。 3.导入必要的库和模块。 ```python import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout import cv2 from HCNetSDK import * ``` 4.创建一个Qt窗口并在其中添加一个标签。 ```python class Video(QWidget): def __init__(self): super().__init__() self.label = QLabel(self) self.layout = QVBoxLayout() self.layout.addWidget(self.label) self.setLayout(self.layout) ``` 5.初始化海康SDK并登录相机。 ```python def init_camera(): # 初始化SDK if not NET_DVR_Init(): print("SDK初始化失败") sys.exit() # 登录相机 device_info = NET_DVR_DEVICEINFO_V30() device_ip = "192.168.1.64" device_port = 8000 device_username = "admin" device_password = "12345" device_id = NET_DVR_Login_V30(device_ip, device_port, device_username, device_password, device_info) if device_id < 0: print("登录相机失败") sys.exit() return device_id ``` 6.获取相机数据并将其转换为OpenCV支持的格式。 ```python def get_frame(device_id): # 获取相机数据 frame = NET_DVR_GetRealPlayImage(device_id) # 将相机数据转换为OpenCV支持的格式 frame_data = frame.contents.pBuffer frame_size = frame.contents.dwSize frame_image = np.frombuffer(frame_data, dtype=np.uint8) frame_image = frame_image.reshape((frame_size[1], frame_size[0], 4)) frame_image = cv2.cvtColor(frame_image, cv2.COLOR_BGRA2BGR) return frame_image ``` 7.在Qt窗口中显示相机数据。 ```python def show_camera(): app = QApplication(sys.argv) video = Video() video.show() device_id = init_camera() while True: frame_image = get_frame(device_id) frame_image = cv2.resize(frame_image, (640, 480)) frame_image = cv2.cvtColor(frame_image, cv2.COLOR_BGR2RGB) video.label.setPixmap(QPixmap.fromImage(QImage(frame_image.data, frame_image.shape[1], frame_image.shape[0], QImage.Format_RGB888))) if cv2.waitKey(1) & 0xFF == ord('q'): break NET_DVR_Logout(device_id) NET_DVR_Cleanup() sys.exit(app.exec_()) ``` 8.运行程序并显示相机数据。 ```python if __name__ == '__main__': show_camera() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值