OpenCV 光流法原理与实战指南:从 Lucas-Kanade 到稠密光流

前言 在计算机视觉的众多技术中,光流法(Optical Flow)可以说是最古老也最具生命力的算法之一。从 1950 年代心理学家 Gibson 首次提出视觉运动感知理论,到 1981 年 Lucas 和 Kanade 发表那篇经典论文,再到今天深度学习时代的 RAFT、GMFlow 等现代光流网络,这项技术已经走过了半个多世纪的历程。 我第一次接触光流法是在大学的计算机视觉课程上。当时教授在黑板上写下那个著名的光流方程 Iₓu + Iᵧv + Iₜ = 0,然后告诉我们:“这个简单的方程,蕴含了理解运动的全部秘密。” 那时候我还不太理解这句话的含义,直到后来在实际项目中用它实现了一个简单的视频目标跟踪系统,才真正体会到光流法的强大之处。 在今天的边缘计算和嵌入式 AI 场景中,光流法依然占据着不可替代的地位。相比于深度学习的目标跟踪算法,传统光流法具有以下优势: 计算量小:不需要复杂的神经网络,可以在资源受限的嵌入式设备上实时运行 无需训练:不需要标注数据,开箱即用 实时性好:很多优化后的实现可以轻松达到 30 FPS 以上 适用范围广:从无人机的视觉导航,到视频防抖,再到动作识别,光流法无处不在 本文将带您从零开始深入理解光流法的原理,从最基本的亮度恒定假设,到经典的 Lucas-Kanade 算法,再到 OpenCV 中的各种光流法实现。我们会通过大量代码示例,让您不仅理解理论,更能在实际项目中应用这项技术。 一、什么是光流法? 1.1 光流的定义 简单来说,光流就是空间中运动物体在成像平面上像素运动的瞬时速度。当你盯着窗外行驶的汽车时,视网膜上汽车图像的移动速度就是光流。 更正式的定义是:给定图像序列 I(x, y, t),光流法的目标是为每个像素点 (x, y) 找到一个速度向量 (u, v),使得: I ( x , y , t ) = I ( x + u · d t , y + v · d t , t + d t ) 这个等式表达的就是:经过微小的时间间隔 dt 后,像素点 (x, y) 移动到了 (x + u·dt, y + v·dt),而亮度保持不变。 ...

May 22, 2026 · 9 min · 👁️ 0 · Tech Snippets

基于 RK3506 的高效图像识别开发完整指南

前言 在嵌入式 AI 应用日益普及的今天,如何在成本、性能和功耗之间找到最佳平衡点,是每一个嵌入式开发者都需要面对的问题。瑞芯微 RK3506 作为一款面向工业控制、智能语音和多媒体交互场景的高性价比芯片,凭借其三核 Cortex-A7 架构和 2D 硬件加速能力,为边缘端的图像识别应用提供了全新的可能性。 本文将从零开始,完整介绍如何基于 RK3506 芯片进行高效的图像识别开发,包括开发环境的搭建、工具链的配置、图像采集与预处理、推理引擎的部署、调试方法以及性能优化的最佳实践。所有步骤均经过实际验证,确保读者可以按照本文一步步实现自己的图像识别应用。 一、RK3506 芯片概述 1.1 芯片核心规格 RK3506 是瑞芯微推出的一款面向工业级应用的高性价比 SoC,其核心规格如下: 规格项 参数说明 CPU 架构 三核 ARM Cortex-A7,主频可动态调节 2D 加速 内置 2D 硬件加速器,支持 1280x1280@60fps 显示输出 显示接口 MIPI DSI,支持高清显示屏 网络接口 双路 100M 以太网 工业总线 CAN FD 音频接口 PDM 麦克风输入,支持语音应用 工作温度 -40°C ~ 85°C 工业级温度范围 GPIO 40 引脚 Raspberry Pi 兼容接口 1.2 为什么选择 RK3506 做图像识别? 很多开发者可能会问:RK3506 没有内置 NPU,为什么要用它来做图像识别?答案在于以下几个方面: 第一,极致的成本控制。 在很多工业场景中,并不需要运行复杂的大模型,只需要完成特定的视觉任务,比如二维码识别、颜色检测、简单的物体分类等。对于这些应用,RK3506 的三核 CPU 完全能够胜任,而成本相比带 NPU 的芯片要低得多。 ...

April 25, 2026 · 8 min · 👁️ 4 · Tech Snippets

基于 OpenCV 的红色物体识别与多目标跟踪实战

前言 在计算机视觉领域,颜色检测是最基础也最实用的技术之一。红色作为一种醒目的颜色,在交通标志、安全警示、工业自动化等场景中应用广泛。今天我们来深入探讨如何用 OpenCV 实现红色物体的识别,并在此基础上实现多目标跟踪功能。 这篇文章不是简单的 API 调用演示,而是从原理出发,结合实际场景中的问题,一步步构建一个健壮的检测与跟踪系统。我们会遇到光照变化、噪声干扰、部分遮挡等实际问题,然后逐一解决。 一、为什么选择 HSV 颜色空间? 当我们谈论颜色检测时,很多新手第一反应是直接在 RGB 图像上做阈值处理。比如,红色物体的 R 通道值比较高,那么我们设定一个阈值,只保留 R > 200 的像素。但实际一试就会发现,这种方法效果非常差。 问题出在哪里?RGB 颜色空间虽然直观,但它把亮度和颜色信息混在一起了。同一个红色物体,在强光下和阴影下,RGB 值可能差异巨大,但人眼感知到的颜色其实是一样的。这就导致基于 RGB 的阈值检测非常不稳定。 这时候 HSV 颜色空间就派上用场了。HSV 把颜色信息分解成三个独立的通道: H (Hue, 色调):表示颜色的种类,取值范围在 OpenCV 中是 0-179 S (Saturation, 饱和度):表示颜色的鲜艳程度,0-255 V (Value, 明度):表示颜色的明亮程度,0-255 HSV 的优势在于,颜色信息主要由 H 通道决定,而 V 通道单独控制亮度。这意味着,即使光线变化导致 V 值波动,只要 H 值在我们设定的红色范围内,我们仍然能稳定地检测到目标。 二、红色在 HSV 空间中的特殊性 红色有个有意思的特性:它在色相环的两端都有分布。在标准的 0-360 度色相环中,红色出现在 0 度附近和 360 度附近。OpenCV 为了用 8 位表示,把这个范围减半成了 0-179,所以红色就分布在 0-10 和 170-179 这两个区间。 ...

April 23, 2026 · 6 min · 👁️ 3 · Tech Snippets

实时检测指定颜色和形状的物体:算法方案对比与实现

引言 在工业检测、机器人视觉、智能分拣等应用场景中,我们经常需要实时检测特定颜色和形状的物体。例如: 冰壶比赛自动计分系统:检测冰面上的圆形冰壶 工业零件分拣:检测红色圆形螺丝、蓝色方形螺母 自动驾驶交通标志识别:检测圆形红圈禁令标志 AGV 小车导航:识别地面彩色圆形二维码 本文将从简单到复杂,介绍几种常见的实现方案,对比它们的性能,并提供完整的开源参考代码,帮助你根据实际场景选择最合适的方案。 方案对比总览 我们主要对比四种主流方案: 方案 原理 计算量 准确率 适合场景 MCU 能否运行 颜色分割 + 轮廓检测 阈值分割 + 形状分析 极低 对颜色形状变化敏感 背景简单、光照稳定 ✅ Cortex-M7 可以 颜色空间转换 + Hough 变换 Hough 圆/直线检测 低 圆形检测较好 固定形状检测 ✅ Cortex-M4 可以 Blob 分析 + 特征匹配 连通域分析 + 形状分类 中 中等 多目标批量处理 ✅ Cortex-M7 可以 深度学习目标检测 YOLO/SSD 直接检测 高 鲁棒性强 复杂背景、光照变化 ❌ 需要 MCU+NPU 或 Linux 下面详细介绍每种方案的实现。 方案一:颜色分割 + 轮廓检测 1.1 算法流程 原始图像 RGB/BGR 颜色空间转换 RGB → HSV 颜色阈值分割 二值掩码 形态学处理 腐蚀 + 膨胀 查找轮廓 cv2.findContours 形状特征计算 面积、周长、圆形度 输出:符合颜色和形状要求的目标 颜色分割 + 轮廓检测流程图 1.2 核心原理 颜色空间转换:从 RGB 转到 HSV 颜色空间,更容易按颜色分割 阈值分割:对 H/S/V 三个通道设置范围,得到二值掩码 形态学处理:腐蚀 + 膨胀去除噪声 轮廓查找:找到所有连通区域 形状特征计算:计算面积、周长、圆形度、矩形度等特征 特征匹配:筛选符合指定形状的目标 1.3 完整 Python 实现 import cv2 import numpy as np def detect_color_shape( image, color_lower=np.array([0, 120, 70]), color_upper=np.array([10, 255, 255]), shape_type="circle", min_area=100, max_area=10000, circularity_threshold=0.8, aspect_ratio_range=(0.9, 1.1) ): """ 检测指定颜色和形状的物体 参数: image: 输入 RGB/BGR 图像 color_lower: HSV 颜色下限 color_upper: HSV 颜色上限 shape_type: "circle" / "square" / "rectangle" min_area: 最小面积(像素) max_area: 最大面积(像素) circularity_threshold: 圆形度阈值(0~1,越大越圆) aspect_ratio_range: 宽高比范围(方形接近 1) 返回: detections: 检测结果列表 [(x, y, w, h, contour), ...] mask: 颜色分割掩码(用于调试) """ # 1. 颜色空间转换:BGR → HSV hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 2. 颜色阈值分割 mask = cv2.inRange(hsv, color_lower, color_upper) # 3. 形态学处理去除噪声 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 4. 查找轮廓 contours, hierarchy = cv2.findContours( mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) detections = [] for contour in contours: # 计算轮廓面积,过滤太小/太大的 area = cv2.contourArea(contour) if area < min_area or area > max_area: continue # 计算轮廓周长 perimeter = cv2.arcLength(contour, True) # 多边形逼近 approx = cv2.approxPolyDP(contour, 0.04 * perimeter, True) # 获取外接矩形 x, y, w, h = cv2.boundingRect(contour) # 形状判断 matched = False if shape_type == "circle": # 圆形度 = 4π * 面积 / (周长^2) # 完美圆形 = 1,越不规则值越小 circularity = 4 * np.pi * area / (perimeter * perimeter) if circularity >= circularity_threshold: matched = True elif shape_type == "square": # 宽高比接近 1,且顶点数约为 4 aspect_ratio = float(w) / h if (len(approx) == 4 and aspect_ratio >= aspect_ratio_range[0] and aspect_ratio <= aspect_ratio_range[1]): matched = True elif shape_type == "rectangle": # 顶点数约为 4 即可 if len(approx) == 4: matched = True elif shape_type == "triangle": if len(approx) == 3: matched = True if matched: center_x = x + w // 2 center_y = y + h // 2 detections.append((center_x, center_y, w, h, contour)) return detections, mask 1.4 使用示例 # 检测红色圆形物体 # HSV 红色范围(两种分段,因为红色在 H 通道首尾) lower_red1 = np.array([0, 120, 70]) upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 120, 70]) upper_red2 = np.array([180, 255, 255]) # 读取图像 image = cv2.imread("test_image.jpg") # 第一次检测 detections1, mask1 = detect_color_shape( image, lower_red1, upper_red1, shape_type="circle", min_area=500 ) # 第二次检测(另一红色区间) detections2, mask2 = detect_color_shape( image, lower_red2, upper_red2, shape_type="circle", min_area=500 ) # 合并结果 all_detections = detections1 + detections2 combined_mask = mask1 | mask2 # 在原图上绘制结果 for (x, y, w, h, contour) in all_detections: cv2.drawContours(image, [contour], -1, (0, 255, 0), 2) cv2.circle(image, (x, y), 3, (0, 0, 255), -1) cv2.putText(image, "Red Circle", (x-20, y-h-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imwrite("result.jpg", image) print(f"检测到 {len(all_detections)} 个红色圆形物体") 1.5 常见颜色 HSV 范围参考 颜色 H 下限 H 上限 S 下限 S 上限 V 下限 V 上限 红色 0/170 10/180 120 255 70 255 橙色 11 25 120 255 70 255 黄色 26 35 120 255 70 255 绿色 36 70 120 255 70 255 青色 71 99 120 255 70 255 蓝色 100 124 120 255 70 255 紫色 125 155 120 255 70 255 粉色 156 169 120 255 70 255 黑色 0 180 0 255 0 46 灰色 0 180 0 43 47 221 白色 0 180 0 30 222 255 注意:不同相机的白平衡和亮度设置不同,实际使用时需要根据你的图像微调范围。建议用 OpenCV 窗口滑动条调参: ...

April 15, 2026 · 8 min · 👁️ 3 · Tech Snippets