通过Python调用OpenMV识别小球获取坐标

2023-05-16

OPenMV介绍

OpenMV是基于Python的嵌入式机器视觉模块,目标是成为机器视觉界的“Arduino”。它成本低易拓展,开发环境友好,除了用于图像处理外,还可以用Python调用其硬件资源,进行I/O控制,与现实世界进行交互。

一、如何通过串口发送数据—-UART
1、UART用法读写操作

uart.read(10)        # read 10 characters, returns a bytes object
                    # 读入10个字符, 返回一个比特对象
uart.read()            # read all available characters
                    # 读取所有的有效字符
uart.readline()        # read a line
                    # 读入一行
uart.readinto(buf)  # read and store into the given buffer
                    # 读入并且保存在缓存中
uart.write('abc')    # write the 3 characters
                    # 向串口写入3个字符abc

2、单个字符的读取与写入

uart.readchar()     # read 1 character and returns it as an integer
                    # 读入一个字符
uart.writechar(42)  # write 1 character
                    # 写入ASCALL码为42的字符

3、判断串口是否有数据

uart.any()          # returns the number of characters waiting

案例:
串口简单用例—》向串口发送数据的代码

# UART Control 串口通信

import time
from pyb import UART

uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
while(True):
    uart.write("Hello World!\r")
    print("Hello World")
    # 休眠1s
    time.sleep(1000)

串口简单用例—》向串口接收数据

# UART Control 串口通信

import time
from pyb import UART

uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters

while(True):

    if uart.any():
        # 判断是否有数据, 有的话就读入
        tmp_data = uart.readline()
        print(tmp_data)

    # 休眠1s
    time.sleep(1000)

二、如何通过OPenMV摄像头获取小球坐标
1、矩形绘制

/*
*  x: 矩形的左上角  x坐标
*  y:矩形的左上角 y坐标
*  width:矩形的宽度
*  height: 矩形的高度
*/
image.draw_rectangle([x, y, width, height])

2、十字绘制

/*
*  x: 十字的x坐标
*  y: 十字的y坐标
*/
image.draw_cross(x, y)

3、find_blobs函数

find_blobs(thresholds, invert=False, roi=Auto)

thresholds 颜色阈值 元组数组

invert=1 反转颜色阈值,invert=False默认不反转.

roi 设置颜色识别的视野区域,roi是一个元组, roi = (x, y, w, h),代表从左上顶点(x,y)开始的宽为w高为h的矩形区域,roi不设置的话默认为整个图像视野。

4、Blob 对象

{x:26, y:54, w:83, h:38, pixels:448, cx:65, cy:75, rotation:0.342305, code:1, count:1}
  1. x 代表矩形区域的左上角的x坐标
  2. y 代表矩形区域的左上角的y坐标
  3. w 矩形区域的宽度
  4. h 矩形区域的高度
  5. pixels 目标区域满足图像阈值范围的像素点的个数
  6. cx center x, 矩形区域中心的x坐标
  7. cy center y, 矩形区域中心的y坐标
  8. rotation 代表目标颜色区域blob的旋转角度
  9. code 代表颜色的编号, 它可以用来分辨这个这个矩形区域是用哪个threshold识别出来的
  10. count blob内包含的子blob个数。
    注:

    rotation 单位是弧度值,如果识别的物体是长条状的,例如钢笔, 那其取值范围为0-180度,如果是圆形的画, 其rotaiton值没有任何意义。
    code 颜色编号 取值范围 2^n : 1,2, 4, 8
    count 如果merge=False count恒等于1, 如果开启色块合并merge=True 则>=1

案例:

# Blob Detection Example
#
# This example shows off how to use the find_blobs function to find color
# blobs in the image. This example in particular looks for dark green objects.

import sensor, image, time

# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...
red_threshold_01 = (0, 35, 0, 50, -10, 40)

#设置红色的阈值,括号里面的数值分别是L A B 的最大值和最小值(minL, maxL, minA,
# maxA, minB, maxB),LAB的值在图像左侧三个坐标图中选取。如果是灰度图,则只需
#设置(min, max)两个数字即可。

# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False)
#关闭白平衡。白平衡是默认开启的,在颜色识别中,需要关闭白平衡。
clock = time.clock() # Tracks FPS.

while(True):
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot() # Take a picture and return the image.
    #  pixels_threshold=100, area_threshold=100
    blobs = img.find_blobs([red_threshold_01], area_threshold=150)

    if blobs:
    #如果找到了目标颜色
        print(blobs)
        for b in blobs:
        #迭代找到的目标颜色区域
            # Draw a rect around the blob.
            img.draw_rectangle(b[0:4]) # rect
            #用矩形标记出目标颜色区域
            img.draw_cross(b[5], b[6]) # cx, cy
            #在目标颜色区域的中心画十字形标记


    print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while
    # connected to your computer. The FPS should increase once disconnected.

三、综合案例
这里写图片描述
main.py文件如下:

# main.py -- put your code here!
import sensor, image, time
import protocol
import utils
from pyb import UART
import json

sensor.reset()  #摄像头初始化
sensor.set_pixformat(sensor.RGB565)  #设置为彩色模式
sensor.set_framesize(sensor.QQVGA)      #画幅为QQVGA即分辨率为160*120
sensor.skip_frames(time = 2000)         #跳过起始画面,获取稳定图像
sensor.set_auto_gain(False) #在色块检测模式下关闭自动补光
sensor.set_auto_whitebal(False) #关闭白平衡
clock = time.clock()

#根据测量设备小球颜色,并把LAB色值存储到集合中
red_threshold   = ( 65,75,-60,-40,30,48) #设置监测红色色块阈值
green_threshold   = ( 65,75,-60,-40,30,48) #设置检测绿色色块阈值
blue_threshold   = ( 65,75,-60,-40,30,48) #设置监测蓝色色块阈值
yellow_threshold   = ( 65,75,-60,-40,30,48) #设置监测黄色色块阈值

# 初始化各坐标值
xPositionNow = 0
yPositionNow = 0
xPositionLast = 0
yPositionLast = 0
imageSize = 128
count=0

#存储每个小球的坐标
matrix = [[] for i in range(10)]
index=0 #识别次数

xIndex=protocol.getColor() #获取要识别颜色小球
print('xIndex',xIndex)


#判断是要识别什么颜色的小球
xThreshold=(0,0,0,0,0,0) #默认值
if xIndex==0x01:
    xThreshold=red_threshold #红色
    print('当前要识别的小球颜色是红色')
elif xIndex==0x02:
    xThreshold=green_threshold #绿色
    print('当前要识别的小球的颜色是绿色')
elif xIndex==0x03:
    xThreshold=blue_threshold #蓝色
    print('当前要识别的小球的颜色是蓝色')
elif xIndex==0x04:
    xThreshold=yellow_threshold #黄色
    print('当前要识别的小球的颜色是黄色')
else:
    xThreshold=red_threshold #红色
    print('默认颜色是红色')

while(True):

    clock.tick()
    img = sensor.snapshot() #获取当期所采集到的图像快照
    # 设置色块阈值,具体数值情况可以通过OpenMVIDE中的阈值调整功能来得出
    # 工具 → Mechine Vision → Threshold Editor
    # area_threshold面积阈值设置为100 ,如果色块被面积小于100,则会被过滤掉
    # pixels_threshold 像素个数阈值,如果色块像素数量小于这个值,会被过滤掉
    # merge 设置为True,合并所有重叠的寻找到的blob为一个色块

    #识别
    blobs = img.find_blobs([xThreshold], pixels_threshold=10, area_threshold=10, merge=True)

    if blobs:
        print('sum ==================================', len(blobs),'\n\r')
        count=0

        for blob in blobs:
            # 绘制相应的图形,方便我们测试的时候使用
            img.draw_cross(blob.cx(), blob.cy())
            #用矩形标记出目标颜色区域
            img.draw_rectangle(blob[0:4]) # rect
            #在目标颜色区域的中心画十字形标记
            img.draw_circle(blob[5], blob[6],10, color = (255, 0, 0))



            x = blob.cx() - (imageSize/2)
            y = (imageSize/2) - blob.cy()
            xPositionLast = xPositionNow
            yPositionLast = yPositionNow
            # 这个0.7的数值不固定,只是在调试的时候为了使得像素点和坐标单位cm匹配所设置的数值
            xPositionNow = x * 0.7
            yPositionNow = y * 0.7
            # 测试时打印出当前坐标
            #print(xPositionNow)
            #print(yPositionNow)
            #print(xPositionNow, yPositionNow, end = ',')


            output_str="[%d,%d]" % (blob[5], blob[6])
            print(index,output_str)

            #print(',' + str(xPositionNow) + ',' +  str((-1)*yPositionNow) + ',')

            #识别五次就退出循环
            count=count+1
            if count<=5:
                matrix[index].append(blob[5])
                matrix[index].append(blob[6])
                time.sleep(1000)

        #识别次数
        index=index+1
        print('第几次识别',index)
        if index==10:
            index=0
            #break


protocol.py(UATR通讯类)

# protocol - By: LW - 周四 4月 26 2018

from pyb import UART
import time
import utils

#串口通讯
uart = UART(3, 115200)    #设置为串口3、波特率为115200发送数据
uart.init(115200, bits=8, parity=None, stop=1)

#返回当前指令数据
def getColor():
    xColor=receive() #xColor识别小球的颜色
    xIndex=0x01 #默认颜色

    if xColor: #不为空
        print('xColor 不为空')
        return readColor(xColor)  #xIndex识别小球的角标
    else:
        print('xColor 为空')
        return xIndex


#获取当前指令是要识别什么颜色
#[0x22,0xFF,0X01,0X00,0X00,0X00,0X01,0XBB]
def readColor(instruct=[]):
    #判断指令的长度
     if len(instruct)<8:
        print('读取的协议有问题!')
     print(instruct[0])
     print(instruct[1])
     if instruct[0]!="0x22" or instruct[1]!="0xFF":
        #如果不是规定的协议,就从新开启监听获取协议
        print('协议有问题!')
        return getColor()

     return filterColor(instruct[2])


#判断当前是什么颜色#默认为红色
#红色:0x01;绿色:0x02;蓝色:0x03;黄色:0x04;
def filterColor(isColor):
    #把十六进制转换为十制数
    colorStyle=int(isColor,16)
    if colorStyle<0x05:
        return colorStyle
    else:
        return 0x01 #默认为红色


#识别成功
#size:小球个数
def sendSuccessFour(size):
     sendFour(0x01,size)

#types:小球颜色 size小球个数
def sendSuccessEight(types,size):
     sendEight(types,0x01,size)

#识别失败
def sendFailFour():
     sendFour(0x00,0x00)

#识别失败
def sendFailEight(types):
     sendEight(types,0x00,0x00)

#当前OPenMV根据给定的颜色识别,返回4个字节指令(协议)
#tag:成功标记【0x01成功、0x00失败】
#size:小球的数量
def sendFour(tag,size):
    sendData=[0x55,0xFF]
    sendData.append(tag)
    sendData.append(size)
    sendArray(sendData)

#当前OPenMV根据给定的颜色识别,返回8个字节指令(协议)
#type:识别那种类型的小球
#tag:成功标记【0x01成功、0x00失败】
#size:小球的数量
def sendEight(types,tag,size):

    #指令类型
    sendData=[0x22,0xFF,0X00,0X00,0X00,0X00,0X01,0XBB]
    sendData[2]=types
    sendData[3]=tag
    sendData[4]=size
    sendArray(sendData)


#发送指令(默认发送5次)
#data[] 数组
def sendArray(data=[]):
    send(5,data)


#发送指令
#data 字符串
def sendReturn(data):
    uart.write(data+'\r\n')


#发送指令
#data[] 数据
#sendSize发送次数
def send(sendSize,data=[]):
    #十六进制数组转换为十六进制字符串
    buf=utils.arrayIntToStr(data)
    #每个一秒发送一次数据
    while sendSize>0:
        uart.write(buf+'\r\n')
        sendSize=sendSize-1
        print('准备发送指令!',buf)
        time.sleep(1000)


#接收指令(一直接受数据)
def receive():
    #一直循环获取数据
    while(True):
        print('接收中!')
        # 休眠1s
        time.sleep(1000)
        # 判断是否有数据, 有的话就读入
        if uart.any():
            #读取有效数据
            buf=[]
            for n in range(uart.any()):
                buf.append(uart.readchar())

            bufStr=utils.arrayIntToStr(buf)
            bufarray=utils.strToArrayHex(bufStr)
            print('接收到指令!',bufarray)

            #返回数据当前接收到数据
            sendReturn(bufStr)
            print('返回接收到指令!',bufStr)
            return bufarray



utlis.py(工具类)如下:

# Untitled - By: LW - 周六 4月 28 2018

#
# 数据类型转换
#
#十六进制转换为整数
def hexToInt(hexStr):
    return int(hexStr,16)

#八进制转换为整数
def octToInt(octStr):
    return int(octStr,8)

#整数转换为十六进制
def intToHex(number):
    return hexFilter(hex(unmber))

#整数转换为八进制
def intToOct(number):
    return oct(number)

#十进制数组转换为十六进制数组
def arrayIntToArrayHex(arrayInt=[]):
    for a in range(len(arrayInt)):
        arrayInt[a]=intToHex(arrayInt[a])
    return arrayInt

#十六进制字符串转换为整形数组
def strToArrayInt(bexStr):
    if bexStr.strip()=='':
        print('strToArrayInt参数为空!')
        return None

    #如果不是偶数,直接跳出
    if len(bexStr)%2!=0: return None

    #创建数组
    arrayBex=[]

    #转换整形为数组
    for b in range(len(bexStr)/2):
        ints=bexStr[b*2 :(b*2)+2]
        arrayBex.append(int(ints,16))

    return arrayBex

#十六进制字符串转换为十六进制数组
def strToArrayHex(bexStr):
    if bexStr.strip()=='':
        print('strToArrayHex参数为空!')
        return None
    #创建数组
    arrayBex=[]

    #如果不是偶数,直接跳出
    if (len(bexStr)%2)!=0: return None

    #转换十六进制为数组
    for b in range(len(bexStr)/2):
        hexs=bexStr[b*2:(b*2)+2]
        arrayBex.append('0x'+hexs)

    return arrayBex

#十六进制数组转换为十六进制字符串
def arrayBexToStr(arrayBex=[]):
    if not arrayBex:
        print('ArrayBexToStr参数为空!')
        return None

    #字符串拼接结果
    result=''
    for b in range(len(arrayBex)):
        #十六进制格式转换
        print(arrayBex[b])
        result+=hexFilter(arrayBex[b])
    print('arrayBexToStr Funtion returns to=====>'+result)
    return result


#十进制数组转换为十六进制字符串
def arrayIntToStr(arrayInt=[]):
    if not arrayInt:
        print('ArrayBexToStr参数为空!')
        return None

    #字符串拼接结果
    result=''
    for b in range(len(arrayInt)):
        #转换为十六进制
         hexStr=hex(arrayInt[b])
        #十六进制格式转换
         result+=hexFilter(hexStr)
    print('arrayIntToStr Funtion returns to=====>'+result)
    return result


#十六进制格式转换0XAA==>AA
def hexFilter(hexStr):
    #转换为大写
    hexStr=hexStr.upper()

    #字符串中包含OX
    if '0X' in hexStr:
        result=hexStr[2:len(hexStr)]
        if len(result)==1:
            result='0'+result
        return result

    #字符串长度为一的时候
    elif len(hexStr)==2:
         return hexStr
    #字符串长度为二的时候
    elif len(hexStr)==1:
        return '0'+hexStr

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

通过Python调用OpenMV识别小球获取坐标 的相关文章

  • 在PyGI中获取窗口句柄

    在我的程序中 我使用 PyGObject PyGI 和 GStreamer 在 GUI 中显示视频 该视频显示在Gtk DrawingArea因此我需要获取它的窗口句柄realize 信号处理程序 在 Linux 上 我使用以下方法获取该句
  • 使用 pandas.date_range() 生成多个日期时间,每周两个日期

    我在用着pd date range start date end date freq W MON 每周一生成每周频率日期时间start date 2017 01 01 and end date 2017 12 31 这意味着每月大约生成 4
  • 指示电子邮件的类型

    我有以下自动化程序 它将电子邮件发送给我自己 并添加了特定的链接 import win32com client as win32 import easygui import tkinter as to from tkinter import
  • 如何使用 Python boto3 获取 redshift 中的列名称

    我想使用 python boto3 获取 redshift 中的列名称 创建Redshift集群 将数据插入其中 配置的机密管理器 配置 SageMaker 笔记本 打开Jupyter Notebook写入以下代码 import boto3
  • 将 pandas 剪切操作转换为常规字符串

    我明白了 pandas cut 操作的输出 0 0 20 1 0 20 2 0 20 3 0 20 4 0 20 5 0 20 6 0 20 7 0 20 8 0 20 9 0 20 如何将 0 20 转换为 0 20 我正在这样做 str
  • 如何将 sql 数据输出到 QCalendarWidget

    我希望能够在日历小部件上突出显示 SQL 数据库中的一天 就像启动程序时突出显示当前日期一样 在我的示例中 它是红色突出显示 我想要发生的是 当用户按下突出显示的日期时 数据库中日期旁边的文本将显示在日历下方的标签上 这是我使用 QT De
  • python celery -A 的无效值无法加载应用程序

    我有一个以下项目目录 azima init py main py tasks py task py from main import app app task def add x y return x y app task def mul
  • 如何使用 Homebrew 在 Mac 上安装 Python 2 和 3?

    我需要能够在 Python 2 和 3 之间来回切换 我如何使用 Homebrew 来做到这一点 因为我不想弄乱路径并陷入麻烦 现在我已经通过 Homebrew 安装了 2 7 我会用pyenv https github com yyuu
  • 时间序列数据预处理 - numpy strides 技巧以节省内存

    我正在预处理一个时间序列数据集 将其形状从二维 数据点 特征 更改为三维 数据点 时间窗口 特征 在这样的视角中 时间窗口 有时也称为回顾 指示作为输入变量来预测下一个时间段的先前时间步长 数据点的数量 换句话说 时间窗口是机器学习算法在对
  • 为什么这个 if 语句会导致语法错误

    我正在尝试设置一个 elif 语句 如果用户按下 Enter 键 代码将继续 但是我不断遇到语法错误 GTIN 0 while True try GTIN int input input your gtin 8 number if len
  • 检索 geodjango 多边形对象的边界框

    如何在 geodjango 中获取 MultiPolygon 对象的边界框 在 API 中找不到任何内容http geodjango org docs geos html http geodjango org docs geos html
  • 为正则表达式编写解析器

    即使经过多年的编程 我很羞愧地说我从未真正完全掌握正则表达式 一般来说 当问题需要正则表达式时 我通常可以 在一堆引用语法之后 想出一个合适的正则表达式 但我发现自己越来越频繁地使用这种技术 所以 自学并理解正则表达式properly 我决
  • 使用 suds SOAP 库进行 HTTP 身份验证的奇怪行为

    我有一个正在运行的 python 程序 它使用 suds 通过 SOAP 获取大量数据 Web服务是通过分页功能实现的 这样我就可以抓取nnn每个 fetch 调用的行并获取下一个nnn与后续的电话 如果我使用如下代码向 HTTP 服务器进
  • Python守护进程:保持日志记录

    我有一个将一些数据记录到磁盘的脚本 logging basicConfig filename davis debug log level logging DEBUG logging basicConfig filename davis er
  • 如何通过函数注释指示函数需要函数作为参数,或返回函数?

    您可以使用函数注释 http www python org dev peps pep 3107 在python 3中指示参数和返回值的类型 如下所示 def myfunction name str age int gt str return
  • 在 numpy 中连接维度

    我有x 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 2 3 I want 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 6 也就是说 我想连接中间维度的所有项目 在这种特殊情况下我可以得到这
  • PyQt5:如何使QThread返回数据到主线程

    I am a PyQt 5 4 1 1初学者 我的Python是3 4 3 这是我尝试遵循的many https mayaposch wordpress com 2011 11 01 how to really truly use qthr
  • 将时间添加到日期时间

    我有一个像这样的日期字符串 然后使用strptime 所以就像这样 my time datetime datetime strptime 07 05 15 m d Y 现在我想添加 23 小时 59 分钟my time 我努力了 timed
  • 如何使用xlwt设置文本颜色

    我无法找到有关如何设置文本颜色的文档 在 xlwt 中如何完成以下操作 style xlwt XFStyle bold font xlwt Font font bold True style font font background col
  • 描述符“join”需要“unicode”对象,但收到“str”

    代码改编自here http wiki geany org howtos convert camelcase from foo bar to Foo Bar def lower case underscore to camel case s

随机推荐