from dynaconf.base import Settings from core.edge_component import EdgeComponent, device, service from device.mv.ImageConvert import * from device.mv.MVSDK import * import struct import time import datetime import logging from typing import List from core.logging import logger from PyQt5.QtCore import QObject, pyqtSignal g_cameraStatusUserInfo = b"statusInfo" class BITMAPFILEHEADER(Structure): _fields_ = [ ('bfType', c_ushort), ('bfSize', c_uint), ('bfReserved1', c_ushort), ('bfReserved2', c_ushort), ('bfOffBits', c_uint), ] class BITMAPINFOHEADER(Structure): _fields_ = [ ('biSize', c_uint), ('biWidth', c_int), ('biHeight', c_int), ('biPlanes', c_ushort), ('biBitCount', c_ushort), ('biCompression', c_uint), ('biSizeImage', c_uint), ('biXPelsPerMeter', c_int), ('biYPelsPerMeter', c_int), ('biClrUsed', c_uint), ('biClrImportant', c_uint), ] # 调色板,只有8bit及以下才需要 class RGBQUAD(Structure): _fields_ = [ ('rgbBlue', c_ubyte), ('rgbGreen', c_ubyte), ('rgbRed', c_ubyte), ('rgbReserved', c_ubyte), ] # 相机设备类 class CameraDevice: def __init__(self, camera_id, key, vendor_name, model_name, serial_number): self.camera_id = camera_id self.key = key self.vendor_name = vendor_name self.model_name = model_name self.serial_number = serial_number def __repr__(self): return (f"CameraDevice(camera_id={self.camera_id}, key={self.key}, " f"vendor_name={self.vendor_name}, model_name={self.model_name}, " f"serial_number={self.serial_number})") class CameraSignals(QObject): # QT 信号 on_device_list = pyqtSignal(list) on_device_link = pyqtSignal(int, str) on_device_change = pyqtSignal() on_device_error = pyqtSignal() on_device_data = pyqtSignal(object) # pyqt的相机管理类 @device("camera", auto_start=False) class Camera(EdgeComponent): signals = CameraSignals() def __init__(self, context): super().__init__(context) global mv_camera mv_camera = self self.devices = None self.current_index = 0 self.streamSource = None def configure(self, setting: Settings) -> None: self.logger.info(f"Camera configure done.") @service() def start(self): if MVSDKdll is None: raise RuntimeError("相机设备SDK未正确加载") camera_count = self.start_discovery() if camera_count <= 0: self.logger.info('no cameras found!') else: self.open_camera() super().start() self.logger.info("Camera start!") @service() def stop(self): self.stop_camera() super().stop() self.logger.info("Camera stop!") def start_discovery(self): cameraCnt, cameraList = enumCameras() if cameraCnt is None: return -1 self.devices = cameraList camera_devices = [] # 显示相机信息 for index in range(0, cameraCnt): camera = cameraList[index] self.logger.info("Camera Id = " + str(index)) self.logger.info("Key = " + str(camera.getKey(camera))) self.logger.info("vendor name = " + str(camera.getVendorName(camera))) self.logger.info("Model name = " + str(camera.getModelName(camera))) self.logger.info("Serial number = " + str(camera.getSerialNumber(camera))) camera_devices.append(CameraDevice(index, str(camera.getKey(camera)), str(camera.getVendorName(camera)), str(camera.getModelName(camera)), str(camera.getSerialNumber(camera)))) self.signals.on_device_list.emit(camera_devices) return cameraCnt def open_camera(self, index = 0): # 打开相机 camera = self.devices[index] nRet = openCamera(camera) if nRet != 0: self.logger.error("openCamera fail.") return -1 # 创建流对象 streamSourceInfo = GENICAM_StreamSourceInfo() streamSourceInfo.channelId = 0 streamSourceInfo.pCamera = pointer(camera) self.streamSource = pointer(GENICAM_StreamSource()) nRet = GENICAM_createStreamSource(pointer(streamSourceInfo), byref(self.streamSource)) if nRet != 0: self.logger.error("create StreamSource fail!") return -1 # 注册相机连接状态回调 nRet = subscribeCameraStatus(camera) if nRet != 0: self.logger.error("subscribeCameraStatus fail!") return -1 self.current_index = index return 0 def stop_camera(self): camera = self.devices[self.current_index] # 关闭相机 nRet = closeCamera(camera) if nRet != 0: self.logger.error("closeCamera fail") # 释放相关资源 if self.streamSource is not None: self.streamSource.contents.release(self.streamSource) return -1 # 反向注册相机连接状态回调 nRet = unsubscribeCameraStatus(camera) if nRet != 0: self.logger.error("unsubscribeCameraStatus fail!") return -1 # 释放相关资源 if self.streamSource is not None: self.streamSource.contents.release(self.streamSource) def set_exposure_time(self, exposure_time: int): # 设置曝光时间 camera = self.devices[self.current_index] setExposureTime(camera, exposure_time) def set_soft_trigger(self): # 设置软触发 camera = self.devices[self.current_index] setSoftTriggerConf(camera) def set_line_trigger(self): # 设置外触发 camera = self.devices[self.current_index] setLineTriggerConf(camera) def set_roi(self, offset_x, offset_y, width, height): # 设置相机ROI camera = self.devices[self.current_index] setROI(camera, offset_x, offset_y, width, height) def grab_one(self): # 设置软触发 camera = self.devices[self.current_index] nRet = setSoftTriggerConf(camera) if nRet != 0: self.logger.error("set SoftTriggerConf fail!") # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 else: self.logger.info("set SoftTriggerConf success!") # 开始拉流 nRet = self.streamSource.contents.startGrabbing(self.streamSource, c_ulonglong(0), c_int(GENICAM_EGrabStrategy.grabStrartegySequential)) if nRet != 0: self.logger.error("startGrabbing fail!") # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 time.sleep(1) # 软触发取一张图 nRet = grabOne(camera) if nRet != 0: self.logger.error("grabOne fail!") # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 else: self.logger.info("trigger time: " + str(datetime.datetime.now())) # 主动取图 frame = pointer(GENICAM_Frame()) nRet = self.streamSource.contents.getFrame(self.streamSource, byref(frame), c_uint(100000)) if nRet != 0: self.logger.error("SoftTrigger getFrame fail! timeOut [100000]ms") # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 else: self.logger.info("SoftTrigger getFrame success BlockId = " + str(frame.contents.getBlockId(frame))) self.logger.info("get frame time: " + str(datetime.datetime.now())) nRet = frame.contents.valid(frame) if nRet != 0: self.logger.error("frame is invalid!") # 释放驱动图像缓存资源 frame.contents.release(frame) # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 # 将裸数据图像拷出 imageSize = frame.contents.getImageSize(frame) self.logger.info(f"imageSize is {imageSize}!") buffAddr = frame.contents.getImage(frame) frameBuff = c_buffer(b'\0', imageSize) memmove(frameBuff, c_char_p(buffAddr), imageSize) # 给转码所需的参数赋值 convertParams = IMGCNV_SOpenParam() convertParams.dataSize = imageSize convertParams.height = frame.contents.getImageHeight(frame) convertParams.width = frame.contents.getImageWidth(frame) convertParams.paddingX = frame.contents.getImagePaddingX(frame) convertParams.paddingY = frame.contents.getImagePaddingY(frame) convertParams.pixelForamt = frame.contents.getImagePixelFormat(frame) # 释放驱动图像缓存 frame.contents.release(frame) # 保存bmp图片 bmpInfoHeader = BITMAPINFOHEADER() bmpFileHeader = BITMAPFILEHEADER() uRgbQuadLen = 0 rgbQuad = (RGBQUAD * 256)() # 调色板信息 rgbBuff = c_buffer(b'\0', convertParams.height * convertParams.width * 3) # 如果图像格式是 Mono8 不需要转码 if convertParams.pixelForamt == EPixelType.gvspPixelMono8: # 初始化调色板rgbQuad 实际应用中 rgbQuad 只需初始化一次 for i in range(0, 256): rgbQuad[i].rgbBlue = rgbQuad[i].rgbGreen = rgbQuad[i].rgbRed = i uRgbQuadLen = sizeof(RGBQUAD) * 256 bmpFileHeader.bfSize = sizeof(bmpFileHeader) + sizeof(bmpInfoHeader) + uRgbQuadLen + convertParams.dataSize bmpInfoHeader.biBitCount = 8 else: # 转码 => BGR24 rgbSize = c_int() nRet = IMGCNV_ConvertToBGR24(cast(frameBuff, c_void_p), byref(convertParams), cast(rgbBuff, c_void_p), byref(rgbSize)) if nRet != 0: mv_camera.logger.error("image convert fail! errorCode = " + str(nRet)) # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 bmpFileHeader.bfSize = sizeof(bmpFileHeader) + sizeof(bmpInfoHeader) + rgbSize.value bmpInfoHeader.biBitCount = 24 bmpFileHeader.bfType = 0x4D42 # 文件头类型 'BM'(42 4D) bmpFileHeader.bfReserved1 = 0 # 保留字 bmpFileHeader.bfReserved2 = 0 # 保留字 bmpFileHeader.bfOffBits = 54 + uRgbQuadLen # 位图像素数据的起始位置 bmpInfoHeader.biSize = 40 # 信息头所占字节数 bmpInfoHeader.biWidth = convertParams.width bmpInfoHeader.biHeight = -convertParams.height bmpInfoHeader.biPlanes = 1 # 位图平面数 bmpInfoHeader.biCompression = 0 # 压缩类型,0 即不压缩 bmpInfoHeader.biSizeImage = 0 bmpInfoHeader.biXPelsPerMeter = 0 bmpInfoHeader.biYPelsPerMeter = 0 bmpInfoHeader.biClrUsed = 0 bmpInfoHeader.biClrImportant = 0 fileName = './image.bmp' imageFile = open(fileName, 'wb+') imageFile.write(struct.pack('H', bmpFileHeader.bfType)) imageFile.write(struct.pack('I', bmpFileHeader.bfSize)) imageFile.write(struct.pack('H', bmpFileHeader.bfReserved1)) imageFile.write(struct.pack('H', bmpFileHeader.bfReserved2)) imageFile.write(struct.pack('I', bmpFileHeader.bfOffBits)) imageFile.write(struct.pack('I', bmpInfoHeader.biSize)) imageFile.write(struct.pack('i', bmpInfoHeader.biWidth)) imageFile.write(struct.pack('i', bmpInfoHeader.biHeight)) imageFile.write(struct.pack('H', bmpInfoHeader.biPlanes)) imageFile.write(struct.pack('H', bmpInfoHeader.biBitCount)) imageFile.write(struct.pack('I', bmpInfoHeader.biCompression)) imageFile.write(struct.pack('I', bmpInfoHeader.biSizeImage)) imageFile.write(struct.pack('i', bmpInfoHeader.biXPelsPerMeter)) imageFile.write(struct.pack('i', bmpInfoHeader.biYPelsPerMeter)) imageFile.write(struct.pack('I', bmpInfoHeader.biClrUsed)) imageFile.write(struct.pack('I', bmpInfoHeader.biClrImportant)) if convertParams.pixelForamt == EPixelType.gvspPixelMono8: # 写入调色板信息 for i in range(0, 256): imageFile.write(struct.pack('B', rgbQuad[i].rgbBlue)) imageFile.write(struct.pack('B', rgbQuad[i].rgbGreen)) imageFile.write(struct.pack('B', rgbQuad[i].rgbRed)) imageFile.write(struct.pack('B', rgbQuad[i].rgbReserved)) imageFile.writelines(frameBuff) else: imageFile.writelines(rgbBuff) imageFile.close() self.logger.info("save " + fileName + " success.") self.logger.info("save bmp time: " + str(datetime.datetime.now())) # 停止拉流 nRet = self.streamSource.contents.stopGrabbing(self.streamSource) if nRet != 0: self.logger.error("stopGrabbing fail!") # 释放相关资源 self.streamSource.contents.release(self.streamSource) return -1 # 相机管理类实例 mv_camera = None # 取流回调函数 def onGetFrame(frame): nRet = frame.contents.valid(frame) if nRet != 0: mv_camera.logger.error("frame is invalid!") # 释放驱动图像缓存资源 frame.contents.release(frame) return mv_camera.logger.info("BlockId = %d" %(frame.contents.getBlockId(frame))) #此处客户应用程序应将图像拷贝出使用 ''' ''' # 释放驱动图像缓存资源 frame.contents.release(frame) # 取流回调函数Ex def onGetFrameEx(frame, userInfo): nRet = frame.contents.valid(frame) if ( nRet != 0): mv_camera.logger.error("frame is invalid!") # 释放驱动图像缓存资源 frame.contents.release(frame) return mv_camera.logger.info("BlockId = %d userInfo = %s" %(frame.contents.getBlockId(frame), c_char_p(userInfo).value)) #此处客户应用程序应将图像拷贝出使用 ''' ''' # 释放驱动图像缓存资源 frame.contents.release(frame) # 相机连接状态回调函数 def deviceLinkNotify(connectArg, linkInfo): mv_camera.on_device_link.emit(connectArg.contents.m_event, c_char_p(linkInfo).value.decode('utf-8')) if EVType.offLine == connectArg.contents.m_event: mv_camera.logger.info("camera has off line, userInfo [%s]" %(c_char_p(linkInfo).value)) elif EVType.onLine == connectArg.contents.m_event: mv_camera.logger.info("camera has on line, userInfo [%s]" %(c_char_p(linkInfo).value)) connectCallBackFuncEx = connectCallBackEx(deviceLinkNotify) frameCallbackFunc = callbackFunc(onGetFrame) frameCallbackFuncEx = callbackFuncEx(onGetFrameEx) # 注册相机连接状态回调 def subscribeCameraStatus(camera): # 注册上下线通知 eventSubscribe = pointer(GENICAM_EventSubscribe()) eventSubscribeInfo = GENICAM_EventSubscribeInfo() eventSubscribeInfo.pCamera = pointer(camera) nRet = GENICAM_createEventSubscribe(byref(eventSubscribeInfo), byref(eventSubscribe)) if nRet != 0: mv_camera.logger.error("create eventSubscribe fail!") return -1 nRet = eventSubscribe.contents.subscribeConnectArgsEx(eventSubscribe, connectCallBackFuncEx, g_cameraStatusUserInfo) if nRet != 0: mv_camera.logger.error("subscribeConnectArgsEx fail!") # 释放相关资源 eventSubscribe.contents.release(eventSubscribe) return -1 # 不再使用时,需释放相关资源 eventSubscribe.contents.release(eventSubscribe) return 0 # 反注册相机连接状态回调 def unsubscribeCameraStatus(camera): # 反注册上下线通知 eventSubscribe = pointer(GENICAM_EventSubscribe()) eventSubscribeInfo = GENICAM_EventSubscribeInfo() eventSubscribeInfo.pCamera = pointer(camera) nRet = GENICAM_createEventSubscribe(byref(eventSubscribeInfo), byref(eventSubscribe)) if nRet != 0: mv_camera.logger.error("create eventSubscribe fail!") return -1 nRet = eventSubscribe.contents.unsubscribeConnectArgsEx(eventSubscribe, connectCallBackFuncEx, g_cameraStatusUserInfo) if nRet != 0: mv_camera.logger.error("unsubscribeConnectArgsEx fail!") # 释放相关资源 eventSubscribe.contents.release(eventSubscribe) return -1 # 不再使用时,需释放相关资源 eventSubscribe.contents.release(eventSubscribe) return 0 # 设置软触发 def setSoftTriggerConf(camera): # 创建control节点 acqCtrlInfo = GENICAM_AcquisitionControlInfo() acqCtrlInfo.pCamera = pointer(camera) acqCtrl = pointer(GENICAM_AcquisitionControl()) nRet = GENICAM_createAcquisitionControl(pointer(acqCtrlInfo), byref(acqCtrl)) if nRet != 0: mv_camera.logger.error("create AcquisitionControl fail!") return -1 # 设置触发源为软触发 trigSourceEnumNode = acqCtrl.contents.triggerSource(acqCtrl) nRet = trigSourceEnumNode.setValueBySymbol(byref(trigSourceEnumNode), b"Software") if nRet != 0: mv_camera.logger.error("set TriggerSource value [Software] fail!") # 释放相关资源 trigSourceEnumNode.release(byref(trigSourceEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigSourceEnumNode.release(byref(trigSourceEnumNode)) # 设置触发方式 trigSelectorEnumNode = acqCtrl.contents.triggerSelector(acqCtrl) nRet = trigSelectorEnumNode.setValueBySymbol(byref(trigSelectorEnumNode), b"FrameStart") if nRet != 0: mv_camera.logger.error("set TriggerSelector value [FrameStart] fail!") # 释放相关资源 trigSelectorEnumNode.release(byref(trigSelectorEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigSelectorEnumNode.release(byref(trigSelectorEnumNode)) # 打开触发模式 trigModeEnumNode = acqCtrl.contents.triggerMode(acqCtrl) nRet = trigModeEnumNode.setValueBySymbol(byref(trigModeEnumNode), b"On") if nRet != 0: mv_camera.logger.error("set TriggerMode value [On] fail!") # 释放相关资源 trigModeEnumNode.release(byref(trigModeEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放相关资源 trigModeEnumNode.release(byref(trigModeEnumNode)) acqCtrl.contents.release(acqCtrl) return 0 # 设置外触发 def setLineTriggerConf(camera): # 创建control节点 acqCtrlInfo = GENICAM_AcquisitionControlInfo() acqCtrlInfo.pCamera = pointer(camera) acqCtrl = pointer(GENICAM_AcquisitionControl()) nRet = GENICAM_createAcquisitionControl(pointer(acqCtrlInfo), byref(acqCtrl)) if nRet != 0: mv_camera.logger.error("create AcquisitionControl fail!") return -1 # 设置触发源为软触发 trigSourceEnumNode = acqCtrl.contents.triggerSource(acqCtrl) nRet = trigSourceEnumNode.setValueBySymbol(byref(trigSourceEnumNode), b"Line1") if nRet != 0: mv_camera.logger.error("set TriggerSource value [Line1] fail!") # 释放相关资源 trigSourceEnumNode.release(byref(trigSourceEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigSourceEnumNode.release(byref(trigSourceEnumNode)) # 设置触发方式 trigSelectorEnumNode = acqCtrl.contents.triggerSelector(acqCtrl) nRet = trigSelectorEnumNode.setValueBySymbol(byref(trigSelectorEnumNode), b"FrameStart") if nRet != 0: mv_camera.logger.error("set TriggerSelector value [FrameStart] fail!") # 释放相关资源 trigSelectorEnumNode.release(byref(trigSelectorEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigSelectorEnumNode.release(byref(trigSelectorEnumNode)) # 打开触发模式 trigModeEnumNode = acqCtrl.contents.triggerMode(acqCtrl) nRet = trigModeEnumNode.setValueBySymbol(byref(trigModeEnumNode), b"On") if nRet != 0: mv_camera.logger.error("set TriggerMode value [On] fail!") # 释放相关资源 trigModeEnumNode.release(byref(trigModeEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigModeEnumNode.release(byref(trigModeEnumNode)) # 设置触发沿 trigActivationEnumNode = acqCtrl.contents.triggerActivation(acqCtrl) nRet = trigActivationEnumNode.setValueBySymbol(byref(trigActivationEnumNode), b"RisingEdge") if nRet != 0: mv_camera.logger.error("set TriggerActivation value [RisingEdge] fail!") # 释放相关资源 trigActivationEnumNode.release(byref(trigActivationEnumNode)) acqCtrl.contents.release(acqCtrl) return -1 # 需要释放Node资源 trigActivationEnumNode.release(byref(trigActivationEnumNode)) acqCtrl.contents.release(acqCtrl) return 0 # 打开相机 def openCamera(camera): # 连接相机 nRet = camera.connect(camera, c_int(GENICAM_ECameraAccessPermission.accessPermissionControl)) if nRet != 0: mv_camera.logger.error("camera connect fail!") return -1 else: mv_camera.logger.info("camera connect success.") # # 注册相机连接状态回调 # nRet = subscribeCameraStatus(camera) # if nRet != 0: # mv_camera.logger.error("subscribeCameraStatus fail!") # return -1 return 0 # 关闭相机 def closeCamera(camera): # 反注册相机连接状态回调 nRet = unsubscribeCameraStatus(camera) if nRet != 0: mv_camera.logger.error("unsubscribeCameraStatus fail!") return -1 # 断开相机 # nRet = camera.disConnect(byref(camera)) # if nRet != 0: # mv_camera.logger.error("disConnect camera fail!") # return -1 return 0 # 设置曝光 def setExposureTime(camera, dVal): # 通用属性设置:设置曝光 --根据属性类型,直接构造属性节点。如曝光是 double类型,构造doubleNode节点 exposureTimeNode = pointer(GENICAM_DoubleNode()) exposureTimeNodeInfo = GENICAM_DoubleNodeInfo() exposureTimeNodeInfo.pCamera = pointer(camera) exposureTimeNodeInfo.attrName = b"ExposureTime" nRet = GENICAM_createDoubleNode(byref(exposureTimeNodeInfo), byref(exposureTimeNode)) if nRet != 0: mv_camera.logger.error("create ExposureTime Node fail!") return -1 # 设置曝光时间 nRet = exposureTimeNode.contents.setValue(exposureTimeNode, c_double(dVal)) if nRet != 0: mv_camera.logger.error("set ExposureTime value [%f]us fail!" % (dVal)) # 释放相关资源 exposureTimeNode.contents.release(exposureTimeNode) return -1 else: mv_camera.logger.info("set ExposureTime value [%f]us success." % (dVal)) # 释放节点资源 exposureTimeNode.contents.release(exposureTimeNode) return 0 # 枚举相机 def enumCameras(): # 获取系统单例 system = pointer(GENICAM_System()) nRet = GENICAM_getSystemInstance(byref(system)) if nRet != 0: mv_camera.logger.error("getSystemInstance fail!") return None, None # 发现相机 cameraList = pointer(GENICAM_Camera()) cameraCnt = c_uint() nRet = system.contents.discovery(system, byref(cameraList), byref(cameraCnt), c_int(GENICAM_EProtocolType.typeAll)); if nRet != 0: mv_camera.logger.error("discovery fail!") return None, None elif cameraCnt.value < 1: mv_camera.logger.info("discovery no camera!") return None, None else: mv_camera.logger.info("cameraCnt: " + str(cameraCnt.value)) return cameraCnt.value, cameraList def grabOne(camera): # 创建流对象 streamSourceInfo = GENICAM_StreamSourceInfo() streamSourceInfo.channelId = 0 streamSourceInfo.pCamera = pointer(camera) streamSource = pointer(GENICAM_StreamSource()) nRet = GENICAM_createStreamSource(pointer(streamSourceInfo), byref(streamSource)) if nRet != 0: mv_camera.logger.error("create StreamSource fail!") return -1 # 创建control节点 acqCtrlInfo = GENICAM_AcquisitionControlInfo() acqCtrlInfo.pCamera = pointer(camera) acqCtrl = pointer(GENICAM_AcquisitionControl()) nRet = GENICAM_createAcquisitionControl(pointer(acqCtrlInfo), byref(acqCtrl)) if nRet != 0: mv_camera.logger.error("create AcquisitionControl fail!") # 释放相关资源 streamSource.contents.release(streamSource) return -1 # 执行一次软触发 trigSoftwareCmdNode = acqCtrl.contents.triggerSoftware(acqCtrl) nRet = trigSoftwareCmdNode.execute(byref(trigSoftwareCmdNode)) if nRet != 0: mv_camera.logger.error("Execute triggerSoftware fail!") # 释放相关资源 trigSoftwareCmdNode.release(byref(trigSoftwareCmdNode)) acqCtrl.contents.release(acqCtrl) streamSource.contents.release(streamSource) return -1 # 释放相关资源 trigSoftwareCmdNode.release(byref(trigSoftwareCmdNode)) acqCtrl.contents.release(acqCtrl) streamSource.contents.release(streamSource) return 0 # 设置感兴趣区域 --- 感兴趣区域的宽高 和 xy方向的偏移量 入参值应符合对应相机的递增规则 def setROI(camera, OffsetX, OffsetY, nWidth, nHeight): #获取原始的宽度 widthMaxNode = pointer(GENICAM_IntNode()) widthMaxNodeInfo = GENICAM_IntNodeInfo() widthMaxNodeInfo.pCamera = pointer(camera) widthMaxNodeInfo.attrName = b"WidthMax" nRet = GENICAM_createIntNode(byref(widthMaxNodeInfo), byref(widthMaxNode)) if nRet != 0: mv_camera.logger.error("create WidthMax Node fail!") return -1 oriWidth = c_longlong() nRet = widthMaxNode.contents.getValue(widthMaxNode, byref(oriWidth)) if nRet != 0: mv_camera.logger.error("widthMaxNode getValue fail!") # 释放相关资源 widthMaxNode.contents.release(widthMaxNode) return -1 # 释放相关资源 widthMaxNode.contents.release(widthMaxNode) # 获取原始的高度 heightMaxNode = pointer(GENICAM_IntNode()) heightMaxNodeInfo = GENICAM_IntNodeInfo() heightMaxNodeInfo.pCamera = pointer(camera) heightMaxNodeInfo.attrName = b"HeightMax" nRet = GENICAM_createIntNode(byref(heightMaxNodeInfo), byref(heightMaxNode)) if nRet != 0: mv_camera.logger.error("create HeightMax Node fail!") return -1 oriHeight = c_longlong() nRet = heightMaxNode.contents.getValue(heightMaxNode, byref(oriHeight)) if nRet != 0: mv_camera.logger.error("heightMaxNode getValue fail!") # 释放相关资源 heightMaxNode.contents.release(heightMaxNode) return -1 # 释放相关资源 heightMaxNode.contents.release(heightMaxNode) # 检验参数 if (oriWidth.value < (OffsetX + nWidth)) or (oriHeight.value < (OffsetY + nHeight)): mv_camera.logger.error("please check input param!") return -1 # 设置宽度 widthNode = pointer(GENICAM_IntNode()) widthNodeInfo = GENICAM_IntNodeInfo() widthNodeInfo.pCamera = pointer(camera) widthNodeInfo.attrName = b"Width" nRet = GENICAM_createIntNode(byref(widthNodeInfo), byref(widthNode)) if nRet != 0: mv_camera.logger.error("create Width Node fail!") return -1 nRet = widthNode.contents.setValue(widthNode, c_longlong(nWidth)) if nRet != 0: mv_camera.logger.error("widthNode setValue [%d] fail!" % (nWidth)) # 释放相关资源 widthNode.contents.release(widthNode) return -1 # 释放相关资源 widthNode.contents.release(widthNode) # 设置高度 heightNode = pointer(GENICAM_IntNode()) heightNodeInfo = GENICAM_IntNodeInfo() heightNodeInfo.pCamera = pointer(camera) heightNodeInfo.attrName = b"Height" nRet = GENICAM_createIntNode(byref(heightNodeInfo), byref(heightNode)) if nRet != 0: mv_camera.logger.error("create Height Node fail!") return -1 nRet = heightNode.contents.setValue(heightNode, c_longlong(nHeight)) if nRet != 0: mv_camera.logger.error("heightNode setValue [%d] fail!" % (nHeight)) # 释放相关资源 heightNode.contents.release(heightNode) return -1 # 释放相关资源 heightNode.contents.release(heightNode) # 设置OffsetX OffsetXNode = pointer(GENICAM_IntNode()) OffsetXNodeInfo = GENICAM_IntNodeInfo() OffsetXNodeInfo.pCamera = pointer(camera) OffsetXNodeInfo.attrName = b"OffsetX" nRet = GENICAM_createIntNode(byref(OffsetXNodeInfo), byref(OffsetXNode)) if nRet != 0: mv_camera.logger.error("create OffsetX Node fail!") return -1 nRet = OffsetXNode.contents.setValue(OffsetXNode, c_longlong(OffsetX)) if nRet != 0: mv_camera.logger.error("OffsetX setValue [%d] fail!" % (OffsetX)) # 释放相关资源 OffsetXNode.contents.release(OffsetXNode) return -1 # 释放相关资源 OffsetXNode.contents.release(OffsetXNode) # 设置OffsetY OffsetYNode = pointer(GENICAM_IntNode()) OffsetYNodeInfo = GENICAM_IntNodeInfo() OffsetYNodeInfo.pCamera = pointer(camera) OffsetYNodeInfo.attrName = b"OffsetY" nRet = GENICAM_createIntNode(byref(OffsetYNodeInfo), byref(OffsetYNode)) if nRet != 0: mv_camera.logger.error("create OffsetY Node fail!") return -1 nRet = OffsetYNode.contents.setValue(OffsetYNode, c_longlong(OffsetY)) if nRet != 0: mv_camera.logger.error("OffsetY setValue [%d] fail!" % (OffsetY)) # 释放相关资源 OffsetYNode.contents.release(OffsetYNode) return -1 # 释放相关资源 OffsetYNode.contents.release(OffsetYNode) return 0 def demo(): # 发现相机 cameraCnt, cameraList = enumCameras() if cameraCnt is None: return -1 # 显示相机信息 for index in range(0, cameraCnt): camera = cameraList[index] print("\nCamera Id = " + str(index)) print("Key = " + str(camera.getKey(camera))) print("vendor name = " + str(camera.getVendorName(camera))) print("Model name = " + str(camera.getModelName(camera))) print("Serial number = " + str(camera.getSerialNumber(camera))) camera = cameraList[0] return 0 if __name__=="__main__": pass # camera_count = mv_camera.start_discovery() # if camera_count <= 0: # mv_camera.logger.info('no cameras found!') # else: # mv_camera.open() # mv_camera.set_roi(0, 0, 3000, 3000) # mv_camera.grab_one() # # time.sleep(2) # # mv_camera.set_exposure_time(20000) # mv_camera.stop() # # 3s exit # time.sleep(3)