人若无名 便可潜心练剑.|

hazy1k

园龄:7个月粉丝:14关注:0

2025-02-12 15:08阅读: 6评论: 0推荐: 0

第14章 图像绘制

第十四章 图像绘制

1. 导入

penMV 是一个小型嵌入式机器视觉模块,广泛用于快速开发计算机视觉应用。OpenMV 的图像绘制方法可以用于在图像上绘制各种形状和文字,以便进行视觉反馈和调试。

CanMV支持OpenMV的图像绘制方法,并增加了一些,如绘制中文字符串的draw_string_advanced

2. 常用图像绘制函数

2.1 drwa_string_advanced

draw_string_advanced 函数使用freetype渲染文字,支持中文,用户也可指定字体

image.draw_string_advanced(x,y,char_size,str,color, font)

2.2.1 参数

  • x, y起点坐标。
  • char_size:字符大小
  • str:需要绘制的中文字符
  • color:字的颜色。
  • font: 字体文件路径

2.2.2 示例

img.draw_string_advanced(10, 10, 32, "你好世界", color=(255, 0, 0))  # 绘制红色线

2.2 draw_line

draw_line 函数可实现在图像上绘制一条线。

image.draw_line(x0, y0, x1, y1, color)

2.2.1 参数

img.draw_line(10, 10, 100, 100, color=(255, 0, 0))  # 绘制红色线

2.3 draw_rectangle

draw_rectangle 函数可实现在图像上绘制一个矩形。

image.draw_rectangle(x, y, w, h, color, thickness=1)

2.3.1 参数

  • x, y:矩形的左上角坐标。
  • w, h:矩形的宽度和高度。
  • color:矩形的颜色。
  • thickness:矩形边框的厚度(默认为1)。
img.draw_rectangle(20, 20, 50, 30, color=(0, 255, 0), thickness=2)  # 绘制绿色矩形

2.4 draw_circle

draw_circle函数可实现在图像上绘制一个圆。

image.draw_circle(x, y, r, color, thickness=1)

2.4.1 参数

  • x, y:圆心坐标。
  • r:圆的半径。
  • color:圆的颜色。
  • thickness:圆边框的厚度(默认为1)。

2.5 draw_cross

draw_cross函数可实现在图像上绘制一个十字交叉。

image.draw_cross(x, y, color, size=5, thickness=1)

2.5.1 参数

  • x, y:交叉点坐标。
  • color:交叉的颜色。
  • size:交叉的大小(默认为5)。
  • thickness:交叉线条的厚度(默认为1)。

2.6 draw_arrow

draw_arrow函数可实现在图像上绘制一条箭头线。

image.draw_arrow(x0, y0, x1, y1, color, thickness=1)

2.6.1 参数

  • x0, y0:起点坐标。
  • x1, y1:终点坐标。
  • color:箭头的颜色。
  • thickness:箭头线条的厚度(默认为1)。

2.7 draw_ellipse

draw_ellipse函数可实现在图像上绘制一个椭圆。

image.draw_ellipse(cx, cy, rx, ry, color, thickness=1)

2.7.1 参数

  • cx, cy:椭圆中心的坐标。
  • rx, ry:椭圆的半径(x轴和y轴方向)。
  • color:椭圆的颜色。
  • thickness:椭圆边框的厚度(默认为1)。

2.8 draw_image

draw_image函数可实现在当前图像上绘制另一个图像。

image.draw_image(img, x, y, alpha=128, scale=1.0)

2.8.1 参数

  • img:要绘制的图像对象。
  • x, y:绘制位置的左上角坐标。
  • alpha:透明度(0-256)。
  • scale:缩放比例(默认为1.0)。

2.8.2 示例

  overlay = image.Image("overlay.bmp")
  img.draw_image(overlay, 10, 10, alpha=128, scale=1.0)  # 在(10, 10)位置绘制 overlay.bmp

2.9 draw_keypinits

draw_keypoints函数可实现在图像上绘制关键点。

image.draw_keypoints(keypoints, size=10, color, thickness=1)

2.9.1 参数

  • keypoints:关键点列表,每个关键点是一个(x, y)元组。
  • size:关键点的大小(默认为10)。
  • color:关键点的颜色。
  • thickness:关键点边框的厚度(默认为1)。

2.9.2 示例

keypoints = [(30, 30), (50, 50), (70, 70)]
img.draw_keypoints(keypoints, size=10, color=(255, 255, 0), thickness=2)  # 绘制黄色关键点

2.10 flood_fill

flood_fill函数可实现在图像上执行洪水填充算法,从指定的起点开始填充指定的颜色。

image.flood_fill(x, y, color, threshold, invert=False, clear_background=False)

2.10.1 参数

  • x, y:起点坐标。
  • color:填充的颜色。
  • threshold:填充阈值,表示起点像素与相邻像素颜色的允许差异范围。
  • invert:布尔值,如果为 True,则反转填充条件。
  • clear_background:布尔值,如果为 True,则清除填充区域以外的背景。

2.10.2 示例

img.flood_fill(30, 30, color=(255, 0, 0), threshold=30, invert=False, clear_background=False)  # 从(30, 30)开始填充红色

2.11 draw_string

draw_string函数可实现在图像上绘制字符串。

image.draw_string(x, y, text, color, scale=1)

2.11.1 参数

  • x, y:字符串的起始坐标。
  • text:要绘制的字符串内容。
  • color:字符串的颜色。
  • scale:字符串的缩放比例(默认为1)。

2.11.2 示例

img.draw_string(10, 10, "Hello OpenMV", color=(255, 255, 255), scale=2)  # 绘制白色字符串

3. 绘制图像基础操作示例

import time, os, urandom, sys, gc
from media.display import *
from media.media import *

try:
    # 显示模式选择
    display_mode = "VIRT" # VIRT:IDE LCD:LCD屏幕 HDMI:通过HDMI连接
    # 根据显示模式调整显示宽高
    if display_mode == "VIRT":
        display_width = ALIGN_UP(1920, 16)  # 如果没有定义,改为math.ceil
        display_height = 1080
    elif display_mode == "LCD":
        display_width = 800
        display_height = 480
    elif display_mode == "HDMI":
        display_width = 1920
        display_height = 1080
    else:
        raise Exception("Invalid display mode")

    if display_mode == "VIRT":
        Display.init(Display.VIRT, width=display_width, height=display_height, fps=60)
    elif display_mode == "LCD":
        Display.init(Display.ST7701, width=display_width, height=display_height, to_ide=True)
    elif display_mode == "HDMI":
        Display.init(Display.LT9611, width=display_width, height=display_height, to_ide=True)

    width = display_width
    height = display_height
    MediaManager.init()  # 初始化媒体管理器
    fps = time.clock()
    img = image.Image(width, height, image.ARGB8888)
    # 随机颜色生成
    def random_color():
        return (urandom.getrandbits(8), urandom.getrandbits(8), urandom.getrandbits(8))
    # 随机尺寸生成
    def random_size():
        return urandom.getrandbits(10) & max_size

    while True:
        fps.tick()
        os.exitpoint()
        img.clear()
        # 绘制红色线
        img.draw_line(10,10,100,100,color=(255,0,0))
        # 绘制绿色矩形
        img.draw_rectangle(20, 20, 50, 30, color=(0, 255, 0), thickness=2)
        # 绘制蓝色圆
        img.draw_circle(30, 30, 30, color=(0, 0, 255), thickness=3)
        # 绘制黄色交叉
        img.draw_cross(40, 40, color=(255, 255, 0), size=10, thickness=2)
        # 绘制红色字符串
        img.draw_string_advanced(50, 50, 32, "你好K230", color=(255, 0, 0))
        # 绘制白色字符串
        img.draw_string_advanced(50, 100, 32, "Hello CanMV", color=(255, 255, 255), scale=2)
        # 绘制红色箭头
        img.draw_arrow(60, 60, 100, 100, color=(255, 0, 0), thickness=2)
        # 绘制蓝色椭圆
        radius_x = urandom.getrandbits(30) % (max(img.height(), img.width())//2)
        radius_y = urandom.getrandbits(30) % (max(img.height(), img.width())//2)
        rot = urandom.getrandbits(30)
        img.draw_ellipse(70, 70, radius_x, radius_y, rot, color = (0, 0, 255), thickness = 2, fill = False)
        # 绘制黄色关键点
        keypoints = [(30, 30), (50, 50), (70, 70)]
        img.draw_keypoints([(30, 40, rot)], color = (255, 255, 0), size = 20, thickness = 2, fill = False)
        # 动态线条绘制
        for _ in range(2):
           x0, y0 = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
           x1, y1 = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
           img.draw_line(x0, y0, x1, y1, color=random_color(),thickness=2)
        # 椭圆动态变化
        for _ in range(5):
            x, y = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
            img.draw_cross(x, y, color=random_color(), size=10, thickness=1)
        # 动态箭头
        for _ in range(3):
            x0, y0 = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
            x1, y1 = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
            img.draw_arrow(x0, y0, x1, y1, color=random_color(), thickness=5)
        # 动态洪水填充
        fx, fy = urandom.getrandbits(10) % width, urandom.getrandbits(10) % height
        img.flood_fill(fx, fy, color=random_color(), threshold=30)
        # 显示绘制结果
        Display.show_image(img)
        print(fps.fps())
        time.sleep_ms(10)
except KeyboardInterrupt as e:
    print(f"user stop")
except BaseException as e:
    print(f"Exception '{e}'")
finally:
    Display.deinit()
    os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
    time.sleep_ms(100)
    MediaManager.deinit()

4. 在显示图像上绘制

import time, os, sys
from media.sensor import *
from media.display import *
from media.media import *

sensor_id = 2
sensor = None


DISPLAY_MODE = "VIRT"
# 根据模式设置显示宽高
if DISPLAY_MODE == "VIRT":
    DISPLAY_WIDTH = ALIGN_UP(1920, 16)
    DISPLAY_HEIGHT = 1080
elif DISPLAY_MODE == "LCD":
    DISPLAY_WIDTH = 800
    DISPLAY_HEIGHT = 480
elif DISPLAY_MODE == "HDMI":
    DISPLAY_WIDTH = 1920
    DISPLAY_HEIGHT = 1080
else:
    raise ValueError("未知的 DISPLAY_MODE,请选择 'VIRT', 'LCD' 或 'HDMI'")

try:
    sensor = Sensor(id=sensor_id)
    sensor.reset()
    sensor.set_framesize(width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, chn=CAM_CHN_ID_0)
    sensor.set_pixformat(Sensor.RGB888, chn=CAM_CHN_ID_0)
    # 根据模式初始化显示器
    if DISPLAY_MODE == "VIRT":
        Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, fps=60)
    elif DISPLAY_MODE == "LCD":
        Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
    elif DISPLAY_MODE == "HDMI":
        Display.init(Display.LT9611, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
    MediaManager.init()
    sensor.run()

    while True:
        os.exitpoint()
        # 捕获通道0的图像
        img = sensor.snapshot(chn=CAM_CHN_ID_0)
        # 绘制内容
        # 1. 绘制绿色矩形
        img.draw_rectangle(20, 20, 100, 50, color=(0, 255, 0), thickness=5)
        # 2. 绘制红色圆形
        img.draw_circle(200, 150, 50, color=(255, 0, 0), thickness=3)
        # 3. 绘制蓝色线条
        img.draw_line(300, 50, 400, 200, color=(0, 0, 255), thickness=2)
        # 4. 绘制黄色字符串
        img.draw_string_advanced(50, 100, 32,"你好, 立创·庐山派K230-CanMV开发板!", color=(255, 255, 0), scale=2)
        # 5. 绘制十字交叉点
        img.draw_cross(400, 240, color=(255, 255, 255), size=20, thickness=2)
        # 显示捕获的图像
        Display.show_image(img)

except KeyboardInterrupt as e:
    print("用户停止: ", e)
except BaseException as e:
    print(f"异常: {e}")
finally:
    # 停止传感器运行
    if isinstance(sensor, Sensor):
        sensor.stop()
    # 反初始化显示模块
    Display.deinit()
    os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
    time.sleep_ms(100)
    # 释放媒体缓冲区
    MediaManager.deinit()
    

本文作者:hazy1k

本文链接:https://www.cnblogs.com/hazy1k/p/18711604

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   hazy1k  阅读(6)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起