OpenMV物品识别(以网球为例、模型训练)

目录-----接单片机设计:DPJSJ0X78

一、识别目标

二、可供采取的识别方式

1. 阈值识别:

2. 多阈值识别:

3. 多阈值加最多像素点识别:

4. 训练神经网络目标检测(重点) :

三、单阈值识别

1. 网球阈值获取

2. 代码编写

3. 识别效果

四、多阈值识别加最多像素点识别

1. 阈值获取

2. 代码编写

3. 效果演示

五、训练神经网络目标检测

1. 获取数据集

数据集采集使用方法

2. 训练神经网络目标检测

数据标注

标记错误解决方法

训练模型

选择模型

导入模型

3. 代码编写

注释版

无注释版

六、串口发送

七、总结

优缺点分析

单阈值识别

多阈值识别加最多像素点识别

训练神经网络目标检测

参考资料


一、识别目标

        使用OpenMV摄像头模块来识别网球,并将识别到的网球在图像中的坐标通过串口通信传输出去,以便其他设备接收并利用这些坐标信息进行后续处理或操作。

二、可供采取的识别方式

1. 阈值识别

        阈值识别是一种基于颜色、亮度或其他图像特征设定固定阈值来进行物体识别的方法。在OpenMV IDE(集成开发环境)中,可以通过分析网球在图像中的颜色特征,手动设定或自动获取颜色阈值,然后利用这些阈值对图像进行二值化处理,从而识别出网球。

2. 多阈值识别

        多阈值识别是对阈值识别方法的扩展,它使用多个阈值来处理更复杂的颜色或亮度变化。在网球识别中,由于光照条件、网球材质或表面磨损等因素,网球的颜色可能会有所变化。因此,可以设定多个颜色阈值范围,以覆盖网球在不同条件下的颜色变化。然后,对每个阈值范围分别进行阈值识别,并将结果合并以得到更准确的网球区域。

3. 多阈值加最多像素点识别

        在多阈值识别的基础上,增加像素量作为识别条件可以提高识别的准确性。具体做法是,在确定了网球可能的颜色范围后,不仅检查像素颜色是否满足阈值条件,还统计满足条件的像素数量。如果某个连通区域中的像素数量超过预设的阈值(即最小网球像素量),则认为该区域是一个网球。这种方法有助于减少误识别,例如将图像中的噪点或类似颜色的其他物体误认为是网球。

4. 训练神经网络目标检测(重点) :

        训练模型识别是一种基于机器学习或深度学习的方法。OpenMV官方提供了训练神经网络目标检测的教程(训练神经网络目标检测),可学习这个教程进行改造,实现自己想要的物品识别。

三、单阈值识别

1. 网球阈值获取

这里要保证摄像头处有网球

2. 代码编写

# 色块监测 例子
#
# 这个例子展示了如何通过find_blobs()函数来查找图像中的色块
# 这个例子查找的颜色是深绿色

import sensor, image, time
import ustruct
# 颜色追踪的例子,一定要控制环境的光,保持光线是稳定的。
green_threshold_num = 2
green_threshold = {}
green_threshold[0] = (48, 100, -128, -8, 20, 127)
green_threshold[1] = (15, 100, -46, -16, 12, 61)
# green_threshold   = (15, 100, -46, -16, 12, 61)
#设置绿色的阈值,括号里面的数值分别是L A B 的最大值和最小值(minL, maxL, minA,
# maxA, minB, maxB),LAB的值在图像左侧三个坐标图中选取。如果是灰度图,则只需
#设置(min, max)两个数字即可。

import display
import time
from pyb import UART

# UART 3, and baudrate.
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
#RX P5      TX P4
# 初始化串口


sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 格式为 RGB565.
sensor.set_framesize(sensor.QQVGA2) # 使用 QQVGA 速度快一些
sensor.skip_frames(time = 2000) # 跳过2000s,使新设置生效,并自动调节白平衡
sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的,在颜色识别中,一定要关闭白平衡。
sensor.set_auto_whitebal(False)
#关闭白平衡。白平衡是默认开启的,在颜色识别中,一定要关闭白平衡。
clock = time.clock() # 追踪帧率

lcd = display.SPIDisplay()




while(True):
    #lcd.write(sensor.snapshot())  # Take a picture and display the image.
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot() # 从感光芯片获得一张图像  宽=128 高=160
    lcd.write(img)  # Take a picture and display the image.
    length = 160
    width = 120
    # 水平方向翻转
    sensor.set_hmirror(True)
    # 垂直翻转图像
    sensor.set_vflip(True)
    blobs = img.find_blobs([green_threshold[0]], pixels_threshold = 50)#invert = 0
    #find_blobs(thresholds, invert=False, roi=Auto),thresholds为颜色阈值,
    #是一个元组,需要用括号[ ]括起来。invert=1,反转颜色阈值,invert=False默认 false没有反转
    #不反转。roi设置颜色识别的视野区域,roi是一个元组, roi = (x, y, w, h),代表
    #从左上顶点(x,y)开始的宽为w高为h的矩形区域,roi不设置的话默认为整个图像视野。
    #这个函数返回一个列表,[0]代表识别到的目标颜色区域左上顶点的x坐标,[1]代表
    #左上顶点y坐标,[2]代表目标区域的宽,[3]代表目标区域的高,[4]代表目标
    #区域像素点的个数,[5]代表目标区域的中心点x坐标,[6]代表目标区域中心点y坐标,
    #[7]代表目标颜色区域的旋转角度(是弧度值,浮点型,列表其他元素是整型),
    #[8]代表与此目标区域交叉的目标个数,[9]代表颜色的编号(它可以用来分辨这个
    #区域是用哪个颜色阈值threshold识别出来的)。
    #img.draw_circle(10, 10, 10, color=(0,255,0))
    # img.draw_rectangle(70, 0, 20, 60, color=(255,0,0)) # rect
    # img.draw_rectangle(70, 20, 20, 20, color=(255,0,0)) # rect
    Target = 0

    if blobs:
    #如果找到了目标颜色
        for b in blobs:
        #迭代找到的目标颜色区域
            # Draw a rect around the blob.
            if abs(b[3] - b[2]) <= 10 :
                img.draw_rectangle(b[0:4], color=(0,255,0)) # rect
                #用矩形标记出目标颜色区域
                img.draw_cross(b[5], b[6], color=(0,255,0)) # cx, cy
                #在目标颜色区域的中心画十字形标记
                #print(b[5], b[6])
                img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
                Target = 1
                uart.write("Target:" + str(Target) + ";X:" + str(b[5]) + ";Y:" + str(img.height() - b[6]) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")

                # 如果没有找到目标颜色
    if Target == 0:
        uart.write("Target:" + str(Target) + ";X:" + "0" + ";Y:" + "0" + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")

    img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
    img.draw_rectangle(32,120,128-32*2,40, color=(0,0,255))
    lcd.write(img)  # Take a picture and display the image.







    #print(clock.fps()) # 注意: 你的OpenMV连到电脑后帧率大概为原来的一半
    #如果断开电脑,帧率会增加

3. 识别效果

这种识别方式对环境,光照要求极高,环境变化后容易识别不准确。

四、多阈值识别加最多像素点识别

1. 阈值获取

        使用三、1中描述的阈值获取方法,在不同的环境和光照条件下分别获取相应的阈值,并将这些阈值保存到一个数组中。

2. 代码编写

# 色块监测 例子
#
# 这个例子展示了如何通过find_blobs()函数来查找图像中的色块
# 这个例子查找的颜色是深绿色

import sensor, image, time
import ustruct
# 颜色追踪的例子,一定要控制环境的光,保持光线是稳定的。
green_threshold_num = 4
green_threshold = {}
green_threshold[0] = (48, 100, -128, -8, 20, 127)
green_threshold[1] = (15, 100, -46, -16, 12, 61)
green_threshold[2] = (37, 64, -39, -12, 28, 127)
green_threshold[3] = (46, 98, -31, -16, 14, 127)
# green_threshold   = (15, 100, -46, -16, 12, 61)
#设置绿色的阈值,括号里面的数值分别是L A B 的最大值和最小值(minL, maxL, minA,
# maxA, minB, maxB),LAB的值在图像左侧三个坐标图中选取。如果是灰度图,则只需
#设置(min, max)两个数字即可。

import display
import time
from pyb import UART

# UART 3, and baudrate.
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
#RX P5      TX P4
# 初始化串口


sensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 格式为 RGB565.
sensor.set_framesize(sensor.QQVGA2) # 使用 QQVGA 速度快一些
sensor.skip_frames(time = 2000) # 跳过2000s,使新设置生效,并自动调节白平衡
sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的,在颜色识别中,一定要关闭白平衡。
sensor.set_auto_whitebal(False)
#关闭白平衡。白平衡是默认开启的,在颜色识别中,一定要关闭白平衡。
clock = time.clock() # 追踪帧率


lcd = display.SPIDisplay()

# 记录网球不同阈值的数组下标
green_threshold_i = 0
Target = 0
Xmax = 128
Ymax = 160
XSD = 0
uart.write("start")
while(True):


    #lcd.write(sensor.snapshot())  # Take a picture and display the image.
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot() # 从感光芯片获得一张图像  宽=128 高=160
    lcd.write(img)  # Take a picture and display the image.

    if green_threshold_i == green_threshold_num:
        # 此处发送数据
        uart.write("Target:" + str(Target) + ";X:" + str(Xmax) + ";Y:" + str(Ymax) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")
        if Target == 1:
            img.draw_circle(Xmax, img.height()-Ymax, 15, color = (255, 0, 0)) # 实际发送坐标(有效坐标)

        # 将发送完的数据清零重新计算
        green_threshold_i = 0
        Target = 0
        Xmax = 128
        Ymax = 160
        XSD = 0
    # 水平方向翻转
    sensor.set_hmirror(True)
    # 垂直翻转图像
    sensor.set_vflip(True)
    blobs = img.find_blobs([green_threshold[green_threshold_i]], pixels_threshold = 50)#invert = 0
    green_threshold_i = green_threshold_i + 1

    #find_blobs(thresholds, invert=False, roi=Auto),thresholds为颜色阈值,
    #是一个元组,需要用括号[ ]括起来。invert=1,反转颜色阈值,invert=False默认 false没有反转
    #不反转。roi设置颜色识别的视野区域,roi是一个元组, roi = (x, y, w, h),代表
    #从左上顶点(x,y)开始的宽为w高为h的矩形区域,roi不设置的话默认为整个图像视野。
    #这个函数返回一个列表,
    # [0]代表识别到的目标颜色区域左上顶点的x坐标,
    # [1]代表左上顶点y坐标,
    # [2]代表目标区域的宽,
    # [3]代表目标区域的高,
    # [4]代表目标区域像素点的个数,[5]代表目标区域的中心点x坐标,[6]代表目标区域中心点y坐标,
    #[7]代表目标颜色区域的旋转角度(是弧度值,浮点型,列表其他元素是整型),
    #[8]代表与此目标区域交叉的目标个数,[9]代表颜色的编号(它可以用来分辨这个
    #区域是用哪个颜色阈值threshold识别出来的)。
    #img.draw_circle(10, 10, 10, color=(0,255,0))
    # img.draw_rectangle(70, 0, 20, 60, color=(255,0,0)) # rect
    # img.draw_rectangle(70, 20, 20, 20, color=(255,0,0)) # rect


    if blobs:
    #如果找到了目标颜色
        for b in blobs:
        #迭代找到的目标颜色区域
            # Draw a rect around the blob.
            if abs(b[3] - b[2]) <= 10 :
                # img.draw_rectangle(b[0:4], color=(0,255,0)) # rect
                #用矩形标记出目标颜色区域
                # img.draw_cross(b[5], b[6], color=(0,255,0)) # cx, cy
                #在目标颜色区域的中心画十字形标记
                #print(b[5], b[6])
                # img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
                Target = 1
                X = b[5]
                Y = img.height() - b[6]
                if b[4] > XSD:
                    # 记录最大且有效的坐标点
                    Xmax = X
                    Ymax = Y
                    XSD = b[4]
                # if green_threshold_i == green_threshold_num - 1:
                #    uart.write("Target:" + str(Target) + ";X:" + str(b[5]) + ";Y:" + str(img.height() - b[6]) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")

                # 如果没有找到目标颜色
    # if Target == 0:
    #    uart.write("Target:" + str(Target) + ";X:" + "0" + ";Y:" + "0" + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")

    img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
    img.draw_rectangle(40,100,128-40*2,60, color=(0,0,255))
    
    # 显示到lcd屏上面
    lcd.write(img)  # Take a picture and display the image.







    #print(clock.fps()) # 注意: 你的OpenMV连到电脑后帧率大概为原来的一半
    #如果断开电脑,帧率会增加

3. 效果演示

我的最新作品,快来一睹为快!

五、训练神经网络目标检测

1. 获取数据集

首先打开OpenMVIDE连接openmv,然后找到(新数据集)

数据集采集使用方法

2. 训练神经网络目标检测

OpenMV合作伙伴EdgeImpulse在线训练网站:https://www.edgeimpulse.com/

加入数据集

yes等待后,叉掉即可。

数据标注

标记错误解决方法

训练模型

选择模型

导入模型

获取模型解压后如下

3. 代码编写

将代码修改,加入lcd屏后串口发送

注释版

# Edge Impulse - OpenMV FOMO Object Detection Example
#
# 这个工作受MIT许可证授权。
# 版权所有 (c) 2013-2024 OpenMV LLC。保留所有权利。
# 许可证详情见:https://github.com/openmv/openmv/blob/master/LICENSE

# 导入必要的库
import sensor, image, time, os, ml, math, uos, gc
from ulab import numpy as np
import ustruct
import display
from pyb import UART

# 配置UART串口,使用UART 3,波特率115200
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
# RX连接P5, TX连接P4
# 初始化串口
clock = time.clock() # 用于追踪帧率

# 初始化LCD显示屏
lcd = display.SPIDisplay()

# 初始化摄像头传感器
sensor.reset()                         # 重置并初始化传感器
sensor.set_pixformat(sensor.RGB565)    # 设置像素格式为RGB565(或灰度)
sensor.set_framesize(sensor.QQVGA2)    # 使用QQVGA分辨率以提高速度
sensor.set_windowing((240, 240))       # 设置240x240的窗口
sensor.skip_frames(time=2000)          # 让摄像头调整

# 加载模型
net = None
labels = None
min_confidence = 0.5                   # 设置最小置信度阈值

try:
    # 尝试加载模型,如果剩余内存少于64K,则将模型文件加载到Flash中
    net = ml.Model("trained.tflite", load_to_fb=uos.stat('trained.tflite')[6] > (gc.mem_free() - (64*1024)))
except Exception as e:
    # 如果加载失败,抛出异常
    raise Exception('加载"trained.tflite"失败,是否已将.tflite和labels.txt文件复制到存储设备? (' + str(e) + ')')

try:
    # 尝试加载标签文件
    labels = [line.rstrip('\n') for line in open("labels.txt")]
except Exception as e:
    # 如果加载失败,抛出异常
    raise Exception('加载"labels.txt"失败,是否已将.tflite和labels.txt文件复制到存储设备? (' + str(e) + ')')

# 定义颜色列表,用于绘制检测到的对象边框
colors = [ 
    (255,   0,   0),
    (  0, 255,   0),
    (255, 255,   0),
    (  0,   0, 255),
    (255,   0, 255),
    (  0, 255, 255),
    (255, 255, 255),
]

# 设置置信度阈值列表
threshold_list = [(math.ceil(min_confidence * 255), 255)]

# 定义后处理函数,用于处理模型输出
def fomo_post_process(model, inputs, outputs):
    # 获取模型的输出形状
    ob, oh, ow, oc = model.output_shape[0]
    
    # 计算x和y方向的缩放比例
    x_scale = inputs[0].roi[2] / ow
    y_scale = inputs[0].roi[3] / oh
    scale = min(x_scale, y_scale)
    
    # 计算x和y方向的偏移量
    x_offset = ((inputs[0].roi[2] - (ow * scale)) / 2) + inputs[0].roi[0]
    y_offset = ((inputs[0].roi[3] - (oh * scale)) / 2) + inputs[0].roi[1]
    
    # 初始化列表,用于存储每个类别的检测结果
    l = [[] for i in range(oc)]
    
    # 遍历每个输出通道
    for i in range(oc):
        # 将输出通道的数据转换为图像
        img = image.Image(outputs[0][0, :, :, i] * 255)
        # 在图像中查找二值化区域(blobs)
        blobs = img.find_blobs(
            threshold_list, x_stride=1, y_stride=1, area_threshold=1, pixels_threshold=1
        )
        # 遍历每个检测到的区域
        for b in blobs:
            rect = b.rect()  # 获取区域的矩形框
            x, y, w, h = rect
            # 计算区域的置信度
            score = img.get_statistics(thresholds=threshold_list, roi=rect).l_mean() / 255.0
            # 将区域的坐标和尺寸转换回原始图像坐标系
            x = int((x * scale) + x_offset)
            y = int((y * scale) + y_offset)
            w = int(w * scale)
            h = int(h * scale)
            # 将检测结果添加到列表中
            l[i].append((x, y, w, h, score))
    return l

# 重置帧率追踪器
clock = time.clock()

# 初始化变量
Target = 0  # 目标检测标志
Xmax = 0    # 最大X坐标
Ymax = 0    # 最大Y坐标
# 向串口发送开始信号
uart.write("start")
while(True):
    clock.tick()  # 更新帧率追踪器
    
    # 拍摄一帧图像
    img = sensor.snapshot()
    # 水平翻转图像
    sensor.set_hmirror(True)
    # 垂直翻转图像
    sensor.set_vflip(True)
    # 通过串口发送当前检测状态和目标位置信息
    uart.write("Target:" + str(Target) + ";X:" + str(Xmax) + ";Y:" + str(Ymax) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")
    print("Target:" + str(Target) + ";X:" + str(Xmax) + ";Y:" + str(Ymax) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")
    # 重置变量
    Xmax = 0
    Ymax = 0
    Target = 0
    # 使用模型进行预测,并处理输出结果
    for i, detection_list in enumerate(net.predict([img], callback=fomo_post_process)):
        if i == 0: continue  # 跳过背景类别
        if len(detection_list) == 0: continue  # 如果该类别没有检测结果,则跳过
        
        # 打印类别标签
        print("********** %s **********" % labels[i])
        
        # 遍历检测结果
        for x, y, w, h, score in detection_list:
            Target = 1  # 设置目标检测标志
            # 计算中心坐标
            center_x = math.floor(x + (w / 2))
            center_y = math.floor(y + (h / 2))
            # 更新最大X坐标和Y坐标(注意Y坐标需要转换为相对于底部的距离)
            Xmax = center_x
            Ymax = img.height() - center_y
            # 打印检测结果
            print(f"x {center_x}\ty {center_y}\tscore {score}")
            # 在图像上绘制检测到的对象中心
            img.draw_circle((center_x, center_y, 12), color=colors[i])
    
    # 打印当前帧率
    print(clock.fps(), "fps", end="\n\n")
    # 在图像上绘制一个十字标记和一个矩形框(仅用于演示)
    img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
    img.draw_rectangle(40,100,128-40*2,60, color=(0,0,255))
    
    # 将图像显示到LCD上
    lcd.write(img)

无注释版

# Edge Impulse - OpenMV FOMO Object Detection Example
#
# This work is licensed under the MIT license.
# Copyright (c) 2013-2024 OpenMV LLC. All rights reserved.
# https://github.com/openmv/openmv/blob/master/LICENSE

import sensor, image, time, os, ml, math, uos, gc
from ulab import numpy as np
import ustruct
import display
from pyb import UART

# UART 3, and baudrate.
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
#RX P5      TX P4
# 初始化串口
clock = time.clock() # 追踪帧率


lcd = display.SPIDisplay()

sensor.reset()                         # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565)    # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QQVGA2) # 使用 QQVGA 速度快一些
sensor.set_windowing((240, 240))       # Set 240x240 window.
sensor.skip_frames(time=2000)          # Let the camera adjust.

net = None
labels = None
min_confidence = 0.5

try:
    # load the model, alloc the model file on the heap if we have at least 64K free after loading
    net = ml.Model("trained.tflite", load_to_fb=uos.stat('trained.tflite')[6] > (gc.mem_free() - (64*1024)))
except Exception as e:
    raise Exception('Failed to load "trained.tflite", did you copy the .tflite and labels.txt file onto the mass-storage device? (' + str(e) + ')')

try:
    labels = [line.rstrip('\n') for line in open("labels.txt")]
except Exception as e:
    raise Exception('Failed to load "labels.txt", did you copy the .tflite and labels.txt file onto the mass-storage device? (' + str(e) + ')')

colors = [ # Add more colors if you are detecting more than 7 types of classes at once.
    (255,   0,   0),
    (  0, 255,   0),
    (255, 255,   0),
    (  0,   0, 255),
    (255,   0, 255),
    (  0, 255, 255),
    (255, 255, 255),
]

threshold_list = [(math.ceil(min_confidence * 255), 255)]

def fomo_post_process(model, inputs, outputs):
    ob, oh, ow, oc = model.output_shape[0]

    x_scale = inputs[0].roi[2] / ow
    y_scale = inputs[0].roi[3] / oh

    scale = min(x_scale, y_scale)

    x_offset = ((inputs[0].roi[2] - (ow * scale)) / 2) + inputs[0].roi[0]
    y_offset = ((inputs[0].roi[3] - (ow * scale)) / 2) + inputs[0].roi[1]

    l = [[] for i in range(oc)]

    for i in range(oc):
        img = image.Image(outputs[0][0, :, :, i] * 255)
        blobs = img.find_blobs(
            threshold_list, x_stride=1, y_stride=1, area_threshold=1, pixels_threshold=1
        )
        for b in blobs:
            rect = b.rect()
            x, y, w, h = rect
            score = (
                img.get_statistics(thresholds=threshold_list, roi=rect).l_mean() / 255.0
            )
            x = int((x * scale) + x_offset)
            y = int((y * scale) + y_offset)
            w = int(w * scale)
            h = int(h * scale)
            l[i].append((x, y, w, h, score))
    return l

clock = time.clock()

Target = 0
Xmax = 0
Ymax = 0
uart.write("start")
while(True):
    clock.tick()

    img = sensor.snapshot()
    # 水平方向翻转
    sensor.set_hmirror(True)
    # 垂直翻转图像
    sensor.set_vflip(True)
    uart.write("Target:" + str(Target) + ";X:" + str(Xmax) + ";Y:" + str(Ymax) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")
    print("Target:" + str(Target) + ";X:" + str(Xmax) + ";Y:" + str(Ymax) + ";TargetX:" + str(img.width()) + ";TargetY:" + str(img.height()) + ";")
    Xmax = 0
    Ymax = 0
    Target = 0
    for i, detection_list in enumerate(net.predict([img], callback=fomo_post_process)):
        if i == 0: continue  # background class
        if len(detection_list) == 0: continue  # no detections for this class?

        print("********** %s **********" % labels[i])

        for x, y, w, h, score in detection_list:
            Target = 1
            center_x = math.floor(x + (w / 2))
            center_y = math.floor(y + (h / 2))
            Xmax = center_x
            Ymax = img.height() - center_y
            print(f"x {center_x}\ty {center_y}\tscore {score}")
            img.draw_circle((center_x, center_y, 12), color=colors[i])

    print(clock.fps(), "fps", end="\n\n")
    img.draw_cross(64, 80, color=(255,0,0)) # cx, cy
    img.draw_rectangle(40,100,128-40*2,60, color=(0,0,255))

    lcd.write(img)  # Take a picture and display the image.

六、串口发送

Target:1;X:<X_COORD>;Y:<Y_COORD>;TargetX:<IMG_WIDTH>;TargetY:<IMG_HEIGHT>;

七、总结

优缺点分析

单阈值识别

  • 优点
    • 实现简单:代码逻辑相对简单,易于理解和上手,对于初学者来说是一种快速实现目标识别的方法。
    • 计算效率高:由于只使用一个固定的颜色阈值进行二值化处理,计算量较小,能保证较高的帧率,实时性较好。
  • 缺点
    • 对环境要求高:光照、网球材质、表面磨损等因素导致网球颜色变化时,识别准确性会大幅下降,适应性较差。
    • 误识别率高:容易将图像中的噪点或类似颜色的其他物体误认为是网球,鲁棒性不足。

多阈值识别加最多像素点识别

  • 优点
    • 适应性增强:通过设置多个颜色阈值范围,能覆盖网球在不同光照和环境条件下的颜色变化,提高了识别的适应性。
    • 减少误识别:增加像素量作为识别条件,有助于排除图像中的噪点和小面积的类似颜色区域,降低误识别率。
  • 缺点
    • 阈值获取复杂:需要在不同环境和光照条件下分别获取阈值,并保存到数组中,增加了前期准备工作的复杂度。
    • 计算量增加:对每个阈值范围分别进行阈值识别,并合并结果,计算量相对单阈值识别有所增加,可能会影响帧率。

训练神经网络目标检测

  • 优点
    • 识别准确性高:通过大量数据训练得到的模型,能够学习到网球的特征,对不同光照、角度和环境下的网球都有较好的识别效果,鲁棒性强。
    • 适应性强:可以适应网球颜色、形状等的变化,对于复杂场景的处理能力优于传统的阈值识别方法。
  • 缺点
    • 训练成本高:需要获取大量的数据集,并进行标注,训练过程也需要一定的计算资源和时间。
    • 模型加载和运行要求高:需要将训练好的模型文件和标签文件复制到存储设备,且对设备的内存和计算能力有一定要求,会影响设备的运行效率。

参考资料

1. 实际道路环境交通标志识别 - 自行训练神经网络目标点检测

2. OpenMV 图像串口传输示例

接单片机设计:DPJSJ0X78

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0X78

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值