【花雕动手做】CanMV K230 AI视觉识别模块之使用draw_cross()方法绘制十字准心
本文介绍了CanMV K230 RISC-V边缘AI平台及其图像处理功能。CanMV K230是一款高性价比的AI视觉开发模块,搭载嘉楠科技K230芯片(6 TOPS算力),支持Python编程和OpenMV类似框架。文章重点展示了使用draw_cross()方法在屏幕上绘制多层十字准心的过程:1)中心大十字(40像素);2)内圈8个小十字;3)外圈12个更小十字;4)四角装饰十字;5)中心点缀小

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


绘制十字准心的draw_cross()方法
image.draw_cross(x, y[, color[, size=5[, thickness=1]]])
在图像上绘制一个十字标记。参数可以分别传入 x, y,也可以作为元组 (x, y) 一起传递。
color: 表示颜色的 RGB888 元组,适用于灰度或 RGB565 图像,默认为白色。对于灰度图像,还可以传递像素值(范围 0-255);对于 RGB565 图像,可以传递字节翻转的 RGB565 值。
size: 控制十字标记的大小,默认为 5。
thickness: 控制十字线条的像素宽度,默认为 1。
该方法返回图像对象,允许通过链式调用其他方法。
不支持压缩图像和 Bayer 格式图像。
测试实验代码
#【花雕动手做】CanMV K230 AI视觉识别模块之使用draw_cross()方法绘制十字准心
# 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
测试显示功能的函数
主要功能:在屏幕上绘制一个精美的十字准心图案,包含中心大十字和多个环绕小十字
"""
# 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,240)位置绘制一个大十字准心
# 参数说明:
# 320, 240: 十字中心坐标(屏幕中心)
# color=(0, 191, 255): 天蓝色 (RGB值)
# size=40: 十字大小,指单臂长度(像素)
# thickness=3: 线宽3像素
img.draw_cross(320, 240, color=(0, 191, 255), size=40, thickness=3)
# ========== 第二层:内圈小十字环绕 ==========
# 在半径为50像素的圆周上均匀分布8个小十字
for i in range(8):
# 计算当前小十字的角度位置(0-360度均匀分布)
angle = i * (360 / 8) # 每个十字间隔45度
# 使用三角函数计算小十字的坐标位置
# math.radians()将角度转换为弧度
# math.cos()和math.sin()计算余弦和正弦值
x = int(320 + 50 * math.cos(math.radians(angle))) # x坐标 = 中心x + 半径*cos(角度)
y = int(240 + 50 * math.sin(math.radians(angle))) # y坐标 = 中心y + 半径*sin(角度)
# 绘制内圈小十字
# color=(135, 206, 235): 浅天蓝色,比中心十字稍浅
# size=15: 大小15像素
# thickness=2: 线宽2像素
img.draw_cross(x, y, color=(135, 206, 235), size=15, thickness=2)
# ========== 第三层:外圈更小的十字 ==========
# 在半径为80像素的圆周上均匀分布12个更小的十字
for i in range(12):
angle = i * (360 / 12) # 每个十字间隔30度
# 计算外圈十字坐标(半径80像素)
x = int(320 + 80 * math.cos(math.radians(angle)))
y = int(240 + 80 * math.sin(math.radians(angle)))
# 绘制外圈小十字
# color=(173, 216, 230): 更浅的天蓝色
# size=10: 大小10像素
# thickness=1: 线宽1像素(最细)
img.draw_cross(x, y, color=(173, 216, 230), size=10, thickness=1)
# ========== 第四层:四个角的装饰性十字 ==========
# 在屏幕四个角落附近绘制中等大小的装饰十字
# 左上角十字 (240, 140)
img.draw_cross(240, 140, color=(0, 191, 255), size=25, thickness=2)
# 右上角十字 (400, 140)
img.draw_cross(400, 140, color=(0, 191, 255), size=25, thickness=2)
# 左下角十字 (240, 340)
img.draw_cross(240, 340, color=(0, 191, 255), size=25, thickness=2)
# 右下角十字 (400, 340)
img.draw_cross(400, 340, color=(0, 191, 255), size=25, thickness=2)
# ========== 第五层:中心点缀小十字 ==========
# 在中心大十字上面再绘制一个更小的十字,增加层次感
img.draw_cross(320, 240, color=(173, 216, 230), size=8, thickness=1)
# 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十字准心绘制代码的技术细节和实现原理:
代码架构分析
- 核心模块导入
python
import time, os, urandom, sys, math
from media.display import *
from media.media import *
math模块:关键!用于三角函数计算圆周分布
media模块:CanMV特有的图形显示功能
这种导入方式显示了嵌入式系统对计算效率的重视
核心技术解析
- 显示系统初始化流程
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()
技术要点:
双缓冲机制:image.Image创建内存缓冲区,Display.show_image()一次性显示
ARGB8888:32位色深,支持透明度(虽然本例未使用Alpha通道)
ST7701驱动:针对特定LCD屏幕的优化驱动
- draw_cross() 方法深度解析
python
方法签名推测(基于使用方式)
def draw_cross(x, y, color, size, thickness):
“”"
绘制十字准心
参数:
x, y: 中心坐标
color: RGB颜色元组
size: 十字单臂长度(从中心到端点的距离)
thickness: 线条粗细
“”"
绘制原理:
十字由两条垂直的线段组成:
水平线:从(x-size, y)到(x+size, y)
垂直线:从(x, y-size)到(x, y+size)
使用Bresenham直线算法或类似的光栅化算法
- 极坐标分布算法
python
for i in range(8):
angle = i * (360 / 8) # 45度间隔
x = int(320 + 50 * math.cos(math.radians(angle)))
y = int(240 + 50 * math.sin(math.radians(angle)))
数学原理:
角度转弧度:math.radians(angle) - 三角函数需要弧度制
极坐标转直角坐标:
x = r × cos(θ) + center_x
y = r × sin(θ) + center_y
均匀分布:360/n度间隔确保等分圆周
- 颜色层次设计
python
颜色渐变策略
颜色方案 = {
“中心”: (0, 191, 255), # 深天蓝 - 最醒目
“内圈”: (135, 206, 235), # 中天蓝 - 中等醒目
“外圈”: (173, 216, 230), # 浅天蓝 - 最淡
“角落”: (0, 191, 255) # 与中心同色 - 形成视觉关联
}
视觉设计原则:
中心突出:最大尺寸 + 最深颜色
层次递减:向外圈尺寸减小、颜色变浅
对称平衡:四个角落重复中心颜色
性能优化分析
- 计算优化
python
预计算避免重复运算
angle_step = 360 / 8 # 只计算一次
for i in range(8):
angle = i * angle_step # 复用计算结果
2. 内存管理
python
单次图像更新
Display.show_image(img) # 避免频繁刷新造成的闪烁
3. 异常处理机制
python
try:
# 主要绘图逻辑
pass
except KeyboardInterrupt:
# 用户主动中断
pass
except BaseException:
# 其他所有异常
pass
重要性:在嵌入式系统中,异常处理防止系统死机
几何布局详解

坐标计算验证:
python
屏幕中心
center_x = DISPLAY_WIDTH // 2 = 640 // 2 = 320
center_y = DISPLAY_HEIGHT // 2 = 480 // 2 = 240
内圈十字示例(0度方向)
x = 320 + 50 * cos(0°) = 320 + 50 * 1 = 370
y = 240 + 50 * sin(0°) = 240 + 50 * 0 = 240
实际应用场景
- 机器视觉瞄准
python
可用于目标跟踪的参考系
def update_crosshair(target_x, target_y):
img.clear()
img.draw_cross(target_x, target_y, color=(255,0,0), size=30, thickness=2)
2. 摄像头校准
python
光学中心校准工具
def calibration_pattern():
# 绘制精确的校准图案
pass
3. 游戏UI元素
python
第一人称射击游戏的准心
def fps_crosshair():
# 可动态变化的准心
pass
实验场景图


更多推荐



所有评论(0)