mirror of
http://git.xinwangdao.com/cnnc-embedded-parts-detect/detect-gui.git
synced 2025-06-24 13:14:11 +08:00
864 lines
31 KiB
Python
864 lines
31 KiB
Python
|
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=True)
|
|||
|
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)
|