【花雕动手做】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 倍。
【花雕动手做】CanMV K230 AI 视觉模块之绘制一个箭头图案
绘制线条的draw_arrow()方法image.draw_arrow(x0, y0, x1, y1[, color[, thickness=1]])
在图像上绘制从 (x0, y0) 到 (x1, y1) 的箭头。参数可以分别传入 x0, y0, x1, y1,也可以作为元组 (x0, y0, x1, y1) 一起传递。
color: 表示颜色的 RGB888 元组,适用于灰度或 RGB565 图像,默认为白色。对于灰度图像,还可以传递像素值(范围 0-255);对于 RGB565 图像,可以传递字节翻转的 RGB565 值。
thickness: 控制箭头线条的像素宽度,默认为 1。
该方法返回图像对象,允许通过链式调用其他方法。
不支持压缩图像和 Bayer 格式图像。
项目测试实验代码
#【花雕动手做】CanMV K230 AI视觉识别模块之使用draw_arrow()方法绘制箭头
# Import required modules
# 导入所需的模块
import time, os, urandom, sys, math
# Import display and media related modules
# 导入显示和媒体相关模块
from media.display import *
from media.media import *
# Define display resolution constants
# 定义显示分辨率常量
DISPLAY_WIDTH = 640 # 显示宽度:640像素
DISPLAY_HEIGHT = 480 # 显示高度:480像素
def display_test():
"""
Function to test display functionality
测试显示功能的函数
主要功能:在屏幕上绘制多个不同方向、大小和颜色的箭头,展示draw_arrow()方法的用法
"""
# Create main background image with white color
# 创建白色背景的主图像
# ARGB8888格式:每个像素32位(Alpha透明通道+RGB各8位)
img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888)
img.clear()# 清空图像缓冲区
# 绘制白色填充矩形作为背景,fill=True表示填充
img.draw_rectangle(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, color=(255,255,255), fill=True)
# Initialize display with ST7701 driver
# 使用ST7701驱动初始化显示器
# ST7701是常见的LCD屏幕驱动芯片
# to_ide=True表示将显示输出同时发送到IDE和硬件屏幕
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
# Initialize media manager
# 初始化媒体管理器 - 负责管理摄像头、显示等媒体资源
MediaManager.init()
try:
# ========== 第一组:中央主要箭头 ==========
# 绘制水平向右的主箭头,象征前进方向
# 参数说明:
# 320, 200: 箭头起点坐标(x1, y1)
# 400, 200: 箭头终点坐标(x2, y2)
# color=(0, 191, 255): 天蓝色 (RGB值)
# thickness=5: 线宽5像素(最粗,突出主箭头)
img.draw_arrow(320, 200, 400, 200, color=(0, 191, 255), thickness=5)
# ========== 第二组:辅助箭头 ==========
# 在主箭头上方和下方绘制两个平行的辅助箭头
# 上方的辅助箭头(比主箭头细且颜色浅)
img.draw_arrow(300, 180, 380, 180, color=(135, 206, 235), thickness=3)
# 下方的辅助箭头
img.draw_arrow(340, 220, 420, 220, color=(135, 206, 235), thickness=3)
# ========== 第三组:对角线箭头 ==========
# 绘制两个对角线方向的箭头,增加画面的动感和立体感
# 左上到右下的对角线箭头
img.draw_arrow(250, 150, 350, 250, color=(0, 191, 255), thickness=3)
# 右上到左下的对角线箭头(实际上是另一个方向的斜箭头)
img.draw_arrow(350, 150, 450, 250, color=(0, 191, 255), thickness=3)
# ========== 第四组:反向箭头 ==========
# 绘制与主箭头方向相反的箭头,形成对比效果
# 与主箭头完全反向(从右向左)
img.draw_arrow(400, 200, 320, 200, color=(173, 216, 230), thickness=3)
# 与上方辅助箭头反向
img.draw_arrow(380, 180, 300, 180, color=(173, 216, 230), thickness=2)
# 与下方辅助箭头反向
img.draw_arrow(420, 220, 340, 220, color=(173, 216, 230), thickness=2)
# ========== 第五组:垂直箭头 ==========
# 绘制垂直方向的箭头,丰富箭头的方向变化
# 左侧垂直向下的箭头
img.draw_arrow(320, 150, 320, 250, color=(0, 191, 255), thickness=3)
# 右侧垂直向下的箭头
img.draw_arrow(400, 150, 400, 250, color=(0, 191, 255), thickness=3)
# ========== 第六组:点缀小箭头 ==========
# 绘制两个小尺寸的装饰性箭头,增加画面的细节
# 左下角的小箭头
img.draw_arrow(300, 220, 310, 230, color=(135, 206, 235), thickness=2)
# 右上角的小箭头
img.draw_arrow(330, 170, 340, 180, color=(135, 206, 235), thickness=2)
# Update display with background image
# 更新显示背景图像 - 将绘制好的箭头图案显示在屏幕上
Display.show_image(img)
# 主循环保持显示
while True:
time.sleep(2)# 每2秒循环一次,保持程序运行
except KeyboardInterrupt as e:
# 捕获键盘中断(如Ctrl+C),优雅退出
print("user stop: ", e)
except BaseException as e:
# 捕获其他所有异常,防止程序崩溃
print(f"Exception {e}")
# Cleanup and deinitialize display
# 清理并反初始化显示器
Display.deinit()
# 启用睡眠退出点,允许系统进入低功耗模式
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)# 短暂延时确保资源释放完成
# Release media resources
# 释放媒体资源
MediaManager.deinit()
if __name__ == "__main__":
# Enable exit points and run display test
# 启用退出点并运行显示测试
# EXITPOINT_ENABLE允许通过IDE停止程序执行
os.exitpoint(os.EXITPOINT_ENABLE)
display_test()# 调用显示测试函数
【花雕动手做】CanMV K230 AI 视觉模块之绘制一个箭头图案
解读这段CanMV K230箭头绘制代码的技术细节和实现原理:代码架构分析
1. 核心模块依赖
python
import time, os, urandom, sys, math
from media.display import *
from media.media import *
math模块:虽然本例未直接使用,但draw_arrow()内部可能用到三角函数计算箭头头部
media模块:提供底层图形绘制能力
模块选择体现了嵌入式系统对计算效率的重视
核心技术解析
1. 显示系统初始化流程
python
img = image.Image(DISPLAY_WIDTH, DISPLAY_HEIGHT, image.ARGB8888)
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
MediaManager.init()
技术要点:
ARGB8888格式:32位色深,支持1600万色和透明度
ST7701驱动:针对RGB接口LCD的专用驱动芯片
双缓冲机制:内存绘制完成后一次性显示,避免闪烁
2. draw_arrow() 方法深度解析
基于使用方式推测的方法签名:
python
def draw_arrow(x1, y1, x2, y2, color, thickness):
"""
绘制从(x1,y1)到(x2,y2)的箭头
技术实现包含:
1. 主体线段绘制
2. 箭头头部三角形计算
3. 抗锯齿处理(可选)
"""
箭头绘制算法原理:
python
# 伪代码实现
def draw_arrow_algorithm(x1, y1, x2, y2, color, thickness):
# 1. 计算方向向量和长度
dx = x2 - x1
dy = y2 - y1
length = math.sqrt(dx*dx + dy*dy)
# 2. 归一化方向向量
if length > 0:
dx /= length
dy /= length
# 3. 绘制主体线段(稍微缩短以避免与箭头头部重叠)
line_end_x = x2 - dx * head_length
line_end_y = y2 - dy * head_length
draw_line(x1, y1, line_end_x, line_end_y, color, thickness)
# 4. 计算箭头头部参数
head_length = thickness * 3# 头部长度与线宽成正比
head_angle = math.pi / 6 # 30度夹角
# 5. 计算箭头翼部点(使用旋转矩阵)
# 左侧翼点
left_angle = math.atan2(dy, dx) - head_angle
left_x = x2 - head_length * math.cos(left_angle)
left_y = y2 - head_length * math.sin(left_angle)
# 右侧翼点
right_angle = math.atan2(dy, dx) + head_angle
right_x = x2 - head_length * math.cos(right_angle)
right_y = y2 - head_length * math.sin(right_angle)
# 6. 绘制箭头头部三角形
draw_line(x2, y2, left_x, left_y, color, thickness)
draw_line(x2, y2, right_x, right_y, color, thickness)
draw_line(left_x, left_y, right_x, right_y, color, thickness)
3. 视觉层次设计策略
颜色层次系统:
python
颜色层次 = {
"主要": (0, 191, 255), # 深天蓝 - 最高重要性
"次要": (135, 206, 235), # 中天蓝 - 中等重要性
"装饰": (173, 216, 230) # 浅天蓝 - 最低重要性
}
线宽层次系统:
python
线宽层次 = {
"主要": 5, # 最粗 - 视觉焦点
"中等": 3, # 中等 - 重要元素
"细小": 2 # 最细 - 装饰元素
}
4. 几何布局分析
坐标计算示例:
python
# 主箭头坐标分析
起点 = (320, 200)# 屏幕水平中心偏上
终点 = (400, 200)# 向右80像素
长度 = 80像素
# 对角线箭头坐标分析
左上右下: (250,150) → (350,250)# 100像素斜线
右上左下: (350,150) → (450,250)# 100像素斜线
性能优化技术
1. 批量绘制优化
python
# 所有箭头在内存中一次性绘制完成
# 然后单次调用Display.show_image()显示
# 避免频繁的显示更新造成的闪烁
2. 计算优化
python
# 可能的内部优化:
- 使用整数运算避免浮点开销
- 使用查表法替代实时三角函数计算
- 利用硬件加速的直线绘制算法
3. 内存管理
python
# ARGB8888内存占用计算:
640 × 480 × 4字节 = 1,228,800字节 ≈ 1.17MB
# 在嵌入式系统中属于较大的帧缓冲区
异常处理机制
python
try:
# 主要绘图逻辑
# 可能发生的异常:
# - 坐标超出范围
# - 内存分配失败
# - 硬件访问错误
except KeyboardInterrupt:
# 用户主动终止 - 友好退出
except BaseException:
# 捕获所有其他异常 - 防止系统崩溃
实际应用场景扩展
1. 导航系统界面
python
def draw_navigation_interface():
# 主方向箭头
img.draw_arrow(320, 240, 400, 200, color=(0,255,0), thickness=4)
# 替代路线箭头
img.draw_arrow(320, 240, 350, 150, color=(255,165,0), thickness=2)
2. 数据流向图示
python
def draw_data_flow():
# 处理器到内存
img.draw_arrow(100, 200, 200, 200, color=(0,0,255), thickness=3)
# 内存到显示器
img.draw_arrow(200, 200, 300, 100, color=(0,0,255), thickness=3)
3. 运动轨迹分析
python
def show_velocity_vectors():
for object in tracked_objects:
img.draw_arrow(object.x, object.y,
object.x + object.vx, object.y + object.vy,
color=(255,0,0), thickness=2)
技术亮点总结
算法效率:在资源受限的嵌入式设备上实现复杂的矢量图形
视觉设计:通过颜色和线宽创建清晰的视觉层次
几何精度:准确的箭头方向计算和头部形状生成
系统稳定性:完善的异常处理确保可靠运行
扩展性:代码结构便于添加更多箭头类型和效果
这个箭头绘制示例很好地展示了CanMV K230在嵌入式图形处理方面的强大能力,结合了计算机图形学、嵌入式系统和UI设计的多个技术领域。代码不仅功能完整,而且在性能和视觉效果之间取得了很好的平衡。
【花雕动手做】CanMV K230 AI 视觉模块之绘制一个箭头图案
实验场景图
页:
[1]