尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
SingleTrack_Project(六)传统视觉追踪方法——颜色阈值法
一、基本原理核心思想用目标的颜色特征来定位目标——建立颜色模板然后在后续帧中找到颜色最相似的区域。颜色阈值法不关心目动不动只关注目标的颜色。颜色阈值法不在RGB空间中工作而是在HSV空间中。H色相:决定是什么颜色。S饱和度决定颜色有多纯。V明度决定颜色有多亮。二、关键步骤1.建模版从第一帧的目标区域统计颜色直方图这个直方图就是模板。颜色直方图对图像中颜色分布的统计把每一种颜色的像素数量画成柱状图。2.反投影在后续帧的每个像素上查这个像素的颜色在模板颜色直方图上的匹配度最后生成概率图。3.定位用算法在该旅途中找到最密集的区域就是目标位置。三、关键代码实现1.类结构一初始化class ColorThresholdTracker(BaseTracker): def __init__(self, tracker_namecolor): super().__init__(tracker_name) self.roi_hist None # ROI的颜色直方图目标的颜色模板 self.track_window None # CamShift跟踪窗口 self.prev_bbox None # 上一帧的跟踪框 self.target_area 0 # 目标面积 self.target_aspect 1.0 # 目标宽高比 self.hist_update_count 0 # 直方图更新计数器 self.lost_count 0 # 跟丢计数 # 形态学核椭圆形状5×5 self.kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) # 运动速度用于运动预测 self.velocity np.array([0.0, 0.0]) # 初始框用于窗口退化恢复 self.init_bbox None # 目标模板灰度图用于模板匹配后备 self.target_template None集成状态变量与多种跟踪策略来强化颜色阈值的跟踪效果。2.初始化方法def init(self, frame, bbox): x, y, w, h [int(v) for v in bbox] self.init_bbox (x, y, w, h) self.prev_bbox (x, y, w, h) self.target_area w * h self.target_aspect w / (h 1e-6) # 中心区域采样 # 切除边框15%只取中心区域学颜色 margin_x, margin_y int(w * 0.15), int(h * 0.15) y1 max(0, y margin_y) y2 min(frame.shape[0], y h - margin_y) x1 max(0, x margin_x) x2 min(frame.shape[1], x w - margin_x) hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) roi hsv[y1:y2, x1:x2] # 如果裁剪后为空用整个框 if roi.size 0: roi hsv[y:yh, x:xw] # 排除低饱和度/低亮度像素 mask cv2.inRange(roi, (0, 30, 30), (180, 255, 255)) # 自适应bins h_bins min(60, max(30, w // 5)) s_bins min(64, max(32, h // 5)) self.roi_hist cv2.calcHist([roi], [0, 1], mask, [h_bins, s_bins], [0, 180, 0, 256]) cv2.normalize(self.roi_hist, self.roi_hist, 0, 255, cv2.NORM_MINMAX) self.track_window (x, y, w, h) # 保存灰度模板模板匹配后备用 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) self.target_template gray[y:yh, x:xw] self.trajectory [bbox] self.frame_count 1初始化时做了四件关键事情第一是中心区域采样切除目标框四周 15% 的边缘区域只取中心 70% 的区域来建立颜色模型第二是排除低饱和度/低亮度像素排除它们让颜色模板更纯净第三是自适应bins颜色直方图的分辨率bins 数量根据目标大小自适应大目标像素多对应bins多否则反之第四是保存灰度模板当颜色跟踪和轮廓跟踪都失败时用传统的模板匹配来找目标。3.三层次跟踪策略颜色阈值法设计了 3 层递进的跟踪策略。第一层是CamShift跟踪如果失败则到第二层颜色概率 轮廓筛选如果失败并且跟丢两帧则到模板匹配。第一层CamShift 跟踪def _search_by_camshift(self, frame, margin_scale): hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # ① 反投影计算每个像素属于目标颜色的概率 back_proj cv2.calcBackProject([hsv], [0, 1], self.roi_hist, [0, 180, 0, 256], 1) back_proj cv2.GaussianBlur(back_proj, (5, 5), 0) # 平滑概率图 # ② 运动预测根据历史运动速度预测当前帧的目标位置 pred_window self._predict_window() x, y, w, h pred_window # ③ 扩大搜索区域 margin int(max_dim * margin_scale) # margin_scale 依次为 1.0, 2.0, 4.0 search_window (x-margin, y-margin, w2*margin, h2*margin) # ④ CamShift 算法在概率图上寻找最密集的区域 term_crit (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 15, 1) ret, new_window cv2.CamShift(back_proj, search_window, term_crit) x_new, y_new, w_new, h_new new_window w_new max(15, int(w_new)) # 防止窗口退化到太小 h_new max(15, int(h_new)) # ⑤ 窗口退化恢复 self._recover_window() return (x_new, y_new, w_new, h_new)CamShift 的工作原理1.反投影用目标的颜色直方图扫描整张图像每个像素得到一个颜色匹配度值生成一张概率图2.MeanShift在概率图上从一个起始窗口开始计算窗口内所有像素的质心然后把窗口中心移到质心位置重复直到收敛。3.CamShift MeanShift 窗口自适应每次迭代不仅移动窗口还会根据窗口内像素分布调整窗口的大小和方向第二层颜色概率 轮廓筛选def _search_by_contour(self, frame): hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) prob cv2.calcBackProject([hsv], [0, 1], self.roi_hist, [0, 180, 0, 256], 1) prob cv2.GaussianBlur(prob, (7, 7), 0) # 7×7 高斯滤波更大的平滑核 # 自适应阈值取概率最大值的25%作为阈值 max_prob prob.max() if max_prob 10: return None # 完全没有匹配的颜色 _, thresh cv2.threshold(prob, max(10, max_prob * 0.25), 255, cv2.THRESH_BINARY) # 形态学处理 thresh cv2.morphologyEx(thresh, cv2.MORPH_OPEN, self.kernel, iterations1) thresh cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, self.kernel, iterations2) # 找轮廓 → 筛选 → 评分与帧差法和背景差减法类似 ...当 CamShift 失败时这个方法采用了与帧差法类似的思路——__找轮廓 筛选 评分__但输入不是帧差或运动检测的结果而#x662F;__#x989C;色概率#x56FE;__#x7684;二值化结果。第三层模板匹配def _search_by_template(self, frame): if self.target_template is None: return None gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) th, tw self.target_template.shape # 模板大小初始化时保存的 # 动态扩大搜索范围跟丢越久搜索范围越大 max_dim max(th, tw) margin int(max_dim * (1.0 self.lost_count * 0.5)) # lost_count0: margin1.0倍 # lost_count4: margin3.0倍 search_roi gray[y1:y2, x1:x2] res cv2.matchTemplate(search_roi, self.target_template, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc cv2.minMaxLoc(res) if max_val 0.4: # 匹配度超过0.4才接受 tx, ty max_loc return (x1 tx, y1 ty, tw, th) return None模板匹配是计算机视觉最经典的匹配方法——把第一帧保存的目标图片在后续帧中滑动计算每个位置的相似度找到最像的地方。4.主更新方法def update(self, frame): # 第一步多尺度 CamShift从小范围开始尝试 margins [1.0, 2.0, 4.0] if self.lost_count 3: margins [2.0, 4.0, 8.0] # 丢失后扩大搜索范围 cand None for margin in margins: cand self._search_by_camshift(frame, margin) if cand is not None: break # 找到就停止 # 第二步CamShift 失败 → 轮廓搜索 if cand is None: cand self._search_by_contour(frame) # 第三步都失败且丢失超过2帧 → 模板匹配 if cand is None and self.lost_count 2: cand self._search_by_template(frame) # 都失败了保持上一帧位置 if cand is None: cand self.prev_bbox # 有效性检查 prev_center self._center(self.prev_bbox) new_center self._center(cand) dist np.linalg.norm(new_center - prev_center) max_dim max(self.prev_bbox[2], self.prev_bbox[3]) new_area cand[2] * cand[3] area_ratio new_area / (self.target_area 1e-6) if dist max_dim * 5 and 0.03 area_ratio 12: #有效更新 self.prev_bbox cand self.lost_count 0 # 更新运动速度指数滑动平均 self.velocity 0.6 * self.velocity 0.4 * (new_center - prev_center) # 每5帧更新一次颜色直方图适应光照变化 if self.hist_update_count % 5 0: ... # 从当前帧目标区域重新计算直方图 self.roi_hist 0.8 * self.roi_hist 0.2 * new_hist # 融合更新 else: #候选框不合理视为丢失 self.lost_count 1 self.hist_update_count 1 self.frame_count 1 self.trajectory.append(self.prev_bbox) return self.prev_bbox每 5 帧用当前跟踪结果重新计算直方图然后与旧直方图按 0.8:0.2 融合这使颜色模板能适应缓慢的光照变化又不会因为单帧错误而剧烈变化。四、局限性1.颜色是弱的特征目标可能与其他物体颜色相似2.光照剧烈变化虽然 HSV 做了分离但极端光照变化比如强光直射仍会导致颜色偏移3.目标旋转或形变目标背后和正面的颜色分布可能不同导致匹配失败4.初始化依赖必须从第一帧学颜色如果第一帧目标被部分遮挡颜色模型不完整。
RELATED

相关推荐

零基础落地 OpenClaw 微信私域,环境校验 + 三类部署完整教学

零基础落地 OpenClaw 微信私域,环境校验 + 三类部署完整教学

本文围绕 OpenClaw 2.7.9 展开完整实操讲解,完整覆盖对接微信搭建私域自动化的整套落地流程,包含本地客户端、云服务器容器、命令行脚本三种部署方案,同步配套环境校验标准、运行性能调优参数、各类运行故障排查手段,适配中小团队…

📅 2026/9/12 15:37:06
智谱冲刺AGI,MiniMax获160亿融资

智谱冲刺AGI,MiniMax获160亿融资

📰 每日AI资讯速递 | 2026年7月13日 检索时间范围:近24小时(2026年7月12日-7月13日) 资讯领域:AI智能、机器人、芯片、大模型与应用 精选条数:10条 🔥 今日热点TOP 10 1. 智谱开启"摸高计…

📅 2026/9/7 23:38:17
《为什么京东订单API个人号调不通?企业认证+店铺授权完整流程》(附python源码)

《为什么京东订单API个人号调不通?企业认证+店铺授权完整流程》(附python源码)

京东订单类API(如 jingdong.pop.order.search)属于商家私有数据接口,个人开发者账号在权限体系上被严格限制,这是你调不通的核心原因。必须走企业认证 店铺 OAuth2.0 授权的完整链路才能拿到数据。一、为什么个人号调不通&#x…

📅 2026/9/10 1:10:52
MORE NEWS

更多资讯

📰

Nautilus Trader InstrumentStatus 数据模型详解:从交易所状态事件到策略级处理

Nautilus Trader InstrumentStatus 数据模型详解:从交易所状态事件到策略级处理 【免费下载链接】nautilus_trader Production-grade Rust-native trading engine with deterministic event-driven architecture 项目地址: https://gitcode.com/GitHub_Trending/n…

📰

GEO媒体资源平台推荐:四大平台实测对比让选型不再纠结

问 AI 助手"这行哪家靠谱"的人,正在变得比敲搜索框的人更多。对企业来说,这意味着过去靠页面位次承接的流量,如今要在几段回答文字里被提到才算拿到手。回答里会不会提到你,很大程度取决于你的内容有没有被发到模型愿意…

📰

基于Python的汽车数据分析大屏可视化实现指南

简介:这是一套基于Python的汽车数据分析大屏可视化系统完整项目代码,主要面向毕业设计、期末大作业与课程设计等场景,也适合希望从完整案例入手学习数据分析可视化开发的Python初学者。项目围绕汽车数据的获取、清洗、统计与可视化展示展开&a…

📰

工控机型号解码:从命名规则看硬件能力与产线适配

1. 工控机不是“加了铁壳的电脑”,它是工业现场的神经节点 很多人第一次听说工控机,下意识觉得就是“把普通电脑塞进个厚铁盒里,再加个风扇”。我刚入行那会儿也这么想,直到在一家汽车焊装车间调试PLC通信模块——那台标着“研华A…

📰

AI SDK 的 Groq 集成包 @ai-sdk/groq:能力全景、核心实现与版本演进深度解析

AI SDK 的 Groq 集成包 ai-sdk/groq:能力全景、核心实现与版本演进深度解析 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents 项…

📰

广告行业认知迭代与实战学习系统搭建

1. 项目概述:为什么广告老板越忙越穷? 在广告行业摸爬滚打多年,我发现一个有趣的现象:许多广告公司老板每天工作16小时,周末无休,团队规模不断扩大,但年底结算时利润却不见增长。这种现象我称之…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬