驴友花雕 发表于 昨天 18:12

【花雕动手做】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 倍。



驴友花雕 发表于 昨天 18:46

【花雕动手做】CanMV K230 AI视觉模块之绘制文字数字

绘制文字的draw_string_advanced方法

【推荐使用】
draw_string_advanced
增强版 draw_string,支持中文显示,并允许用户通过 font 参数自定义字体。
image.draw_string_advanced(x, y, char_size, str, )
【不推荐使用】
draw_string
image.draw_string(x, y, text[, color[, scale=1[, x_spacing=0[, y_spacing=0[, mono_space=True]]]]])
从图像的 (x, y) 位置开始绘制 8x10 大小的文本。参数可以分别传入 x, y,也可以作为元组 (x, y) 一起传递。

text: 要绘制的字符串,换行符 \n、\r 或 \r\n 用于将光标移动到下一行。
color: 表示颜色的 RGB888 元组,适用于灰度或 RGB565 图像,默认为白色。对于灰度图像,还可以传递像素值(范围 0-255);对于 RGB565 图像,可以传递字节翻转的 RGB565 值。
scale: 控制文本的缩放比例,默认为 1。只能为整数。
x_spacing: 调整字符之间的水平间距。正值表示增加间距,负值表示减少。
y_spacing: 调整行之间的垂直间距。正值表示增加间距,负值表示减少。
mono_space: 默认为 True,使字符具有固定宽度。设置为 False 时,字符间距将根据字符宽度动态调整。
该方法返回图像对象,允许通过链式调用其他方法。

不支持压缩图像和 Bayer 格式图像。

项目测试实验代码

#【花雕动手做】CanMV K230 AI视觉识别模块之使用draw_string_advanced()方法绘制文字

# 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位),支持1600万色和透明度
    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屏幕驱动芯片,支持RGB接口
    # to_ide=True表示将显示输出同时发送到IDE和硬件屏幕,便于调试
    Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
   
    # Initialize media manager
    # 初始化媒体管理器 - 负责统一管理摄像头、显示、音频等媒体资源
    MediaManager.init()

    try:
      # ========== 第一行:中文文字绘制 ==========
      # 使用draw_string_advanced方法绘制中文文字"世界你好!"
      # 参数说明:
      # 245, 200: 文字起始坐标(x, y)
      # 30: 字体大小(像素高度),30像素是比较大的字号
      # "世界你好!": 要绘制的中文字符串,包含4个汉字和1个标点
      # color=(0, 255, 127): 翠绿色,RGB值 (红=0, 绿=255, 蓝=127)
      img.draw_string_advanced(245, 200, 30, "世界你好!", color=(0, 255, 127))

      # ========== 第二行:英文文字绘制 ==========
      # 绘制英文文字"Hello World!",位于中文文字上方
      # 参数说明:
      # 230, 150: 文字起始坐标,y坐标150比中文的200更靠上
      # 30: 字体大小,与中文保持一致
      # "Hello World!": 经典的编程问候语
      # color=(0, 0, 255): 纯蓝色,RGB值 (红=0, 绿=0, 蓝=255)
      img.draw_string_advanced(230, 150, 30, "Hello World!", color=(0, 0, 255))
      
      # ========== 第三行:数字文字绘制 ==========
      # 绘制数字序列"1234567890",位于中文文字下方
      # 参数说明:
      # 230, 260: 文字起始坐标,y坐标260比中文的200更靠下
      # 30: 字体大小,保持统一
      # "1234567890": 数字0-9的完整序列
      # color=(255, 0, 0): 纯红色,RGB值 (红=255, 绿=0, 蓝=0)
      img.draw_string_advanced(230, 260, 30, "1234567890", color=(255, 0, 0))

      # Update display with background image
      # 更新显示背景图像 - 将绘制好的文字图像显示在屏幕上
      # 这里使用了双缓冲技术:先在内存中绘制完成,再一次性显示到屏幕,避免闪烁
      Display.show_image(img)
      
      # 主循环保持显示
      # 无限循环确保程序持续运行,文字保持显示状态
      while True:
            time.sleep(2)# 每2秒循环一次,保持程序运行,减少CPU占用

    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)# 短暂延时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()# 调用显示测试函数,程序从这里开始执行

驴友花雕 发表于 昨天 18:53

【花雕动手做】CanMV K230 AI视觉模块之绘制文字数字

解读这段CanMV K230文字绘制代码的技术细节和实现原理:

整体架构分析
1. 模块化设计
python
# 核心模块导入

from media.display import *    # 显示功能

from media.media import *      # 媒体管理
模块分工明确:display负责图形显示,media负责资源管理
硬件抽象层:通过统一的API屏蔽底层硬件差异

核心技术深度解析
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格式详解:
text
每个像素32位分配:
A (Alpha) - 透明度通道 (本例中未使用,全为0xFF)
R (Red)    - 红色通道 (0-255)
G (Green)- 绿色通道 (0-255)
B (Blue)      - 蓝色通道 (0-255)

内存布局:0xAARRGGBB
示例:白色 = 0xFFFFFFFF,红色 = 0xFFFF0000
ST7701驱动特性:
RGB接口:并行RGB 16/18/24位接口
分辨率支持:最高支持1280x800
硬件加速:可能包含2D图形加速功能

2. draw_string_advanced() 方法技术实现
方法签名推测:
python
def draw_string_advanced(x, y, size, text, color,

                        font=None, background=None,

                        spacing=1, monospace=False):

    """

    高级文字绘制方法完整参数

    """
底层渲染算法:
c
// 基于FreeType或类似字体引擎的实现

typedef struct {

    uint16_t x;

    uint16_t y;

    uint8_t size;

    char* text;

    uint32_t color;

    Font* font;

} TextRenderParams;



void draw_string_advanced(TextRenderParams* params) {

    // 1. 字体加载和缩放

    Font* font = load_font(params->font, params->size);

   

    // 2. 文本编码转换

    uint32_t* unicode_chars = text_to_unicode(params->text);

   

    // 3. 逐个字符渲染

    uint16_t cursor_x = params->x;

    for(int i = 0; unicode_chars != 0; i++) {

      // 获取字符位图

      CharBitmap* bitmap = get_char_bitmap(font, unicode_chars);

      

      // 4. 位图渲染到帧缓冲区

      render_char_bitmap(cursor_x, params->y, bitmap, params->color);

      

      // 5. 更新光标位置(考虑字符宽度和间距)

      cursor_x += bitmap->advance + params->spacing;

    }

}
3. 多语言文字处理技术
字符编码处理:
python
def handle_multi_language_text(text):

    """

    处理多语言文本的编码和渲染

    """

    # 编码检测

    if is_ascii_text(text):

      # ASCII文本(英文、数字、符号)

      encoding = 'ascii'

      font_file = 'latin_font.bin'

      

    elif contains_chinese(text):

      # 中文字符检测

      encoding = 'gb2312'# 或UTF-8

      font_file = 'chinese_font.bin'

      

    else:

      # 其他语言

      encoding = 'utf-8'

      font_file = 'unicode_font.bin'

   

    return encoding, font_file
中文字符渲染优化:
python
def render_chinese_character(char, size):

    """

    中文字符的特殊处理

    """

    # 中文字符特点:

    # - 字形复杂,笔画多

    # - 在点阵字体中需要更高分辨率

    # - 可能需要矢量轮廓渲染

   

    if size < 20:

      # 小字号使用简化字型

      use_simplified_glyph = True

      antialias = False

    else:

      # 大字号使用完整字型,启用抗锯齿

      use_simplified_glyph = False

      antialias = True

   

    return load_chinese_glyph(char, size, use_simplified_glyph, antialias)
4. 坐标系统和布局算法
文字位置计算:
python
def calculate_text_position(text, size, alignment='center'):

    """

    计算文字在屏幕上的位置

    """

    # 估算文本宽度(近似计算)

    if is_chinese_text(text):

      char_width = size * 0.8# 中文字符宽度系数

    else:

      char_width = size * 0.6# 英文字符宽度系数

   

    text_width = len(text) * char_width

   

    # 根据对齐方式计算起始x坐标

    if alignment == 'center':

      x = (DISPLAY_WIDTH - text_width) // 2

    elif alignment == 'left':

      x = 10# 左边距

    else:# right

      x = DISPLAY_WIDTH - text_width - 10

   

    return x
实际坐标分析:
python
# 代码中的坐标布局:

英文: (230, 150) - "Hello World!" ≈ 240像素宽,居中:230+120=350(接近320)

中文: (245, 200) - "世界你好!" ≈ 125像素宽,居中:245+62.5=307.5(接近320)

数字: (230, 260) - "1234567890" ≈ 180像素宽,居中:230+90=320(完美居中)



# 垂直间距:50像素,形成清晰的视觉层次
5. 颜色管理和视觉设计
颜色空间处理:
python
def color_management_system():

    """

    颜色管理和转换

    """

    # RGB888转RGB565(如果显示硬件需要)

    def rgb888_to_rgb565(r, g, b):

      return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)

   

    # 伽马校正(可选)

    def gamma_correct(color):

      # 提高在LCD上的显示效果

      return int(pow(color / 255.0, 2.2) * 255)
色彩心理学应用:
python
颜色策略 = {

    "英文": (0, 0, 255),      # 蓝色 - 技术、专业、稳定

    "中文": (0, 255, 127),    # 翠绿 - 自然、和谐、生机

    "数字": (255, 0, 0)       # 红色 - 重要、警示、突出

}
6. 性能优化技术
字体缓存机制:
python
class FontCache:

    def __init__(self):

      self.cache = {}

      self.max_size = 100# 最大缓存字符数

   

    def get_char(self, char, size):

      key = (char, size)

      if key in self.cache:

            return self.cache

      

      # 缓存未命中,加载字符

      bitmap = load_char_from_flash(char, size)

      

      # LRU缓存管理

      if len(self.cache) >= self.max_size:

            self.evict_oldest()

      

      self.cache = bitmap

      return bitmap
双缓冲显示技术:
python
def double_buffering_system():

    """

    双缓冲显示,避免闪烁

    """

    # 前台缓冲区:当前显示的内容

    # 后台缓冲区:正在绘制的内容

   

    while True:

      # 在后台缓冲区绘制

      back_buffer.clear()

      back_buffer.draw_text(...)

      

      # 交换缓冲区(原子操作)

      swap_buffers()
7. 异常处理和鲁棒性
资源管理:
python
def safe_resource_management():

    try:

      # 资源申请

      display = Display.init(...)

      media = MediaManager.init()

      

      # 业务逻辑

      main_loop()

      

    finally:

      # 确保资源释放(RAII模式)

      if display:

            Display.deinit()

      if media:

            MediaManager.deinit()
字体回退机制:
python
def robust_text_rendering(text, size, color):

    """

    健壮的文字渲染,处理字体缺失等情况

    """

    try:

      img.draw_string_advanced(x, y, size, text, color)

    except FontNotFoundError:

      # 字体缺失,使用默认字体

      img.draw_string_advanced(x, y, size, "【字体缺失】", color)

    except UnicodeEncodeError:

      # 编码错误,显示替代字符

      img.draw_string_advanced(x, y, size, "???", color)
技术亮点总结
多语言支持:完整的中英文和数字渲染能力
硬件加速:利用显示控制器的图形功能
内存优化:高效的字体缓存和位图管理
视觉设计:科学的颜色搭配和布局算法
系统稳定性:完善的异常处理和资源管理
实时性能:优化的渲染流水线,适合嵌入式环境

这个文字显示系统展示了CanMV K230在嵌入式GUI开发方面的强大能力,为复杂的用户界面应用奠定了坚实的技术基础。

驴友花雕 发表于 昨天 18:57

【花雕动手做】CanMV K230 AI视觉模块之绘制文字数字

实验场景图




页: [1]
查看完整版本: 【花雕动手做】CanMV K230 AI 视觉模块之绘制文字与数字