回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【花雕动手做】CanMV K230 AI 视觉识别模块之颜色识别 简单

头像 驴友花雕 2025.11.09 7 0

00 (2).jpg

什么是 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 倍。

 

00 (3).jpg

知识点
颜色识别是计算机视觉中基于像素色彩特征的基础任务,核心是从图像中筛选出特定颜色的区域(如红色路标、绿色零件),通过 “颜色空间转换 + 阈值分割” 实现,适配简单场景的快速识别,也是巡线、物体分类等任务的基础。

1、核心原理
颜色识别的关键是 “用合适的颜色空间描述颜色,并通过阈值筛选目标颜色”,核心逻辑:
颜色空间转换:将图像从默认的 RGB 空间,转换为更适合颜色分割的空间(如 HSV、HSL),减少光照变化的影响。
阈值设定:在目标颜色空间中,定义目标颜色的范围(如 HSV 中红色的 hue、saturation、value 区间)。
阈值分割:筛选出颜色落在目标范围内的像素,生成二值掩码(目标区域为白色,其他为黑色)。
后处理:通过形态学操作优化掩码,提取目标区域的轮廓或位置。

2、主流颜色空间(按实用性分类)

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0e8ad84f1c854008ae345303c176200c.jpeg#pic_center)
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、典型应用场景
巡线机器人:识别特定颜色的赛道标线(如黑色背景上的白色、红色标线)。
工业质检:筛选特定颜色的零件(如红色合格产品、蓝色不合格产品)。
智能分拣:机器人识别不同颜色的物品,进行分类分拣(如快递包裹、水果)。
交通标志识别:识别红色警告标志、黄色警示标志等。

 

41.jpg
42.jpg
43.jpg

【花雕动手做】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范围分割图像
连通域分析:找到符合条件的色块区域
特征提取:计算位置、大小、中心点
可视化:绘制边框和中心标记
通信:封装数据并通过串口发送

实验串口返回情况

 

44.jpg

 

实验场景图  

 

45 (1).jpg
45 (2).jpg
45 (3).jpg
46.jpg

评论

user-avatar
icon 他的勋章
    展开更多