Python调用OpenCV时,如何抑制C++库输出到stdout的消息?
如何抑制OpenCV中estimateChessboardSharpness的stdout输出?
问题背景
调用OpenCV的estimateChessboardSharpness函数时,若棋盘格尺寸过小,该函数会通过C层直接向stdout打印消息:calcEdgeSharpness: checkerboard too small for calculation.。已提交PR修复该问题,但需要临时抑制这条输出。
已尝试但无效的方法
- 使用
contextlib.redirect_stdout将输出重定向到None或/dev/null - 尝试重定向
stderr替代stdout - 在导入
cv2前设置OPENCV_LOG_LEVEL为SILENT
问题复现代码
import cv2 import numpy as np img = np.zeros((512, 640), dtype='uint8') corners = [] for i in range(10): for j in range(8): corner = (30 + 3 * j, 70 + 3 * i) if i and j: corners.append(corner) if (i % 2) ^ (j % 2): img[corner[0]:corner[0] + 3, corner[1]:corner[1] + 3] = 255 corners = np.array(corners)
执行以下代码时会触发输出:
>>> cv2.estimateChessboardSharpness(img, (9, 7), corners) calcEdgeSharpness: checkerboard too small for calculation. ((9999.0, 9999.0, 9999.0, 9999.0), None)
已尝试的抑制代码(均无效)
from contextlib import redirect_stdout from os import devnull import sys with redirect_stdout(None): cv2.estimateChessboardSharpness(img, (9, 7), corners) with open(devnull, "w") as null, redirect_stdout(null): cv2.estimateChessboardSharpness(img, (9, 7), corners) sys.stdout = open(devnull, "w") cv2.estimateChessboardSharpness(img, (9, 7), corners)
有效解决方案
由于这条输出是OpenCV的C层代码直接写入底层文件描述符,而非通过Python的sys.stdout,因此需要通过操作系统级别的文件描述符重定向来拦截。
单次调用实现
import os import cv2 # 保存原始stdout的文件描述符 original_stdout = os.dup(1) # 打开/dev/null devnull = os.open(os.devnull, os.O_WRONLY) # 将stdout重定向到/dev/null os.dup2(devnull, 1) # 调用目标函数,此时不会输出消息 result = cv2.estimateChessboardSharpness(img, (9, 7), corners) # 恢复原始stdout os.dup2(original_stdout, 1) # 关闭打开的文件描述符 os.close(devnull) os.close(original_stdout) # 正常打印结果 print(result)
封装为上下文管理器(复用更方便)
import os from contextlib import contextmanager @contextmanager def suppress_c_stdout(): # 保存原始stdout描述符 original_stdout = os.dup(1) # 打开/dev/null devnull = os.open(os.devnull, os.O_WRONLY) # 重定向stdout os.dup2(devnull, 1) try: yield finally: # 恢复原始stdout os.dup2(original_stdout, 1) # 清理文件描述符 os.close(devnull) os.close(original_stdout) # 使用方式 with suppress_c_stdout(): result = cv2.estimateChessboardSharpness(img, (9, 7), corners) print(result)
原理说明
Python的redirect_stdout仅修改了Python解释器层面的sys.stdout对象,而OpenCV的C代码直接操作的是操作系统提供的文件描述符(对应stdout的句柄),两者不属于同一层级,因此Python层面的重定向无法拦截C层的输出。通过os.dup2直接修改文件描述符的指向,才能从底层拦截这类输出。
内容的提问来源于stack exchange,提问作者Mad Physicist
相关产品推荐
相关产品推荐

