# coding=utf-8 import cv2 import numpy as np import mvsdk import camera_configs import threading import time import logging import logging.handlers from multiprocessing import Process, Queue, set_start_method #全局log level, 等级从高到底为:error, warning, info, debug, 低于当前log level的log不会被打印 LOG_LEVEL = logging.INFO from configparser import ConfigParser config = ConfigParser() config.read(r'./config.ini',encoding='utf-8') #部署时,将其改成对应的相机名 friendlyName_L = config['camera_name']['Serial_number'] + '_l' friendlyName_R = config['camera_name']['Serial_number'] + '_r' #binocular id, 存数据库使用 BINOCULAR_ID = int(friendlyName_L.split('_')[0]) class Camera(object): def __init__(self,logger): super(Camera,self).__init__() #设备信息 self.DevInfo_L = None self.DevInfo_R = None #设备对象 self.hCamera_L = 0 self.hCamera_R = 0 #相机FriendNlyName,使用相机工具修改为如下 #self.friendlyName_L = '1_l' #self.friendlyName_R = '1_r' #设备参数 self.cap_L = None self.cap_R = None #为左右相机申请的内存 self.pFrameBuffer_L = 0 self.pFrameBuffer_R = 0 #logger self.logger = logger def camera_init(self): while True: # 枚举相机 DevList = mvsdk.CameraEnumerateDevice() if nDev < 1: self.logger.warning("No camera was found!") continue for DevInfo in DevList: #获取相机FriendlyName if DevInfo.GetFriendlyName() == friendlyName_L: self.DevInfo_L = DevInfo elif DevInfo.GetFriendlyName() == friendlyName_R: self.DevInfo_R = DevInfo if self.DevInfo_L == None or self.DevInfo_R == None: self.logger.warning('Get camera info failed!') time.sleep(10) continue try: #初始化摄像机 self.hCamera_L = mvsdk.CameraInit(self.DevInfo_L, -1, -1) self.hCamera_R = mvsdk.CameraInit(self.DevInfo_R, -1, -1) except mvsdk.CameraException as e: #仅断电重新上电后,执行mvsdk.CameraInit不会产生异常 #仅断网重新联网后,执行mvsdk.CameraInit会产生异常(重复初始化),错误码为-13 print('init camera error:>>',e) if e.error_code == -13: self.logger.warning("CameraInit Failed({}): {}".format(e.error_code, e.message)) #time.sleep(15) #continue #if self.hCamera_L > 0: # mvsdk.CameraUnInit(self.hCamera_L) # self.hCamera_L = 0 #if self.hCamera_R > 0: # mvsdk.CameraUnInit(self.hCamera_R) # self.hCamera_R = 0 self.close() time.sleep(10) continue self.cap_L = mvsdk.CameraGetCapability(self.hCamera_L) self.cap_R = mvsdk.CameraGetCapability(self.hCamera_R) #mvsdk.CameraSetFrameSpeed(self.hCamera_L, 5) #mvsdk.CameraSetFrameSpeed(self.hCamera_R, 5) #彩色相机输出24位灰度,这里不需要判断是黑白相机还是彩色相机 mvsdk.CameraSetIspOutFormat(self.hCamera_L, mvsdk.CAMERA_MEDIA_TYPE_BGR8) mvsdk.CameraSetIspOutFormat(self.hCamera_R, mvsdk.CAMERA_MEDIA_TYPE_BGR8) # 相机模式切换成软件触发采集,触发次数1 mvsdk.CameraSetTriggerMode(self.hCamera_L, 1)#0: 连续触发; 1: 软触发; 2: 外触发; mvsdk.CameraSetTriggerCount(self.hCamera_L, 1);#如果这里设置成0,后面用mvsdk.CameraSoftTrigger触发则会产生-12超时错误 mvsdk.CameraSetTriggerMode(self.hCamera_R, 1) mvsdk.CameraSetTriggerCount(self.hCamera_R, 1); # 自动曝光,设定亮度 mvsdk.CameraSetAeState(self.hCamera_L, 1) mvsdk.CameraSetAeTarget(self.hCamera_L, 120) mvsdk.CameraSetAeState(self.hCamera_R, 1) mvsdk.CameraSetAeTarget(self.hCamera_R, 120) #曝光时间30ms mvsdk.CameraSetExposureTime(self.hCamera_L, 15 * 1000) mvsdk.CameraSetExposureTime(self.hCamera_R, 15 * 1000) # 分配RGB buffer,用来存放ISP输出的图像 # 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer) FrameBufferSize_L = self.cap_L.sResolutionRange.iWidthMax * self.cap_L.sResolutionRange.iHeightMax * 3 FrameBufferSize_R = self.cap_R.sResolutionRange.iWidthMax * self.cap_R.sResolutionRange.iHeightMax * 3 self.pFrameBuffer_L = mvsdk.CameraAlignMalloc(FrameBufferSize_L, 16) self.pFrameBuffer_R = mvsdk.CameraAlignMalloc(FrameBufferSize_R, 16) # 让SDK内部取图线程开始工作 mvsdk.CameraPlay(self.hCamera_L) mvsdk.CameraPlay(self.hCamera_R) return def grab(self): #hCamera_L = self.hCamera_L #hCamera_R = self.hCamera_R #pFrameBuffer_L = self.pFrameBuffer_L #pFrameBuffer_R = self.pFrameBuffer_R frame_L = None frame_R = None # 软触发一次 #清空缓冲区图像 mvsdk.CameraClearBuffer(self.hCamera_L) mvsdk.CameraClearBuffer(self.hCamera_R) #软触发 mvsdk.CameraSoftTrigger(self.hCamera_L) mvsdk.CameraSoftTrigger(self.hCamera_R) #获取图像 try: pRawData_L, FrameHead_L = mvsdk.CameraGetImageBuffer(self.hCamera_L, 6000) pRawData_R, FrameHead_R = mvsdk.CameraGetImageBuffer(self.hCamera_R, 6000) except mvsdk.CameraException as e: #此处经常产生-12和-28异常,超时、正忙 self.logger.warning(str(e)) raise mvsdk.CameraException(e.error_code) #return None,None mvsdk.CameraImageProcess(self.hCamera_L, pRawData_L, self.pFrameBuffer_L, FrameHead_L) mvsdk.CameraImageProcess(self.hCamera_R, pRawData_R, self.pFrameBuffer_R, FrameHead_R) mvsdk.CameraReleaseImageBuffer(self.hCamera_L, pRawData_L) mvsdk.CameraReleaseImageBuffer(self.hCamera_R, pRawData_R) #转换图像为opencv格式 frame_data_L = (mvsdk.c_ubyte * FrameHead_L.uBytes).from_address(self.pFrameBuffer_L) frame_data_R = (mvsdk.c_ubyte * FrameHead_R.uBytes).from_address(self.pFrameBuffer_R) frame_L = np.frombuffer(frame_data_L, dtype=np.uint8) frame_R = np.frombuffer(frame_data_R, dtype=np.uint8) frame_L = frame_L.reshape((FrameHead_L.iHeight, FrameHead_L.iWidth, 3)) frame_R = frame_R.reshape((FrameHead_R.iHeight, FrameHead_R.iWidth, 3)) #释放内存,,,关闭相机时再释放即可 #mvsdk.CameraAlignFree(pFrameBuffer_L) #mvsdk.CameraAlignFree(pFrameBuffer_R) #使用标定数据进行校正 img1_rectified = cv2.remap(frame_L, camera_configs.left_map1, camera_configs.left_map2, cv2.INTER_LINEAR) img2_rectified = cv2.remap(frame_R, camera_configs.right_map1, camera_configs.right_map2, cv2.INTER_LINEAR) return img1_rectified, img2_rectified def set_param(self,params): #print(type(params)) #print(type(params["left"]),type(params["left"])) try: if params["left"] > 0: mvsdk.CameraSetAeTarget(self.hCamera_L, params["left"]) if params["right"] > 0: mvsdk.CameraSetAeTarget(self.hCamera_R, params["right"]) except Exception as e: logger.warning(str(e)) #if params["whitebalance"]=="true": # mvsdk.CameraSetOnceWB(self.hCamera_L) # mvsdk.CameraSetOnceWB(self.hCamera_R) # print('set once WB') def reconnect(self): #抓图失败执行重连 print('Start reconnecting...') #先释放申请的资源 self.close() #初始化相机 self.camera_init() def close(self): if self.hCamera_L > 0: mvsdk.CameraUnInit(self.hCamera_L) self.hCamera_L = 0 if self.hCamera_R > 0: mvsdk.CameraUnInit(self.hCamera_R) self.hCamera_R = 0 mvsdk.CameraAlignFree(self.pFrameBuffer_L) mvsdk.CameraAlignFree(self.pFrameBuffer_R) self.pFrameBuffer_L = 0 self.pFrameBuffer_R = 0 def logger_init(): logger = logging.getLogger('mylogger.a') #set log level WARNING logger.setLevel(logging.INFO) #formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s") #backup log is 3, max to 1MB. master.log3/master.log2/master.log1: oldest to newest #file_handler = logging.handlers.RotatingFileHandler('master.log',mode='a',maxBytes=1024*1024,backupCount=3) #file_handler.setFormatter(formatter) #logger.addHandler(file_handler) return logger def img_capture(queue_web,queue_binocular,queue_param): #主线程函数 #logger = logger_init() #相机初始化 camera = Camera(logger) camera.camera_init() # grab_faild_count = 0 while True: #读取左右相机 try: image_L, image_R = camera.grab() cv2.imwrite('L.bmp',image_L) cv2.imwrite('R.bmp',image_R) #实际情况中延迟比较大,需要sleep time.sleep(1) except mvsdk.CameraException as e: #程序退出立即启动,调用mvsdk.CameraGetImageBuffer产生未初始化错误,重连 if e.error_code in [-5,-12,-13,-28]: logger.warning('grab error, error code:',str(e.error_code)) grab_faild_count +=1 #5次失败后,重新连接相机 if grab_faild_count > 5: grab_faild_count = 0 logger.warning('reconnecting...') camera.reconnect() else: time.sleep(5) continue if image_L is None or image_R is None: print('grab none') continue try: #将图像送入双目队列 queue_binocular.put_nowait([image_L,image_R]) except Exception as e: logger.warning(e) try: #将图像输入前端队列 queue_web.put_nowait([image_L,image_R]) except Exception as e: logger.warning(e) try: #读取相机参数队列 params = queue_param.get_nowait() except Exception as e: logger.warning(str(e)) else: camera.set_param(params) def img_capture1(queue_web,queue_binocular,queue_param): #主线程函数 while True: image_L = cv2.imread('2023-03-09-17-10-41.7.jpg') image_R = cv2.imread('2023-03-09-17-10-41.7.jpg') time.sleep(1) try: #将图像送入双目队列 queue_binocular.put_nowait([image_L,image_R]) except Exception as e: logger.warning(e) try: #将图像输入前端队列 queue_web.put_nowait([image_L,image_R]) except Exception as e: logger.warning(e) logger = logger_init() #camera = Camera(logger) #camera.camera_init() if __name__ == '__main__': #日志 #multiprocessing.set_start_method('spawn') #两个队列,分别存放推送到前端的图像和双目处理的图像 global queue_web queue_web = Queue(10) global queue_binocular queue_binocular= Queue(10) #用于存放识别后的图像的队列,predict_new线程和webskt_server进程通信使用 global queue_masked_img queue_masked_img = Queue(10) #存放相机设置参数 global queue_param queue_param = Queue(1) img_capture(queue_binocular,queue_masked_img,queue_param)