如何为cv2视频添加可生效的trackbar实现指定颜色保留灰度滤镜
问题核心原因
你的代码存在4个关键问题导致滑块调节无效果:
- 显示优先级冲突:trackbar回调生成的滤镜帧,会被主循环最后执行的
cv2.imshow('video', frame)直接覆盖,滑动滑块的瞬间看到效果也会立刻被下一帧的原始画面顶掉 - 未定义函数报错:主循环调用的
show_change()函数不存在,代码实际运行会直接抛出异常 - 灰度化逻辑错误:你误将BGR转HSV的结果当做灰度图,二者色彩空间完全不匹配,无法实现灰度效果
- 全局变量异常修改:回调中直接修改全局frame的尺寸,会导致帧被反复缩小,画面会持续变糊
修复思路
不要把滤镜渲染逻辑放在trackbar回调里,回调仅在滑块拖动时触发,而视频播放时每一帧都需要应用当前滑块的色相参数。直接在主循环的每帧渲染逻辑中读取滑块参数、生成滤镜效果即可。
修复后可运行代码
import cv2 import sys import numpy as np import os FILE_PATH = os.path.dirname(os.path.abspath(__file__)) video = cv2.VideoCapture(FILE_PATH +'/city_ex.mp4') if not video.isOpened(): print("Video Open Failed") sys.exit() # 空回调即可,不需要在回调里做渲染 def empty_callback(pos): pass cv2.namedWindow('video') cv2.createTrackbar('Hue_min', 'video', 0, 179, empty_callback) cv2.createTrackbar('Hue_max', 'video', 0, 179, empty_callback) while True: ret, frame = video.read() if not ret: break # 统一缩小帧尺寸,避免反复修改全局变量 h, w = frame.shape[:2] frame = cv2.resize(frame, (w//2, h//2)) # 读取当前滑块参数 hue_min = cv2.getTrackbarPos('Hue_min', 'video') hue_max = cv2.getTrackbarPos('Hue_max', 'video') # 生成色相掩码 frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask = cv2.inRange(frame_hsv, (hue_min, 0, 0), (hue_max, 255, 255)) mask_inv = cv2.bitwise_not(mask) # 保留选中色相的彩色部分 colored_portion = cv2.bitwise_and(frame, frame, mask=mask) # 生成其余部分的灰度效果:转灰度后堆叠为3通道才能和彩色部分合并 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray_3ch = np.stack((gray,)*3, axis=-1) gray_portion = cv2.bitwise_and(gray_3ch, gray_3ch, mask=mask_inv) # 合并两部分 combined = colored_portion + gray_portion # 直接显示处理后的帧即可,不需要额外回调渲染 cv2.imshow('video', combined) key = cv2.waitKey(1) if key == 27: break video.release() cv2.destroyAllWindows()
运行说明
拖动Hue_min和Hue_max滑块即可调整保留的色相范围,比如要保留红色可以把范围设为0-10/170-179,要保留绿色设为35-77即可。
内容的提问来源于stack exchange,提问作者Ahoy Munnow
相关产品推荐
相关产品推荐

