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