项目场景:
对Basler相机进行二次开发,在这里贴上自己写的camera.py文件,主要包括两个类——Handler类和avtCamera类,前者用于相机图像获取与传输,后者用于设置相机的参数。
代码
提示:需要提前装上basler相机的pypylon库,可以参考其他博主的文章
如下:
# -*- coding = UTF-8 -*-
from pymba import Vimba
import vimba
from vimba import *
from typing import Optional
import SysParam as SP
import sys
import cv2
class Handler:
def __init__(self):
self.shutdown_event = threading.Event()
# 相机采集结果指针数组 存放采集结果 大小为MAX_BUFFER
# self.m_GrabResult = [ vimba.Frame for i in range(SP.MAX_BUFFER)]
self.m_GrabResult = [i for i in range(SP.MAX_BUFFER)]
# 用于显示的采集结果指针
self.m_DisplayGrabResult = vimba.Frame
# 显示图像标志位
self.mDisplayImage = False
# 保存图像标志位
self.mSaveImage = False
# 用于记录已存放的采集结果图片数量
self.img_num = 0
# 采集结束标志位
self.bGrabOver = False
def __call__(self, cam: Camera, frame: Frame):
print('aa')
if frame.get_status() == FrameStatus.Complete:
# print('{} acquired {}'.format(cam, frame), flush=True)
print("Image succeeded")
self.bGrabOver = True
if self.mSaveImage:
self.m_GrabResult[self.img_num] = frame.as_numpy_ndarray()
print("a")
assert self.img_num < SP.MAX_BUFFER
cam.queue_frame(frame)
self.shutdown_event.set()
class avtCamera:
def __init__(self, mb: int):
global MAX_BUFFER
MAX_BUFFER = mb
# self.mThreadSaveAndDisplayImageThread = None
self.mIsCameraConnected = False
# self.mDisplayBitmapImage = #BMP图像
# 用于获取要保存或显示的图像
self.mImageEventHandler = Handler()
# 存放抓取照片结果
self.mGrabResult = vimba.Frame
# 传入相机的ID
self.mcamera = 1
# 变量用于修改相机的曝光参数
def InitCamera(self):
"""
初始化相机,根据输入参数设置相机的左右标志位
注册相机 用于取得拍摄到的图片
设置相机用于缓存图像的最大缓存区域
打开相机
获取相机ID 并保存到其成员变量mCameraID中
根据mCameraTriggerMode切换相机的触发模式
设置相机的曝光事件
最后设置相机的心跳机制响应时间
"""
pass
#self.OpenCamera()
def OpenCamera(self):
self.mcamera._open()
def CloseCamera(self):
"""
如果正在抓取图像则停止抓取
监控相机线程关闭状态 如果未结束则报错
接着删除pylon相机对象mCamera和事件处理对象 mImageEventHandler
"""
# self.mcamera._close()
self.mIsCameraConnected = False
del self.mcamera
del self.mImageEventHandler # 用del语句来删除对象
def AllowImageSave(self, flag: bool):
self.mImageEventHandler.mSaveImage = flag
def AllowImageDisplay(self, flag: bool):
self.mImageEventHandler.mDisplayImage = flag
# 开始连续图像抓取
def StartContinueImageAcquisition(self):
# if self.mcamera.is_streaming():
# self.mcamera.stop_streaming()
# buffer_count设置相机用于缓存图像的最大缓存区域
pass
# 停止图像抓取,如果正在抓取图像则停止抓取
def StopImageAcquisition(self):
if self.mcamera.is_streaming():
self.mcamera.stop_streaming()
# 示例修改相机曝光值参数
def SetExposure(self, mExposure:int):
try:
with Vimba.get_instance():
cam = self.mcamera
with cam:
exposure_time = cam.ExposureTimeAbs
exposure_time.set(mExposure*1000)
except BaseException as e:
print(str(e))
def SwitchTriggerMode(self, mTriggerMode):
"""
调整相机的触发模式- true为软触发模式 false为硬触发模式
选择触发线为接口1 触发方式为上升沿电平
"""
try:
with Vimba.get_instance():
cam = self.mcamera
with cam:
if mTriggerMode:
cam.TriggerMode.set('Off')
cam.TriggerSource.set('Software')
else:
cam.TriggerMode.set('On')
cam.TriggerSource.set('Line1')
cam.TriggerActivation.set('RisingEdge')
cam.TriggerSelector.set('FrameStart')
cam.AcquisitionMode.set('Continuous')
except BaseException as e:
print(str(e))
def SaveContinueImageAcquisition(self,FolderPathPlus):
"""
将连续采集的MAX_BUFFER张图片 存储到FolderPathPuls下 按编号存储
flag-是否全部村图成功的标志位,false存图成功,true存图失败
"""
# for i in range(SP.MAX_BUFFER):
# # BMP文件的存储位置
# strBMP_Path = FolderPathPlus + str(i + 1) + '.bmp'
# cv2.imwrite(strBMP_Path,self.mImageEventHandler.m_GrabResult[i])
# frame = cam.get_frame()
# strBMP_Path = FolderPathPlus + str(i + 1) + '.bmp'
# cv2.imwrite(strBMP_Path, frame.as_opencv_image())
flag = False
for i in range(SP.MAX_BUFFER):
# BMP文件的存储位置
strBMP_Path = FolderPathPlus + str(i + 1) + ".bmp"
cv2.imwrite(strBMP_Path, self.mImageEventHandler.m_GrabResult[i])
return flag
# class vimbaCamera():
# def __init__(self, mb):
# global MAX_BUFFER
# MAX_BUFFER = mb
# # self.mThreadSaveAndDisplayImageThread = None
# self.mIsCameraConnected = False
# # self.mDispalyBitmapImage = pylon.CPylonBitmapImage() #BMP图像
# # 用于获取要保存或显示的图像
# self.mImageEventHandler = ImageEventHandler()
# self.mImageEventHandler.minit()
# # 存放抓取照片结果
# self.mGrabResult = vimba.Frame
# # avt 自带的相机实例
# self.mcamera = vimba.Camera('DEV_000F315DB756')
# 变量用于修改相机的曝光参数
# def InitCameras(self, i):
# # 初始化相机
# if i == 0:
# print("Initialization Avt.")
# vimbas = Vimba.get_instance() # Get the transport layer factory.
# with Vimba.get_instance() as vimba:
# m_devices = vimbas.get_all_cameras() # 获取所有连接的相机 # type(devices))为tuple
# num = len(m_devices)
# print(num, " cameras are connected")
# if(num < 2):
# print("Cameras link error")
# # 通过id区分左右相机
# # id- CameraId to search for. For GigE - Cameras, the IP and MAC-Address can be used to Camera lookup.
# mid= m_devices[i].get_id()
# # 将测头名称变换为相机编号 1的ascii码是49
# mIDCamera = ord(mid[15]) - 54
# print(mIDCamera)
# return mIDCamera
总结:
都在代码里了
希望可以帮到有相关相机开发需求的同学。