openmv入门之路

2023-05-16

如果你发现OpenCV函数繁多!!!

如果你发现OpenCV配置繁琐!!!

如果你发现自己买不起miniPC!!!

请选择OpenMV来完成你的项目吧!!!

新篇章新阶段,来自其他小白提醒

  • OpenMV简介

OpenMV,其目标是成为机器视觉界的“Arduino”,它以STM32CPU为核心,提供Python的编程接口,成本低,拓展性好,不仅能够用来进行图像处理,还可以当作一个普通的单片机使用。OpenMV的像素较小,所以适用范围是一些对精度要求不高的视觉任务,例如:扫码,色块检测,目标跟踪,以及 一些简单的机器学习任务(当然,这里仅仅介绍与视觉有关的内容,除非你想用它去做嵌入式开发)。

  • OpenMV的安装

OpenMV的安装不需要像OpenMV一样配置一系列的环境,非常简便!!!
具体安装步骤可参考官网:

OpenMV IDE安装 | 星瞳科技​singtown.com/learn/49989/

  • OpenMV快速上手

如果你想尽快的对OpenMV的功能做出了解,并能够通过代码去实现简单的功能,可以参考如下材料:

10分钟快速上手 · OpenMV中文入门教程​book.openmv.cc/quick-starter.html正在上传…重新上传取消

  • 基于例程进行代码移植

如果我们去网页搜索我们想要完成的任务,我们搜到的基本都是使用OpenCV实现的代码,关于OpenMV的博客显然屈指可数,在这种情况下IDE中的示例则显得尤为重要,而官方的函数手册则更为重要了。

例如我们想进行色块检测并打印图中的色块摆放的顺序结果编码(如图从左向右从上向下编码为123312)1——红,2——绿,3——蓝:

首先我们可以在示例中发现multi_color_blob_tracking.py的例程:

# Multi Color Blob Tracking Example
#
# This example shows off multi color blob tracking using the OpenMV Cam.

import sensor, image, time, math

# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green things. You may wish to tune them...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds
              (30, 100, -64, -8, -32, 32), # generic_green_thresholds
              (0, 15, 0, 40, -80, -20)] # generic_blue_thresholds
# You may pass up to 16 thresholds above. However, it's not really possible to segment any
# scene with 16 thresholds before color thresholds start to overlap heavily.

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()

# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. Don't set "merge=True" becuase that will merge blobs which we don't want here.

while(True):
    clock.tick()
    img = sensor.snapshot()
    for blob in img.find_blobs(thresholds, pixels_threshold=200, area_threshold=200):
        # These values depend on the blob not being circular - otherwise they will be shaky.
        if blob.elongation() > 0.5:
            img.draw_edges(blob.min_corners(), color=(255,0,0))
            img.draw_line(blob.major_axis_line(), color=(0,255,0))
            img.draw_line(blob.minor_axis_line(), color=(0,0,255))
        # These values are stable all the time.
        img.draw_rectangle(blob.rect())
        img.draw_cross(blob.cx(), blob.cy())
        # Note - the blob rotation is unique to 0-180 only.
        img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
    print(clock.fps())

 

根据例程如何得到我们想要的程序呢?代码中的img.find_blobs()很明显是一个Lists,代表着很多个色块对象,我们想要获取色块位置就需要知道包络色块的矩形框的信息,这些信息都包含在这个对象的成员中。这就需要用到函数手册

https://docs.openmv.io/​docs.openmv.io/

我们搜索Blobs这个类可以看到其成员,之后的事情就是我们自己写代码了,通过调用其成员对色块进行筛选和处理,最终打印位置编码。

最终的程序和结果如下:

#color_test

# Multi Color Blob Tracking Example
#
# This example shows off multi color blob tracking using the OpenMV Cam.

import sensor, image, time, math

# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green things. You may wish to tune them...
thresholds = [(38, 65, 49, 114, -8, 113), # generic_red_thresholds
              (30, 80, -62, -33, -30, 74), # generic_green_thresholds
              (27, 56, -40, 59, -86, -41)] # generic_blue_thresholds
# You may pass up to 16 thresholds above. However, it's not really possible to segment any
# scene with 16 thresholds before color thresholds start to overlap heavily.
thresholds_red=((38, 65, 49, 114, -8, 113))
thresholds_green=((30, 80, -62, -33, -30, 74))
thresholds_blue=((27, 56, -40, 59, -86, -41))
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()

# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. Don't set "merge=True" becuase that will merge blobs which we don't want here.

while(True):
    clock.tick()
    img = sensor.snapshot()
    
    blobs_red=img.find_blobs([thresholds_red], pixels_threshold=200, area_threshold=200)
    blobs_green=img.find_blobs([thresholds_green], pixels_threshold=200, area_threshold=200)
    blobs_blue=img.find_blobs([thresholds_blue], pixels_threshold=200, area_threshold=200)
    
    for blobs in blobs_red:
        img.draw_rectangle(blobs.rect())
    for blobs in blobs_green:
        img.draw_rectangle(blobs.rect())
    for blobs in blobs_blue:
        img.draw_rectangle(blobs.rect())
    
    if len(blobs_red)==2:
        if blobs_red[0].cy()<blobs_red[1].cy():
            blobs_red_on=blobs_red[0]
            blobs_red_under=blobs_red[1]            
        else:
            blobs_red_on=blobs_red[1]
            blobs_red_under=blobs_red[0]            
    else:
        continue

    if len(blobs_green)==2:
        if blobs_green[0].cy()<blobs_green[1].cy():
            blobs_green_on=blobs_green[0]
            blobs_green_under=blobs_green[1]            
        else:
            blobs_green_on=blobs_green[1]
            blobs_green_under=blobs_green[0]
    else:
        continue

    if len(blobs_blue)==2:
        if blobs_blue[0].cy()<blobs_blue[1].cy():
            blobs_blue_on=blobs_blue[0]
            blobs_blue_under=blobs_blue[1]            
        else:
            blobs_blue_on=blobs_blue[1]
            blobs_blue_under=blobs_blue[0]
    else:
        continue

    color_list="abcdef"

    list_on=[blobs_red_on.cx(),blobs_green_on.cx(),blobs_blue_on.cx()]
    list_under=[blobs_red_under.cx(),blobs_green_under.cx(),blobs_blue_under.cx()]

    if min(list_on)==blobs_red_on.cx():
        color_list=color_list.replace('a','1')
        if max(list_on)==blobs_green_on.cx():
            color_list=color_list.replace('c','2')
            color_list=color_list.replace('b','3')
        else:
            color_list=color_list.replace('c','3')
            color_list=color_list.replace('b','2')
            
    if min(list_on)==blobs_green_on.cx():
        color_list=color_list.replace('a','2')
        if max(list_on)==blobs_red_on.cx():
            color_list=color_list.replace('c','1')
            color_list=color_list.replace('b','3')
        else:
            color_list=color_list.replace('c','3')
            color_list=color_list.replace('b','1') 
            
    if min(list_on)==blobs_blue_on.cx():
        color_list=color_list.replace('a','3')
        if max(list_on)==blobs_red_on.cx():
            color_list=color_list.replace('c','1')
            color_list=color_list.replace('b','2')
        else:
            color_list=color_list.replace('c','2')
            color_list=color_list.replace('b','1')
            
    if min(list_under)==blobs_red_under.cx():
        color_list=color_list.replace('d','1')
        if max(list_under)==blobs_green_under.cx():
            color_list=color_list.replace('f','2')
            color_list=color_list.replace('e','3')
        else:
            color_list=color_list.replace('f','3')
            color_list=color_list.replace('e','2')

    if min(list_under)==blobs_green_under.cx():
        color_list=color_list.replace('d','2')
        if max(list_under)==blobs_red_under.cx():
            color_list=color_list.replace('f','1')
            color_list=color_list.replace('e','3')
        else:
            color_list=color_list.replace('f','3')
            color_list=color_list.replace('e','1')

    if min(list_under)==blobs_blue_under.cx():
        color_list=color_list.replace('d','3')
        if max(list_under)==blobs_red_under.cx():
            color_list=color_list.replace('f','1')
            color_list=color_list.replace('e','2')
        else:
            color_list=color_list.replace('f','2')
            color_list=color_list.replace('e','1')

    print(color_list)
    
    print(clock.fps())

输出的是“123312”的编码以及帧率。

这里借助这个小例程分析如何基于例程进行程序的移植,希望能够对刚入手OpenMV的小伙伴有所启发。

类似的移植方法也可以用来进行串口通信,二维码的扫描等这些常用的功能。

  • 常用小工具

OpenMV提供了许多帮助调试的小工具,可以在界面——工具一栏中找到,例如在上述例程中需要标定thresholds,则点击“工具——视觉终端——阈值编辑器”可以方便的调整阈值进行标定,只需要记录下各阈值即可。

希望可以为大家快速上手OpenMV有所帮助!!!

参考资料:

OpenMV IDE安装 | 星瞳科技​singtown.com/learn/49989/

Overview — MicroPython 1.15 documentation

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openmv入门之路 的相关文章

随机推荐

  • 使用Docker部署软件运行环境

    什么是docker xff1f Docker是基于Go语言进行开发实现 xff0c 一个开源的应用容器引擎 采用Linux内核的cgroup xff0c namespace xff0c 以及AUFS类的Union FS等技术 xff0c 对
  • 【控制control】四足机器人运动学、动力学模型

    系列文章目录 提示 xff1a 这里可以添加系列文章的所有文章的目录 xff0c 目录需要自己手动添加 TODO 写完再整理 文章目录 系列文章目录前言一 四足机器人实际模型的物理难点二 四足机器人运动学模型1 方法一 xff1a DH法建
  • 【项目解读】fast_planner工程解读

    系列文章目录 提示 xff1a 这里可以添加系列文章的所有文章的目录 xff0c 目录需要自己手动添加 TODO 写完再整理 文章目录 系列文章目录前言一 规划系统运行逻辑 业务部分 1 Fast planner node cpp 程序入口
  • IMU方向位姿估计

    系列文章目录 提示 xff1a 这里可以添加系列文章的所有文章的目录 xff0c 目录需要自己手动添加 TODO 写完再整理 文章目录 系列文章目录前言一 方法一 xff1a IMU方向位姿可以直接从IMU本身提供的专有算法中获得 xff0
  • 【autoware的仿真平台】

    系列文章目录 提示 xff1a 这里可以添加系列文章的所有文章的目录 xff0c 目录需要自己手动添加 TODO 写完再整理 文章目录 系列文章目录前言一 仿真的必要性及常见的仿真工具介绍二 gazebo仿真插件介绍及源码解析1 gazeb
  • 【机械臂、无人机规控篇】(8)机械臂轨迹规划、跟踪控制方向

    系列文章目录 提示 xff1a 这里可以添加系列文章的所有文章的目录 xff0c 目录需要自己手动添加 TODO 写完再整理 文章目录 系列文章目录前言一 机械臂的规划控制和无人的规划控制的异同点分析1 规划的异同分析2 控制的异同分析 二
  • 微信支付——支付签名验证失败的坑

    只讲几个微信支付开发中的签名问题 xff08 JAVA版的公众号支付 xff09 第一个是获取订单数据时生成 xff0c 然后通过这些数据生成预支付订单 xff08 通过 统一下单 方法取得 xff09 xff0c 微信官方返回一串xml数
  • c++的多重继承

    一 前言 每个类只继承一个父辈 xff0c 在现实世界中事情通常是这样的 xff0c 但是有一些类却代表两个类的合成 例如两用沙发 xff0c 它是一张床 xff0c 也是一个沙发 二 示例代码 xff0c 用作下面提出问题使用 span
  • 学习 STM32之九轴姿态传感器(BWT901CL)串口通信读取数据

    由于个人应用到3轴传感器 xff0c 所以买了直接买了一个9轴的 xff0c 用于学习STM32Core平台串口2连接维特智能串口Normal协议 xff0c 然后通过串口1直接打印数据 xff0c 接收传感器数据和与传感器进行通信 xff
  • 用遗传算法求解旅行商问题

    以下是用遗传算法解决旅行商问题的实验报告 1 问题描述 旅行商问题 xff08 Travelling Salesman Problem 简记TSP xff0c 亦称货郎担问题 xff1a 设有n个城市和距离矩阵D 61 dij xff0c
  • 学习LLC谐振变换电路的工作原理

    五 学习LLC谐振变换电路的工作原理 在具有电阻R 电感L和电容C元件的交流电路中 xff0c 电路两端的电压与其中电流相位一般是不同的 如果调节电路元件 xff08 L或C xff09 的参数或电源频率 xff0c 可以使它们相位相同 x
  • 关于电赛应该了解的事

    2021年1月31日 xff0c 全国大学生电子设计竞赛组委会向各赛区组委会 各有关高校下发 关于组织2021年全国大学生电子设计竞赛的通知 xff0c 正式启动2021年全国竞赛组织工作 电赛越来越近 xff0c 很多大一大二的同学还没有
  • stm32的基本学习路径---新手指南

    心得 xff1a 本人学习STM32的时候有一些跟风的因素 xff0c 自以为学的芯片越多就越厉害 61 61 其实 xff0c 学习嵌入式重要的是整体的工程思想和项目经验积累 xff0c 说到底这些芯片 xff0c 我感觉学习起来都差不多
  • 初学stm32建议的---实用开发板推荐

    STM32编程作为一项实操性很强的技能 xff0c 所以要多实操 初学的话 xff0c 我觉得书籍就暂时先不买吧 xff0c 先考虑入手一块STM32开发板 xff0c 然后跟着开发板的教程走 几年前 xff0c 做STM32的教程有很多家
  • 嵌入式操作系统-ucos是什么?

    一句话概括ucos系统 xff1a 一款源代码开放的 xff0c 抢占式多任务实时操作系统 其在整个嵌入式产品的架构中的角色和主要功能代码如下图所示 xff1a ucos 系统建立了用户程序和底层硬件之间沟通的渠道 通过ucos系统的管理和
  • 自学stm32,需要会到什么程度能找到一份工作?

    我是从大一就开始接触单片机 xff0c 学过很多类型的单片机 从最简单的51单片机 xff08 stc xff0c atmel intel等类型都用过 xff09 到国内现在最火的stm32 xff08 推荐正点原子 xff0c 后期很多项
  • 学习STM32的寄存器版本好还是库函数版本好

    我个人认为 xff0c 在回答这个问题之前 xff0c 你得先问清楚自己 xff0c 我学习stm32 或者再往更深的地方走 xff0c 我学习单片机 xff0c 究竟是为了什么 xff1f 你现在是处于什么状态 xff1f 你是学生还是已
  • proteus 8 打开proteus 7版本仿真文件的两个方法

    Proteus版本一直在更新 xff0c 其中常见的大版本Proteus 7 和Proteus 8兼容是有问题的 xff0c Proteus是向上兼容的 xff0c 高版本可以打开低版本的仿真 xff0c 低版本打不开高版本的 Proteu
  • stm32 单片机主要优点有哪些?

    51单片机之所以成为经典 xff0c 成为易上手的单片机主要有以下特点 xff1a 特性 xff1a 1 从内部的硬件到软件有一套完整的按位操作系统 xff0c 称作位处理器 xff0c 处理对象不是字或字节而是位 不但能对片内某些特殊功能
  • openmv入门之路

    如果你发现OpenCV函数繁多 xff01 xff01 xff01 如果你发现OpenCV配置繁琐 xff01 xff01 xff01 如果你发现自己买不起miniPC xff01 xff01 xff01 请选择OpenMV来完成你的项目吧