驴友花雕 发表于 5 天前

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



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



驴友花雕 发表于 5 天前

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

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

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), np.array(color_ranges))

      mask2 = cv2.inRange(hsv, np.array(color_ranges), np.array(color_ranges))

      mask = cv2.bitwise_or(mask1, mask2)

    else:

      mask = cv2.inRange(hsv, np.array(color_ranges), np.array(color_ranges))

   

    # 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, , -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、典型应用场景
巡线机器人:识别特定颜色的赛道标线(如黑色背景上的白色、红色标线)。
工业质检:筛选特定颜色的零件(如红色合格产品、蓝色不合格产品)。
智能分拣:机器人识别不同颜色的物品,进行分类分拣(如快递包裹、水果)。
交通标志识别:识别红色警告标志、黄色警示标志等。







驴友花雕 发表于 5 天前

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

【花雕动手做】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 + lab_threshold) // 2# 亮度中心
    a_center = (lab_threshold + lab_threshold) // 2# 红绿色度中心
    b_center = (lab_threshold + lab_threshold) // 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 包含 (x, y, width, height)
      img.draw_rectangle(blob, color=color, thickness=4)
      
      # 在色块中心绘制十字标记 / Draw cross at blob center
      # blob, blob 是中心点坐标 (cx, cy)
      img.draw_cross(blob, blob, color=color, thickness=2)
      
      # 提取色块信息 / Extract blob information
      x = blob      # 左上角x坐标
      y = blob      # 左上角y坐标
      w = blob      # 宽度
      h = blob      # 高度
      
      # 通过协议封装颜色数据 / 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          # 获取对应颜色的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(, 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()

驴友花雕 发表于 5 天前

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

程序功能解读
核心功能:实时颜色识别与通信
颜色检测:基于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(, area_threshold=5000, merge=True)
参数说明:
area_threshold=5000:最小面积5000像素,过滤噪声
merge=True:合并相邻色块,避免碎片化
返回的blob包含:

性能优化特性
1. 智能色块处理
python
break# 只处理第一个检测到的色块
提高处理效率,避免处理过多色块

适合主要目标追踪场景

2. 实时性能监控
python
clock = time.clock()

fps = clock.fps()
持续监控系统性能

为算法优化提供数据支持

算法工作流程
实时处理流水线
text
图像采集 → LAB颜色空间转换 → 色块检测 → 轮廓绘制 → 数据封装 → 串口发送 → 结果显示

颜色识别详细流程
图像获取:摄像头捕获RGB565格式图像
颜色转换:内部转换为LAB颜色空间
阈值分割:根据预设LAB范围分割图像
连通域分析:找到符合条件的色块区域
特征提取:计算位置、大小、中心点
可视化:绘制边框和中心标记
通信:封装数据并通过串口发送

驴友花雕 发表于 5 天前

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

实验串口返回情况



实验场景图









页: [1]
查看完整版本: 【花雕动手做】CanMV K230 AI 视觉识别模块之颜色识别