from pypylon import pylon
import cv2
import numpy as np
class BaslerCameras:
def __init__(self, interface_type, width, height, exposure, gain):
"""
初始化 BaslerCamera 类
:param interface_type: 接口类型 ('GigE' 或 'USB')
:param width: 图像宽度
:param height: 图像高度
:param exposure: 曝光时间(微秒)
:param gain: 增益
"""
self.interface_type = interface_type
self.camera = None
self.width = width
self.height = height
self.exposure = exposure
self.gain = gain
# 初始化 Pylon 系统
# pylon.initialize()
# 获取所有可用的相机
self.camera_list = pylon.TlFactory.GetInstance().EnumerateDevices()
if not self.camera_list:
raise RuntimeError("No camera detected")
# 根据接口类型选择相机
self.select_camera()
# 配置相机参数
self.camera.Width = self.width
self.camera.Height = self.height
self.camera.ExposureTime = self.exposure
self.camera.Gain = self.gain
# 开始采集图像
self.camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
def select_camera(self):
"""
选择适当的相机根据接口类型
"""
for device in self.camera_list:
if (self.interface_type == 'GigE' and device.GetDeviceClass() == 'BaslerGigE') or \
(self.interface_type == 'USB' and device.GetDeviceClass() == 'BaslerUsb'):
self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateDevice(device))
break
if self.camera is None:
raise RuntimeError(f"No {self.interface_type} camera detected")
# 打开相机
self.camera.Open()
def grab_image(self):
"""
抓取一帧图像
:return: 图像(如果成功),否则返回 None
"""
if self.camera.IsGrabbing():
#这行代码从相机中检索抓取结果。5000 表示等待结果的最大时间
grab_result = self.camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
if grab_result.GrabSucceeded():
# 获取图像数据
image = grab_result.Array
# 将图像数据转换为 OpenCV 格式
image = np.array(image, dtype=np.uint8)
image = cv2.cvtColor(image, cv2.COLOR_BAYER_BG2BGR)
grab_result.Release()
return image
return None
def start_recording(self, output_file, duration):
"""
开始录像
:param output_file: 输出文件路径
:param duration: 录像时长(秒)
"""
#创建一个视频编解码器对象,使用的是XVID编码格式。用于指定视频编解码器。
fourcc = cv2.VideoWriter_fourcc(*'XVID')
#建一个视频写入器对象,用于将视频帧写入文件。output_file:输出视频文件的路径。视频的帧率(每秒20帧)。
out = cv2.VideoWriter(output_file, fourcc, 20.0, (self.width, self.height))
#计算出录像结束时的时钟周期计数。获取当前的时钟周期计数。将指定的录像时长(秒)转换为时钟周期数。
end_time = cv2.getTickCount() + duration * cv2.getTickFrequency()
#在当前时钟周期计数小于结束时间之前,持续循环。
while cv2.getTickCount() < end_time:
image = self.grab_image()
if image is not None:
out.write(image)
else:
break
#释放视频写入器
out.release()
def close(self):
"""
停止采集并关闭相机
"""
if self.camera:
self.camera.StopGrabbing()
self.camera.Close()
# 释放 Pylon 系统
pylon.terminate()
def camera_worker(camera, operation, *args):
"""
工作线程函数
:param camera: BaslerCamera 实例
:param operation: 操作类型 ('capture' 或 'record')
:param args: 操作参数
"""
if operation == 'capture':
image = camera.grab_image()
if image is not None:
cv2.imshow(f'Camera {camera}', image)
cv2.waitKey(0)
elif operation == 'record':
output_file, duration = args
camera.start_recording(output_file, duration)
# 使用示例
def main():
# 创建多个相机实例
cameras = [
BaslerCameras(interface_type='GigE', width=1920, height=1080, exposure=5000, gain=10),
BaslerCameras(interface_type='USB', width=1920, height=1080, exposure=5000, gain=10)
]
threads = []
# 启动线程来同时操作多个相机
for i, cam in enumerate(cameras):
if i % 2 == 0:
# 每隔一个相机捕捉图像
t = threading.Thread(target=camera_worker, args=(cam, 'capture'))
else:
# 其他相机录制视频
t = threading.Thread(target=camera_worker, args=(cam, 'record', f'output_{i}.avi', 10))
t.start()
threads.append(t)
# 等待所有线程完成
for t in threads:
t.join()
# 释放资源
for cam in cameras:
cam.close()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
python basler 相机调用方法 USB通信 网口通讯 多台相机同时启用
于 2024-08-10 14:47:25 首次发布