
什么是 CanMV K230?
CanMV K230是一款高性价比的RISC-V边缘AI平台,凭借低功耗、强视觉处理能力和开放的开发生态,成为嵌入式AI开发的理想选择,尤其适合需要快速部署视觉与AI功能的创客、中小企业及教育场景。CanMV 是一套 AI 视觉开发平台,K230 是其核心芯片。该模块结合了图像采集、AI推理、边缘计算等能力,适合嵌入式视觉应用开发。
CanMV:类似 OpenMV 的图像处理框架,支持 Python 编程,简化视觉识别开发流程。
K230 芯片:嘉楠科技推出的 AIoT SoC,采用 RISC-V 架构,内置第三代 KPU(AI加速单元),算力高达 6 TOPS,性能是 K210 的 13.7 倍。

知识点
颜色识别是计算机视觉中基于像素色彩特征的基础任务,核心是从图像中筛选出特定颜色的区域(如红色路标、绿色零件),通过 “颜色空间转换 + 阈值分割” 实现,适配简单场景的快速识别,也是巡线、物体分类等任务的基础。
1、核心原理
颜色识别的关键是 “用合适的颜色空间描述颜色,并通过阈值筛选目标颜色”,核心逻辑:
颜色空间转换:将图像从默认的 RGB 空间,转换为更适合颜色分割的空间(如 HSV、HSL),减少光照变化的影响。
阈值设定:在目标颜色空间中,定义目标颜色的范围(如 HSV 中红色的 hue、saturation、value 区间)。
阈值分割:筛选出颜色落在目标范围内的像素,生成二值掩码(目标区域为白色,其他为黑色)。
后处理:通过形态学操作优化掩码,提取目标区域的轮廓或位置。
2、主流颜色空间(按实用性分类)

3、实操示例(OpenCV+HSV 颜色识别,适配 K230)
HSV 空间抗干扰性最优,以下代码支持实时识别单一颜色(以红色为例),可直接替换为其他颜色:
python
import cv2
import numpy as np
def get_color_range(color):
"""获取常见颜色的HSV阈值范围(OpenCV格式)"""
color_ranges = {
"red": [(0, 120, 70), (10, 255, 255), (160, 120, 70), (179, 255, 255)], # 红色分两段(HSV中红跨0°)
"green": [(35, 120, 70), (77, 255, 255)],
"blue": [(100, 120, 70), (130, 255, 255)],
"yellow": [(20, 120, 70), (34, 255, 255)],
"orange": [(11, 120, 70), (19, 255, 255)]
}
return color_ranges.get(color.lower(), [(0,0,0), (0,0,0)])
# 初始化K230摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
target_color = "red" # 可改为 green/blue/yellow/orange
color_ranges = get_color_range(target_color)
if not cap.isOpened():
print("摄像头打开失败")
exit()
while True:
ret, frame = cap.read()
if not ret:
break
img_copy = frame.copy()
# 1. 转换为HSV颜色空间
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# 2. 生成颜色掩码(红色分两段,其他颜色一段)
if target_color == "red":
mask1 = cv2.inRange(hsv, np.array(color_ranges[0]), np.array(color_ranges[1]))
mask2 = cv2.inRange(hsv, np.array(color_ranges[2]), np.array(color_ranges[3]))
mask = cv2.bitwise_or(mask1, mask2)
else:
mask = cv2.inRange(hsv, np.array(color_ranges[0]), np.array(color_ranges[1]))
# 3. 形态学优化:去除噪声、连接断裂区域
kernel = np.ones((5, 5), np.uint8)
mask = cv2.erode(mask, kernel, iterations=1)
mask = cv2.dilate(mask, kernel, iterations=2)
# 4. 提取目标颜色区域的轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 5. 绘制识别结果
for cnt in contours:
if cv2.contourArea(cnt) > 1000: # 过滤小噪声
# 绘制轮廓和外接矩形
cv2.drawContours(img_copy, [cnt], -1, (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img_copy, (x, y), (x+w, y+h), (255, 0, 0), 2)
# 标注颜色名称
cv2.putText(img_copy, target_color, (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2)
# 拼接显示原图和掩码
result = np.hstack((img_copy, cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)))
cv2.imshow(f"{target_color} Detection", result)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()4、关键优化技巧(提升识别鲁棒性)
(1)阈值校准:
实际场景中,用 “阈值调试工具” 获取精准 HSV 范围(代码如下),适配环境光照:
python
# HSV阈值调试工具(单独运行)
def hsv_tuner():
cv2.namedWindow("HSV Tuner")
cv2.createTrackbar("Hmin", "HSV Tuner", 0, 179, lambda x: x)
cv2.createTrackbar("Smin", "HSV Tuner", 0, 255, lambda x: x)
cv2.createTrackbar("Vmin", "HSV Tuner", 0, 255, lambda x: x)
cv2.createTrackbar("Hmax", "HSV Tuner", 179, 179, lambda x: x)
cv2.createTrackbar("Smax", "HSV Tuner", 255, 255, lambda x: x)
cv2.createTrackbar("Vmax", "HSV Tuner", 255, 255, lambda x: x)
while True:
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
hmin = cv2.getTrackbarPos("Hmin", "HSV Tuner")
smin = cv2.getTrackbarPos("Smin", "HSV Tuner")
vmin = cv2.getTrackbarPos("Vmin", "HSV Tuner")
hmax = cv2.getTrackbarPos("Hmax", "HSV Tuner")
smax = cv2.getTrackbarPos("Smax", "HSV Tuner")
vmax = cv2.getTrackbarPos("Vmax", "HSV Tuner")
mask = cv2.inRange(hsv, (hmin,smin,vmin), (hmax,smax,vmax))
cv2.imshow("HSV Tuner", np.hstack((frame, cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR))))
if cv2.waitKey(1) == ord('q'):
print(f"HSV阈值:({hmin},{smin},{vmin}) ~ ({hmax},{smax},{vmax})")
break(2)光照适应:
降低 S 通道阈值下限(如 120→80),适配低饱和度场景;提高 V 通道范围(如 70-255),兼容明暗变化。
对图像进行直方图均衡化(针对亮度通道),减少光照不均的影响。
(3)后处理强化:
用 “开运算”(先腐蚀后膨胀)去除小噪声,“闭运算”(先膨胀后腐蚀)修复目标区域的孔洞。
筛选轮廓面积和宽高比,排除形状不符的干扰区域(如识别红色零件时,过滤细长的红色杂点)。
(4)K230 平台适配:
用 NPU 加速颜色空间转换和阈值分割,CPU 负责轮廓提取,单帧延迟可降至 50ms 内。
通过 ISP 模块调整摄像头曝光参数,避免过亮或过暗导致颜色失真。
5、典型应用场景
巡线机器人:识别特定颜色的赛道标线(如黑色背景上的白色、红色标线)。
工业质检:筛选特定颜色的零件(如红色合格产品、蓝色不合格产品)。
智能分拣:机器人识别不同颜色的物品,进行分类分拣(如快递包裹、水果)。
交通标志识别:识别红色警告标志、黄色警示标志等。



【花雕动手做】CanMV K230 AI 视觉识别模块之颜色识别
项目测试实验代码
#【花雕动手做】CanMV K230 AI 视觉识别模块之颜色识别
import time, os, sys
from media.sensor import *
from media.display import *
from media.media import *
# 导入串口通信相关库 / Import UART communication libraries
from libs.YbProtocol import YbProtocol # 亚博通信协议
from ybUtils.YbUart import YbUart # 串口工具
# 初始化串口通信 / Initialize UART communication
# uart = None # 已注释的备用代码
uart = YbUart(baudrate=115200) # 创建串口对象,波特率115200
pto = YbProtocol() # 创建协议处理对象
# 显示参数 / Display parameters
DISPLAY_WIDTH = 640 # LCD显示宽度 / LCD display width
DISPLAY_HEIGHT = 480 # LCD显示高度 / LCD display height
# LAB颜色空间阈值 / LAB color space thresholds
# 格式: (L Min, L Max, A Min, A Max, B Min, B Max)
THRESHOLDS = [
(0, 66, 7, 127, 3, 127), # 红色阈值 / Red threshold
(42, 100, -128, -17, 6, 66), # 绿色阈值 / Green threshold
(43, 99, -43, -4, -56, -7), # 蓝色阈值 / Blue threshold
(37, 100, -128, 127, -128, -27) # 亚博智能Logo的颜色 / YAHBOOM logo color
]
def get_closest_rgb(lab_threshold):
"""
根据LAB阈值计算最接近的RGB颜色 / Calculate closest RGB color based on LAB threshold
参数:
lab_threshold: LAB颜色空间阈值元组
返回:
RGB颜色元组 (R, G, B)
"""
# 获取LAB空间的中心点值 / Calculate center points in LAB space
l_center = (lab_threshold[0] + lab_threshold[1]) // 2 # 亮度中心
a_center = (lab_threshold[2] + lab_threshold[3]) // 2 # 红绿色度中心
b_center = (lab_threshold[4] + lab_threshold[5]) // 2 # 黄蓝色度中心
# 将LAB颜色转换为RGB颜色 / Convert LAB color to RGB color
return image.lab_to_rgb((l_center, a_center, b_center))
def init_sensor():
"""初始化摄像头 / Initialize camera sensor"""
sensor = Sensor() # 创建传感器对象
sensor.reset() # 重置传感器到默认状态
# 设置分辨率为640x480 / Set resolution to 640x480
sensor.set_framesize(width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT)
# 设置像素格式为RGB565 / Set pixel format to RGB565
sensor.set_pixformat(Sensor.RGB565)
return sensor
def init_display():
"""初始化显示 / Initialize display"""
# 初始化ST7701显示屏,输出到IDE / Initialize ST7701 display, output to IDE
Display.init(Display.ST7701, to_ide=True)
# 初始化媒体管理器 / Initialize media manager
MediaManager.init()
def process_blobs(img, blobs, color):
"""
处理检测到的色块 / Process detected color blobs
参数:
img: 图像对象
blobs: 检测到的色块列表
color: 绘制颜色
"""
for blob in blobs:
# 绘制色块矩形框 / Draw rectangle around the blob
# blob[0:4] 包含 (x, y, width, height)
img.draw_rectangle(blob[0:4], color=color, thickness=4)
# 在色块中心绘制十字标记 / Draw cross at blob center
# blob[5], blob[6] 是中心点坐标 (cx, cy)
img.draw_cross(blob[5], blob[6], color=color, thickness=2)
# 提取色块信息 / Extract blob information
x = blob[0] # 左上角x坐标
y = blob[1] # 左上角y坐标
w = blob[2] # 宽度
h = blob[3] # 高度
# 通过协议封装颜色数据 / Package color data using protocol
pto_data = pto.get_color_data(x, y, w, h)
# 通过串口发送数据 / Send data via UART
uart.send(pto_data)
print(pto_data) # 打印数据到控制台
break # 只处理第一个检测到的色块
def draw_fps(img, fps):
"""
绘制FPS信息 / Draw FPS information
参数:
img: 图像对象
fps: 帧率值
"""
img.draw_string_advanced(0, 0, 30, f'FPS: {fps:.3f}', color=(255, 255, 255))
def main():
"""主函数 / Main function"""
try:
# 初始化设备 / Initialize devices
sensor = init_sensor() # 初始化摄像头
init_display() # 初始化显示
sensor.run() # 启动摄像头采集
# 初始化性能监控时钟 / Initialize performance monitoring clock
clock = time.clock()
# 选择要检测的颜色索引 / Select color index to detect
# 0:红色, 1:绿色, 2:蓝色, 3:亚博Logo色
color_index = 0 # 可以修改这个值来选择检测不同的颜色
threshold = THRESHOLDS[color_index] # 获取对应颜色的LAB阈值
detect_color = get_closest_rgb(threshold) # 计算对应的RGB颜色用于绘制
# 主循环 - 实时颜色识别 / Main loop - real-time color recognition
while True:
clock.tick() # 更新时钟用于FPS计算
# 捕获图像 / Capture image
img = sensor.snapshot()
# 检测指定颜色 / Detect specified color
# area_threshold=5000: 最小面积阈值,过滤小色块
# merge=True: 合并相邻的色块
blobs = img.find_blobs([threshold], area_threshold=5000, merge=True)
# 如果检测到色块,进行处理 / If blobs detected, process them
if blobs:
process_blobs(img, blobs, detect_color)
# 计算并显示帧率 / Calculate and display FPS
fps = clock.fps()
draw_fps(img, fps) # 在图像上绘制FPS
print(fps) # 在控制台打印FPS
# 显示处理后的图像 / Display processed image
Display.show_image(img)
except KeyboardInterrupt as e:
# 处理用户中断 (Ctrl+C) / Handle user interrupt
print("用户中断 / User interrupted: ", e)
except Exception as e:
# 处理其他异常 / Handle other exceptions
print(f"发生错误 / Error occurred: {e}")
finally:
# 清理资源 / Cleanup resources
if 'sensor' in locals() and isinstance(sensor, Sensor):
sensor.stop() # 停止摄像头
Display.deinit() # 关闭显示
MediaManager.deinit() # 释放媒体资源
# 程序入口点 / Program entry point
if __name__ == "__main__":
main()程序功能解读
核心功能:实时颜色识别与通信
颜色检测:基于LAB颜色空间的色块识别
视觉反馈:在图像上标记检测到的色块
串口通信:将检测结果通过UART发送给其他设备
性能监控:实时显示处理帧率
技术架构分析
1. LAB颜色空间优势
python
THRESHOLDS = [
(0, 66, 7, 127, 3, 127), # 红色
(42, 100, -128, -17, 6, 66), # 绿色
(43, 99, -43, -4, -56, -7), # 蓝色
]
LAB颜色空间特点:
L通道:亮度,0-100
A通道:红绿色度,-128到+127
B通道:黄蓝色度,-128到+127
优势:比RGB更接近人类视觉感知,对光照变化不敏感
2. 串口通信系统
python
uart = YbUart(baudrate=115200) # 高速串口
pto = YbProtocol() # 协议封装
通信流程:
text
颜色检测 → 数据封装 → 串口发送 → 外部设备接收
3. 色块检测算法
python
blobs = img.find_blobs([threshold], area_threshold=5000, merge=True)
参数说明:
area_threshold=5000:最小面积5000像素,过滤噪声
merge=True:合并相邻色块,避免碎片化
返回的blob包含:[x, y, width, height, cx, cy]
性能优化特性
1. 智能色块处理
python
break # 只处理第一个检测到的色块
提高处理效率,避免处理过多色块
适合主要目标追踪场景
2. 实时性能监控
python
clock = time.clock()
fps = clock.fps()
持续监控系统性能
为算法优化提供数据支持
算法工作流程
实时处理流水线
text
图像采集 → LAB颜色空间转换 → 色块检测 →
轮廓绘制 → 数据封装 → 串口发送 → 结果显示
颜色识别详细流程
图像获取:摄像头捕获RGB565格式图像
颜色转换:内部转换为LAB颜色空间
阈值分割:根据预设LAB范围分割图像
连通域分析:找到符合条件的色块区域
特征提取:计算位置、大小、中心点
可视化:绘制边框和中心标记
通信:封装数据并通过串口发送
实验串口返回情况

实验场景图





返回首页
回到顶部
评论