如何用OpenCV Python实时提取视频中未知范围的主导色
实时提取视频主导色并可视化的解决方案
核心思路
不用固定颜色检测或手动设置HSV范围,改用K-Means聚类算法自动从视频帧的像素中分组出占比最高的颜色。聚类能根据当前帧的像素分布自动识别主导色,完全适配未知颜色范围的视频。
原代码的问题
- 循环内重复创建
VideoCapture实例,会导致资源浪费且无法正常读取帧 - 冗余读取本地图片
taxi.jpeg,对视频处理无意义 - 仅计算单通道(B通道)的直方图,无法获取多通道的整体主导色
- 直接用
cv.imshow显示plt对象是错误用法,两者渲染逻辑不兼容
完整实现代码
import cv2 as cv import numpy as np from sklearn.cluster import KMeans from collections import Counter # 设置参数:要提取的主导色数量 TOP_COLORS = 3 # 可改为6或其他数字 def get_dominant_colors(frame, num_colors): # 将BGR转RGB,并扁平化像素数据 rgb_frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) pixels = rgb_frame.reshape(-1, 3) # K-Means聚类 kmeans = KMeans(n_clusters=num_colors) labels = kmeans.fit_predict(pixels) # 计算每个颜色的占比 color_counts = Counter(labels) total_pixels = len(pixels) color_info = [] for label, count in color_counts.items(): color = kmeans.cluster_centers_[label].astype(int) percentage = (count / total_pixels) * 100 color_info.append((color, percentage)) # 按占比从高到低排序 color_info.sort(key=lambda x: x[1], reverse=True) return color_info def plot_color_blocks(color_info): # 创建颜色块画布 block_width = 100 block_height = 300 canvas = np.zeros((block_height, len(color_info)*block_width, 3), dtype=np.uint8) for i, (color, percentage) in enumerate(color_info): start_x = i * block_width canvas[:, start_x:start_x+block_width] = color[::-1] # RGB转回BGR给OpenCV显示 # 添加占比文字 cv.putText(canvas, f"{percentage:.1f}%", (start_x + 10, block_height//2), cv.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 2) return canvas # 初始化视频捕获:0为摄像头,替换为视频路径则读取本地视频 vid = cv.VideoCapture(0) while True: ret, frame = vid.read() if not ret: break # 视频结束或读取失败 # 获取主导色 dominant_colors = get_dominant_colors(frame, TOP_COLORS) # 生成颜色块显示图 color_canvas = plot_color_blocks(dominant_colors) # 显示原视频和颜色块 cv.imshow("Original Video", frame) cv.imshow("Dominant Colors", color_canvas) # 按q退出 if cv.waitKey(1) & 0xFF == ord('q'): break # 释放资源 vid.release() cv.destroyAllWindows()
代码说明
get_dominant_colors函数:负责将帧像素扁平化,用K-Means聚类得到指定数量的主导色,并计算每个颜色的占比plot_color_blocks函数:生成包含颜色块和占比文字的画布,方便和视频同步显示- 支持切换摄像头/本地视频:把
cv.VideoCapture(0)的参数换成视频文件路径即可 - 可调整
TOP_COLORS变量来提取前N种主导色
注意事项
- 需要提前安装依赖:
pip install opencv-python scikit-learn numpy - 若实时性要求高,可适当降低视频分辨率(比如用
cv.resize缩小帧),减少K-Means的计算量
内容的提问来源于stack exchange,提问作者plus
相关产品推荐
相关产品推荐

