**非常详细的视频和文字教程,讲解常见的openmv教程包括 巡线、物体识别、圆环识别、阈值自动获取等。非常适合学习openmv、K210、K230等项目
视频合集链接在
openmv教程合集 openmv入门到项目开发 openmv和STM32通信 openmv和opencv区别 openmv巡线 openmv数字识别教程LCD
3.6.3-通过颜色区域+霍夫变换检测圆形+三种颜色阈值设置
- 通过颜色阈值分割找到目标颜色的区域。
- 在目标区域内使用霍夫变换检测圆形。
- 使用卡尔曼滤波器对检测到的圆环位置进行预测和跟踪。
- 将预测的圆心和圆环限制在目标颜色框内。
import sensor, image, time, math
from ulab import numpy as np
#教程作者:好家伙VCC
#欢迎交流群QQ: 771027961 作者邮箱: 1930299709@qq.com
#更多教程B站主页:[好家伙VCC的个人空间-好家伙VCC个人主页-哔哩哔哩视频](https://space.bilibili.com/434192043)
#淘宝主页链接:[首页-好家伙VCC-淘宝网](https://shop415231378.taobao.com)
#更多嵌入式手把手教程-尽在好家伙VCC
# ******************** 参数配置 ********************
# 颜色阈值配置(LAB格式)
color_thresholds = {
'red': (0, 100, 0, 127, 0, 127),
'green': (0, 100, -128, -10, 0, 127),
'blue': (0, 100, -128, 127, -128, -10)
}
# 当前目标颜色(按需切换)
target_color = 'red'
# 霍夫变换参数
HOUGH_THRESHOLD = 2000 # 检测灵敏度(值越高要求边缘越明显)
MIN_RADIUS = 10 # 最小半径(根据实际调整)
MAX_RADIUS = 50 # 最大半径(根据实际调整)
# 卡尔曼滤波参数
TS = 1/60 # 帧时间(假设帧率22fps)
# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.set_vflip(True)
sensor.set_hmirror(True)
sensor.skip_frames(2000)
#sensor.set_auto_gain(False)
#sensor.set_auto_whitebal(False)
clock = time.clock()
# ******************** 卡尔曼滤波器类 ********************
class KalmanFilter:
def __init__(self, initial_state):
# 状态转移矩阵
self.A = np.array([
[1, 0, 0, 0, TS, 0],
[0, 1, 0, 0, 0, TS],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1]
])
# 观测矩阵
self.C = np.eye(6)
# 过程噪声
self.Q = np.diag([1e-6]*6)
# 观测噪声
self.R = np.diag([1e-6]*6)
# 初始状态
self.x_hat = initial_state
self.p = np.diag([10]*6)
def update(self, Z):
# 预测步骤
x_hat_minus = np.dot(self.A, self.x_hat)
p_minus = np.dot(self.A, np.dot(self.p, self.A.T)) + self.Q
# 更新步骤
S = np.dot(self.C, np.dot(p_minus, self.C.T)) + self.R
S_inv = np.linalg.inv(S + 1e-4*np.eye(6))
K = np.dot(np.dot(p_minus, self.C.T), S_inv)
self.x_hat = x_hat_minus + np.dot(K, (Z - np.dot(self.C, x_hat_minus)))
self.p = np.dot((np.eye(6) - np.dot(K, self.C)), p_minus)
return self.x_hat
# 初始化三个卡尔曼滤波器(分别对应红、绿、蓝)
kf_red = KalmanFilter(np.array([80, 60, 30, 30, 2, 2]))
kf_green = KalmanFilter(np.array([80, 60, 30, 30, 2, 2]))
kf_blue = KalmanFilter(np.array([80, 60, 30, 30, 2, 2]))
# ******************** 主循环 ********************
while True:
clock.tick()
img = sensor.snapshot().lens_corr(1.8)
# ===== 在画幅中心绘制小圆环标志 =====
img.draw_circle(80, 60, 5, color=(0, 0, 0), thickness=1) # 黑色小圆环,半径5像素
# 第一步:颜色阈值分割
blobs = img.find_blobs([color_thresholds[target_color]], merge=True, margin=10)
if blobs:
# 取最大的色块
largest_blob = max(blobs, key=lambda b: b.area())
img.draw_rectangle(largest_blob.rect(), color=(255,0,0))
# 第二步:在色块ROI内检测圆形
roi = (largest_blob.x(), largest_blob.y(), largest_blob.w(), largest_blob.h())
circles = img.find_circles(
threshold=HOUGH_THRESHOLD,
x_margin=10,
y_margin=10,
r_margin=10,
r_min=MIN_RADIUS,
r_max=MAX_RADIUS,
roi=roi # 限制检测区域
)
if circles:
# 筛选同心圆:取半径最大的圆(假设最外层是目标)
valid_circles = []
for c in circles:
# 检查是否在色块中心附近
if abs(c.x() - largest_blob.cx()) < 15 and abs(c.y() - largest_blob.cy()) < 15:
valid_circles.append(c)
if valid_circles:
target = max(valid_circles, key=lambda c: c.r())
x, y, r = target.x(), target.y(), target.r()
img.draw_circle(x, y, r, color=(0,255,0))
# 更新卡尔曼滤波器
Z = np.array([x, y, 2*r, 2*r, 0, 0])
if target_color == 'red':
kf_red.update(Z)
elif target_color == 'green':
kf_green.update(Z)
elif target_color == 'blue':
kf_blue.update(Z)
# 输出卡尔曼滤波预测的圆心坐标
print("卡尔曼预测坐标: X={}, Y={}, R={}".format(int(state[0]), int(state[1]), int(state[2]/2)))
# 绘制预测结果
if target_color == 'red':
state = kf_red.x_hat
elif target_color == 'green':
state = kf_green.x_hat
else:
state = kf_blue.x_hat
pred_x = int(state[0])
pred_y = int(state[1])
pred_r = int(state[2]/2)
# === 新增:约束圆心在目标颜色框内 ===
if blobs:
# 获取目标颜色框的边界
blob_x, blob_y, blob_w, blob_h = largest_blob.rect()
# 约束圆心在框内
pred_x = max(blob_x, min(blob_x + blob_w, pred_x))
pred_y = max(blob_y, min(blob_y + blob_h, pred_y))
# 约束半径不超过框的大小
pred_r = min(pred_r, min(blob_w, blob_h) // 2)
# 绘制约束后的圆心和圆
img.draw_cross(pred_x, pred_y, color=(255,0,0))
img.draw_circle(pred_x, pred_y, pred_r, color=(255,255,0))
print("FPS:", clock.fps())