如何从nvarguscamerasrc的3840x2160流获取1280x1280帧且不缩放?
解决nvarguscamerasrc输出1280x1280帧出现黑边的问题
问题核心:你的相机源是3840x2160(16:9宽高比),nvarguscamerasrc默认会按原比例缩放,指定输出1280宽度时,高度只能对应到720,剩余区域填充黑边。要得到无黑边的1280x1280帧,需先将源帧裁剪为正方形,再缩放到目标分辨率。
修改gstreamer pipeline配置
在JetsonCamera.py的gstreamer_pipeline函数中,添加裁剪和强制缩放逻辑,具体代码如下:
def gstreamer_pipeline( capture_width=3840, capture_height=2160, display_width=1280, display_height=1280, framerate=30, flip_method=0, ): # 从3840x2160源帧裁剪中间2160x2160的正方形区域 crop_left = (capture_width - capture_height) // 2 return ( "nvarguscamerasrc ! " f"video/x-raw(memory:NVMM), width=(int){capture_width}, height=(int){capture_height}, framerate=(fraction){framerate}/1 ! " f"nvvidconv flip-method={flip_method} ! " f"video/x-raw(memory:NVMM), width=(int){capture_height}, height=(int){capture_height}, " f"cropleft={crop_left}, croptop=0, cropwidth={capture_height}, cropheight={capture_height} ! " f"nvvidconv ! " f"video/x-raw, width=(int){display_width}, height=(int){display_height}, format=(string)BGRx ! " "videoconvert ! " "video/x-raw, format=(string)BGR ! " "appsink" )
调整Camera类初始化逻辑
确保Camera类使用修改后的pipeline,示例代码:
class Camera: def __init__(self, width=1280, height=1280, framerate=30, flip_method=0): self.width = width self.height = height self.pipeline = gstreamer_pipeline( capture_width=3840, capture_height=2160, display_width=width, display_height=height, framerate=framerate, flip_method=flip_method ) self.cap = cv2.VideoCapture(self.pipeline, cv2.CAP_GSTREAMER) if not self.cap.isOpened(): raise RuntimeError("Failed to open camera") self.frame_reader = FrameReader(self.cap) self.frame_reader.start()
FrameReader线程类无需额外修改
只要Camera类的pipeline正确输出1280x1280的BGR帧,线程读取逻辑保持原样即可:
class FrameReader(threading.Thread): def __init__(self, cap): super().__init__() self.cap = cap self.frame = None self.running = True def run(self): while self.running: ret, frame = self.cap.read() if ret: self.frame = frame def stop(self): self.running = False self.join()
main.py调用逻辑保持匹配
确保请求的分辨率与Camera初始化参数一致:
from JetsonCamera import Camera if __name__ == "__main__": try: camera = Camera(width=1280, height=1280) while True: frame = camera.frame_reader.frame if frame is not None: # 处理1280x1280帧 cv2.imshow("Camera Output", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break finally: camera.frame_reader.stop() camera.cap.release() cv2.destroyAllWindows()
关键逻辑说明
- 裁剪正方形区域:从3840x2160源帧中裁剪中间2160x2160的正方形(左右各裁840像素),得到1:1比例的原始帧。
- 强制缩放:将裁剪后的2160x2160帧缩放到1280x1280,因源与目标均为1:1比例,不会出现黑边。
- 硬件加速:全程使用
memory:NVMM格式,利用Jetson硬件加速避免性能损耗。
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

