2023年电赛---运动目标控制与自动追踪系统(E题)发挥题思路

前言

(1)因为博客编辑字数超过1W字会导致MD编辑器非常卡顿。所以我将发挥题和基础题的思路拆开了。
(2)更新日记:
<1>2023年8月4日,9点20分。分离发挥题思路和基础题思路,增加了博主Huiyeee整体代码,增加关于红点被黑带吸收问题的调试方法
<2>2023年8月4日,15点55分。回答追小球代码中的目标值是那个。

关于红点被黑带吸收问题

让IDE上出现红点

(1)很多人反馈,红点被黑色矩形框吸收了,识别不到。
(2)这边推荐的调试办法如下:
<1>首要目的是让PC端的IDE上人们肉眼能够看到红色激光。所以外面要适当调整下面初始化部分代码。
<2>我们可以将RGB565改成GRAYSCALE的灰度图。
<3>适当提高图像分辨率,将QQVGA改成其他图像画质。
<4>设置亮度,因为是从OpenART移植过来的,所以亮度不能是3000。使用OpenMV的同学请注意,应该是-3到+3.

在这里插入图片描述

<5>曝光度可以按照另外一位博主的来。通过调整曝光度,可以控制图像的明暗程度,从而创造出不同的视觉效果。我们这里没有使用sensor.set_auto_exposure()函数设置曝光度,所以是默认打开了的。你们可以看看另外一位博主的思路和调整。
<6>我们图像识别要关闭白平衡和自增益。但是如果调节出来没结果。可以尝试打开看看有木有优化

# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 设置图像色彩格式为RGB565格式
sensor.set_framesize(sensor.QQVGA)  # 设置图像大小为160*120
sensor.set_auto_whitebal(True)      # 设置自动白平衡
sensor.set_brightness(3000)         # 设置亮度为3000
sensor.skip_frames(time = 20)       # 跳过帧

(3)注意,这一阶段只需要调整摄像头的初始化!!!PC端IDE出现了红色斑点再开始处理!!!

白平衡和自增益的作用

(1)关闭白平衡和自增益可能适用于以下场景:
<1>保持色彩一致性:在某些图像识别应用中,特别是涉及色彩信息重要性较高的场景,关闭白平衡可以保持图像中的色彩一致性。白平衡会根据不同光源调整图像颜色,这可能导致相同对象在不同光照条件下的颜色出现差异,影响识别的准确性。
<2>特定光照条件下的优化:在一些特殊环境中,如低光照条件或强烈光线照射的情况下,关闭自增益可以避免图像过度曝光或欠曝光。这样做可以保留图像中更多细节,有助于图像识别算法更好地处理图像。
<3>原始数据分析:在某些图像分析应用中,关闭白平衡和自增益可以使用原始的传感器数据进行分析,而不受相机的颜色处理和亮度调整影响。这可以提供更纯粹、更原始的数据,有助于一些特定图像处理和识别算法的优化。
(2)需要注意的是,关闭白平衡和自增益也可能导致一些挑战,比如图像中的颜色信息可能会出现较大的变化,而且在某些场景下可能需要更复杂的图像处理算法来应对不同光照条件下的挑战。因此,在图像识别应用中是否关闭白平衡和自增益需要根据具体的情况和应用场景进行权衡和决策。

发挥题思路

第一问 — 追踪

(1)我个人认为这个必须上PID了。我个人认为这个题目和OpenMV的追小球云台代码类似。
(2)基础题目我认为一个OpenMV就可以完成。而发挥题目需要两个OpenMV。这两个OpenMV一个放红色激光笔,一个放绿色激光笔。
(3)各位可以综合追小球云台的代码,以及我下面讲的:关于C站那位博主代码的注意事项 部分
(4)追踪的绿色激光笔建议。
<1>变成灰度图,这样可以消除其他颜色的干扰,只观察红色。然后追踪。
<2>提高分辨率,较高的分辨率,能够提供更好的效果。
<3>使用多组颜色阈值,就像OpenMV多颜色识别详解的代码那样。让识别的颜色阈值变成多组。提高分辨效果。

第二问 — 追踪和走基础题3,4问

如果基础题做出来了,以及发挥题的追踪做出来了。那么就直接用基础题的红色激光笔走,然后发挥题追踪。这个和上面的代码应该是差不多的。

第三问 — 暂停键

这个我还是建议自己焊接一个按键,并联一个104的电容,进行硬件方面的按键消抖。然后自己写逻辑代码。

在这里插入图片描述

main.py

(1)以下为官方的追小球云台代码,我增加了中文注释。
(2)因为GitHub是在外网,所以我直接复制过来了。但是总是有一些网友,硬要官方的GitHub链接。我也贴到了前言部分。

代码

import sensor, image, time

from pid import PID
from pyb import Servo  #从内置pyb导入servo类,也就是舵机控制类

pan_servo=Servo(1)  #定义两个舵机,对应P7引脚
tilt_servo=Servo(2) #定义两个舵机,对应P8引脚

pan_servo.calibration(500,2500,500)
tilt_servo.calibration(500,2500,500)

red_threshold  = (13, 49, 18, 61, 6, 47)  #设置红色阈值

pan_pid = PID(p=0.07, i=0, imax=90) #PID参数,只需要调整P量即可,设置P7引脚的PI值
tilt_pid = PID(p=0.05, i=0, imax=90) #PID参数,只需要调整P量即可,设置P8引脚的PI值
#pan_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
#tilt_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID

sensor.reset() # 初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565) # 使用 RGB565 彩图
sensor.set_framesize(sensor.QQVGA) # 使用 QQVGA 分辨率
sensor.skip_frames(10) #跳过几帧,让新的设置生效。
sensor.set_auto_whitebal(False) # 因为是颜色识别,所以需要把白平衡关闭
clock = time.clock() # 追踪帧率,影响不大

#__________________________________________________________________
#定义寻找最大色块的函数,因为图像中有多个色块,所以追踪最大的那个
def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob

#__________________________________________________________________
while(True):
    clock.tick() # 跟踪快照()之间经过的毫秒数。
    img = sensor.snapshot() # 截取一张图片

    blobs = img.find_blobs([red_threshold]) #识别红色阈值
    if blobs:   #如果找到红色色块
        max_blob = find_max(blobs)  #调用上面自定义函数,找到最大色块
        pan_error = max_blob.cx()-img.width()/2
        tilt_error = max_blob.cy()-img.height()/2

        print("pan_error: ", pan_error)

        img.draw_rectangle(max_blob.rect()) # 在找到最大色块画一个矩形框
        img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy

        pan_output=pan_pid.get_pid(pan_error,1)/2
        tilt_output=tilt_pid.get_pid(tilt_error,1) #上面两个都说进行PID运算
        print("pan_output",pan_output)
        pan_servo.angle(pan_servo.angle()+pan_output) #将最终值传入两个舵机中,追踪目标
        tilt_servo.angle(tilt_servo.angle()-tilt_output)# 因为两个舵机方向和摆放位置不同,所以一个是+一个是-

舵机控制

舵机选择

(1)Servo是舵机控制类。因为我们使用from pyb import Servo直接从pyd导入了servo类。所以可以直接写成Servo()。
(2)引脚对应关系:Servo(1)——P7,Servo(2)——P8,Servo(3)——P9。
(3)
<1>因此我们可以知道,pan_servo.calibration就是对P7进行相应的控制,因为pan_servo=Servo(1)。
<2>tilt_servo.calibration就是对P8控制,因为tilt_servo=Servo(2)

在这里插入图片描述

舵机脉冲设置

(1)pan_servo.calibration(500,2500,500) , 这个其实就是设置舵机的脉宽的。因为我们知道,常见的舵机周期都是20ms,脉宽都是再500us到2500us之间。
(2)所以这里的第一个参数是500,第二个参数是2500。第三个参数是舵机0°位置,根据下图可以知道,也是500。最后两个值是可以填可不填的,个人不建议填写。

在这里插入图片描述
在这里插入图片描述

PID目标值是那个

pan_servo.angle()是当前舵机角度,pan_output是通过PID计算出来的偏移角度。

颜色阈值设置

(1)因为我们要追踪红色,所以是使用red_threshold = (13, 49, 18, 61, 6, 47) 进行设置阈值。
(2)颜色阈值设置教程:OpenMV颜色阈值设置

PID的P和I参数设置

(1)注意,因为云台是比较稳定的,不要求高反应速度,所以我猜测只使用了PI,而没有使用PID。因此我们可以看到pan_pid和tilt_pid只有P和I两个参数。
(2)I的参数不需要进行调整!imax是用于积分限幅的,这个也别更改!,如果你的云台抖动厉害,说明P过大了,需要调小。
(3)如果你感觉你云台反应太慢,就需要调高P值。
(4)最佳的P值是,你云台有抖动的前一个值。这个才是P的最优值。但是我认为,P没必要太大,因为云台还是比较稳的。
(5)所以说,只需要调整P值,I值和imax值不需要进行调整!!!

帧率禁用

(1)当OpenMV连接电脑端IDE的时候,运行帧率和不连接电脑端IDE是不一样的。因为我们连接上电脑端IDE的时候,OpenMV会向电脑端IDE传输数据,所以会导致帧率下降。
(2)帧率下降,会导致我们实际脱机跑的时候,PID参数和连接上电脑端IDE时候的PID参数不一样。
(3)所以我们需要点击电脑端右上角的禁用,或者是Disable。被禁用之后,我们的效果就是脱机之后真实运行效果。

在这里插入图片描述

pid.py

(1)这里面的代码我们不需要管,就算PID的代码。
(2)再次强调,这里请别擅自更改,出现问题自己负责。

from pyb import millis
from math import pi, isnan
 
class PID:
    _kp = _ki = _kd = _integrator = _imax = 0
    _last_error = _last_derivative = _last_t = 0
    _RC = 1/(2 * pi * 20)
    def __init__(self, p=0, i=0, d=0, imax=0):
        self._kp = float(p)
        self._ki = float(i)
        self._kd = float(d)
        self._imax = abs(imax)
        self._last_derivative = float('nan')
 
    def get_pid(self, error, scaler):
        tnow = millis()
        dt = tnow - self._last_t
        output = 0
        if self._last_t == 0 or dt > 1000:
            dt = 0
            self.reset_I()
        self._last_t = tnow
        delta_time = float(dt) / float(1000)
        output += error * self._kp
        if abs(self._kd) > 0 and dt > 0:
            if isnan(self._last_derivative):
                derivative = 0
                self._last_derivative = 0
            else:
                derivative = (error - self._last_error) / delta_time
            derivative = self._last_derivative + \
                                     ((delta_time / (self._RC + delta_time)) * \
                                        (derivative - self._last_derivative))
            self._last_error = error
            self._last_derivative = derivative
            output += self._kd * derivative
        output *= scaler
        if abs(self._ki) > 0 and dt > 0:
            self._integrator += (error * self._ki) * scaler * delta_time
            if self._integrator < -self._imax: self._integrator = -self._imax
            elif self._integrator > self._imax: self._integrator = self._imax
            output += self._integrator
        return output
    def reset_I(self):
        self._integrator = 0
        self._last_derivative = float('nan')

关于C站那位博主代码的注意事项

代码

原文链接 : https://blog.csdn.net/weixin_52385589/article/details/126334744

感光器初始化代码

sensor.reset()
    sensor.set_auto_gain(False)
    sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.RGB565
    sensor.set_framesize(sensor.  QVGA) # or sensor.QVGA (or others)
    sensor.skip_frames(time=900) # Let new settings take affect.
    sensor.set_auto_exposure(False, 1000)#在这里调节曝光度,调节完可以比较清晰地看清激光点
    sensor.set_auto_whitebal(False) # turn this off.
    sensor.set_auto_gain(False) # 关闭增益(色块识别时必须要关)

识别激光点代码

def color_blob(threshold):

    blobs = img.find_blobs(threshold,x_stride=1, y_stride=1, area_threshold=0, pixels_threshold=0,merge=False,margin=1)

    if len(blobs)>=1 :#有色块
        # Draw a rect around the blob.
        b = blobs[0]
        #img.draw_rectangle(b[0:4]) # rect
        cx = b[5]
        cy = b[6]
        for i in range(len(blobs)-1):
            #img.draw_rectangle(b[0:4]) # rect
            cx = blobs[i][5]+cx
            cy = blobs[i][6]+cy
        cx=int(cx/len(blobs))
        cy=int(cy/len(blobs))
        #img.draw_cross(cx, cy) # cx, cy
        print(cx,cy)
        return int(cx), int(cy)
    return -1, -1 #表示没有找到

颜色阈值

threshold=[(60, 255, -20, 20, -20, 20)]

整体代码

(1)这个是那位博主的整体代码,感兴趣的可以拿过来用。
(2)版权归C站博主Huiyeee所有!用了代码的同学,一定要去Huiyeee的博主下面感谢!!!

def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size :
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob


def FindCR():

    counts=0
    w_avg=0
    x_avg=0
    y_avg=0
    judge=0
    shape=0
    c_times=0
    r_times=0
    max_size=0
    cx=0
    cy=0
    while(counts<30):
        if(pin1.value()==0):
            break
        counts=counts+1
        clock.tick()#返回以毫秒计的通电后的运行时间。
        img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)#抓取一帧的图像并返回一个image对象
        #img.find_blobs()查找图像中所有色块,并返回包含每个色块的色块对象列表

        flag=0
        blobs=img.find_blobs(thresholds, pixels_threshold=200, area_threshold=300, merge=True)
        if blobs:
            max_blob=find_max(blobs)
            if max_blob:
                if judge==0:
                    for c in img.find_circles(max_blob.rect(),threshold = 5000, x_margin = 5, y_margin = 5,
                     r_margin = 5, r_min = 2, r_max = 200 , r_step = 2):
                        print(c)
                        if c.magnitude()>5000:
                            c_times=c_times+1
                            cx=cx+c.x()
                            cy=cy+c.y()
                            #img.draw_circle(c.x(),c.y(),c.r(),(0,255,0))
                        if c_times>5:
                            judge=1
                            shape=1
                            print("circle")
                            cx=int(cx/c_times)
                            cy=int(cy/c_times)
                            break
                    for r in img.find_rects(max_blob.rect(),threshold = 10):
                        img.draw_rectangle(r.x(),r.y(),r.w(),r.h(),(0,255,0))
                        print(r)
                        if r.magnitude()>50000 and judge==0:
                            r_times=r_times+1
                        if r_times:
                            judge=1
                            shape=0
                            print("rect")
                            break
                if abs(max_blob.w()-max_blob.h())<4:
                    if shape==1:
                        x_avg=cx
                        y_avg=cy
                    else:
                        x_avg=(max_blob.x()+0.5*max_blob.w()+x_avg)+max_blob.cx()
                        y_avg=(max_blob.y()+0.5*max_blob.h()+y_avg)+max_blob.cy()
                        max_size=max_size+2
                    flag=1
                #if(max_blob.cx()-max_blob.x()>w_avg):
                    #w_avg=max_blob.cx()-max_blob.x()
                #if(max_blob.w()-max_blob.cx()+max_blob.x())>x_avg:
                    #x_avg=max_blob.w()-max_blob.cx()+max_blob.x()

                #if(max_blob.cy()-max_blob.y()>w_avg):
                    #w_avg=max_blob.cy()-max_blob.y()
                #if(max_blob.w()-max_blob.cy()+max_blob.y())>x_avg:
                    #x_avg=max_blob.w()-max_blob.cy()+max_blob.y()
                if max_blob.w()>w_avg:
                    w_avg=max_blob.w()
                if max_blob.h()>w_avg:
                    w_avg=max_blob.h()
                #a=math.sqrt((max_blob.cx()-max_blob.x())**2-(max_blob.cy()-max_blob.y())**2)
                #if a>w_avg:
                    #w_avg=a
                img.draw_rectangle(max_blob.rect())#画矩形框 blob.rect() ---> 返回一个矩形元组(可当作roi区域)

                img.draw_cross(max_blob.cx(),max_blob.cy())
        if flag==0:
            counts=counts-1
        else:
            if shape==0:
                img.draw_cross(int(x_avg/max_size),int(y_avg/max_size))#画十字 blob.cx(), blob.cy() --->返回中心点x和y坐标
            else:
                img.draw_cross(x_avg,y_avg)
           #print(clock.fps())#clock.fps() ---> 停止追踪运行时间,并返回当前FPS(必须先调用tick)。
    if shape==0:
        print(int(x_avg/max_size),int(y_avg/max_size),int(w_avg))
        data=[int(x_avg/max_size)+1,int(y_avg/max_size)-2 ,int(w_avg),shape]
    elif shape==1:
        data=[x_avg,y_avg,int(w_avg),shape]

    return data




def detect():
    sensor.reset() #初始化设置
    sensor.set_pixformat(sensor.RGB565) #设置为彩色
    sensor.set_framesize(sensor.QVGA) #设置清晰度
    sensor.skip_frames(time = 2000) #跳过前2000ms的图像
    sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的。
    sensor.set_auto_whitebal(False) #关闭白平衡。在颜色识别中,一定要关闭白平衡。
    clock = time.clock() #创建一个clock便于计算FPS,看看到底卡不卡

    judge=0
    r_time=0
    a_r=0
    a_c=0
    a_rt=0
    c_time=0
    rt_time=0
    row_data=[-1,-1]

    while(judge==0): #不断拍照
        clock.tick()
        img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)

        blobs=img.find_blobs(thresholds,pixels_threshold=10,area_threshold=10)
        #openmv自带的寻找色块函数。
        #pixels_threshold是像素阈值,面积小于这个值的色块就忽略
        #roi是感兴趣区域,只在这个区域内寻找色块
        #are_threshold是面积阈值,如果色块被框起来的面积小于这个值,会被过滤掉
            #print('该形状占空比为',blob.density())
        if blobs:
            max_blob=find_max(blobs)
            if max_blob:


            #print('该形状的面积为',area)
             #density函数居然可以自动返回色块面积/外接矩形面积这个值,太神奇了,官方文档还是要多读!
                if max_blob.density()>0.78:#理论上矩形和他的外接矩形应该是完全重合
            #但是测试时候发现总会有偏差,多次试验取的这个值。下面圆形和三角形亦然

                    r_time=r_time+1
                    #a_r=a_r+area
                    #area=int(max_blob.x()*max_blob.y()*max_blob.density()*0.0185)
                    img.draw_rectangle(max_blob.rect())
                    print('长方形长',max_blob.density())
                    if r_time>1:
                        #area=int(a_r/r_time)
                        #print(area)
                        judge=1
                        row_data[0]=1
                        print("检测为长方形  ",end='')
                elif max_blob.density()>0.46:

                    #area=int(max_blob.x()*max_blob.y()*max_blob.density()*0.0575)
                    c_time=c_time+1
                    #a_c=a_c+area
                    img.draw_circle((max_blob.cx(), max_blob.cy(),int((max_blob.w()+max_blob.h())/4)))
                    print('圆形半径',max_blob.density())
                    if c_time>8:
                        #area=int(a_c/c_time)
                        #print(area)
                        judge=1
                        row_data[0]=2
                        print("检测为圆  ",end='')
                elif max_blob.density()>0.2:
                    #area=int(max_blob.x()*max_blob.y()*max_blob.density()*0.0207)
                    rt_time=rt_time+1
                    #a_rt=a_rt+area
                    img.draw_cross(max_blob.cx(), max_blob.cy())
                    print(max_blob.density(),)
                    if rt_time>20:
                        #area=int(a_rt/rt_time)
                        #if c_time>0:
                            #area=area-10*c_time
                        #print(area)
                        judge=1
                        row_data[0]=3
                        print("检测为三角型  ",end='')
                else: #基本上占空比小于0.4的都是干扰或者三角形,索性全忽略了。
                    continue

                #row_data[1]=area

    area=0
    count=0
    while(1):
        clock.tick()
        img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)
        img.binary(thresholds)
        img.draw_rectangle(80,40,150,120)
        x_init=80
        y_init=40

        for i in range(150):
            for j in range(100):
                if img.get_pixel(i+x_init,j+y_init)[0]==255:
                    count=count+1

        break
        #img.draw_rectangle(80,40,150,120)
        #sta=img.get_statistics(thresholds, invert=False, roi=(80,40,150,120))
        #area=area+(30-sta.mean())*1000
        #counts=counts+1
        #print(sta.mean())
        #if(counts>50):
            #area=int(area/counts*0.0031495)
            #print(area)
            #break
    row_data[1]=int(count*0.02329*1.14946236559)
    #
    \

    print(row_data[1])
    data=bytearray(row_data)
    uart.write(u_start)
    uart.write(data)
    uart.write(u_over)



#-------------------------------------------------------------------------

#threshold=[(90, 100, -101, 87, -94, 84)]
threshold=[(60, 255, -20, 20, -20, 20)]

def color_blob(threshold):

    blobs = img.find_blobs(threshold,x_stride=1, y_stride=1, area_threshold=0, pixels_threshold=0,merge=False,margin=1)

    if len(blobs)>=1 :
        # Draw a rect around the blob.
        b = blobs[0]
        #img.draw_rectangle(b[0:4]) # rect
        cx = b[5]
        cy = b[6]
        for i in range(len(blobs)-1):
            #img.draw_rectangle(b[0:4]) # rect
            cx = blobs[i][5]+cx
            cy = blobs[i][6]+cy
        cx=int(cx/len(blobs))
        cy=int(cy/len(blobs))
        #img.draw_cross(cx, cy) # cx, cy
        print(cx,cy)
        return int(cx), int(cy)
    return -1, -1

import sensor, image, time ,math,utime
from pyb import UART
from pyb import Pin
from pyb import ExtInt
from pyb import LED



uart = UART(3, 115200, timeout_char=1000)  # i使用给定波特率初始化
uart.init(115200, bits=8, parity=None, stop=1, timeout_char=1000)
u_start=bytearray([0xb3,0xb3])
u_over=bytearray([0x0d,0x0a])
thresholds = [(0, 15, -21,10, -18, 6),(0, 22, -28, 19, -4, 13),
(0, 25, -22, 10, -30, 10),(0, 25, -20, 15, -37, 12),(3,22,-4,40,-10,13)]#LAB阈值
pin1 = Pin('P1', Pin.IN, Pin.PULL_UP)
pin2 = Pin('P2',Pin.IN,Pin.PULL_UP)


#extint = ExtInt(pin2, ExtInt.IRQ_FALLING, Pin.PULL_UP, callback_PIN2)
#顺序:(L Min, L Max, A Min, A Max, B Min, B Max)

clock = time.clock()#定义时钟对象clock



while(1):
    while(pin1.value()==0):
        continue
    row_data = [-1,-1,-1,-1,-1,-1]
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA)
    sensor.skip_frames(time = 500)
    sensor.set_auto_gain(False) # 关闭增益(色块识别时必须要关)
    sensor.set_auto_whitebal(False) # 关闭白平衡
    LED(1).on()
    if(pin1.value()==0):
        continue
    if(pin2.value()==0):
        detect()

    row_data[0],row_data[1],row_data[2],row_data[3]=FindCR()
    if(pin1.value()==0):
        continue
    if(pin2.value()==0):
        detect()
    LED(1).off()
    LED(2).on()
    data=bytearray(row_data)
    uart.write(u_start)
    uart.write(data)
    uart.write(u_over)
    print(row_data)
    LED(2).off()
    if(pin1.value()==0):
        continue
    sensor.reset()
    sensor.set_auto_gain(False)
    sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.RGB565
    sensor.set_framesize(sensor.  QVGA) # or sensor.QVGA (or others)
    sensor.skip_frames(time=900) # Let new settings take affect.
    sensor.set_auto_exposure(False, 1000)
    sensor.set_auto_whitebal(False) # turn this off.
    sensor.set_auto_gain(False) # 关闭增益(色块识别时必须要关)
    times=0
    num=[-1,-1,-1]
    add=[-1,-1]
    while(True):
        if(pin1.value()==0):
            break
        if(pin2.value()==0):
            detect()
        #EXPOSURE_TIME_SCALE = 1.01
        #current_exposure_time_in_microseconds = sensor.get_exposure_us()

        # 默认情况下启用自动曝光控制(AEC)。调用以下功能可禁用传感器自动曝光控制。
        # 另外“exposure_us”参数在AEC被禁用后覆盖自动曝光值。
        #sensor.set_auto_exposure(False, \
            #exposure_us = int(current_exposure_time_in_microseconds * EXPOSURE_TIME_SCALE))
        #roi=(int(row_data[0]-0.5*row_data[2]),int(row_data[1]-0.5*row_data[2]),row_data[2],row_data[2])
        clock.tick()
        img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)#抓取一帧的图像并返回一个image对象
        img.draw_circle(data[0],data[1],int(data[2]*0.5))
        img.draw_cross(data[0],data[1])
        img = sensor.snapshot().lens_corr(strength = 1.8, zoom = 1.0)#抓取一帧的图像并返回一个image对象
        row_data[4],row_data[5]=color_blob(threshold)

        if row_data[4]!=-1:
            if times==0:
                num[times]=[row_data[4],row_data[5]]
            else:
                if abs(row_data[4]-num[0][0])>10 or abs(row_data[5]-num[0][1])>10:

                    continue #丢弃数据
            times=times+1
            num[0]=[row_data[4],row_data[5]]
            #img.draw_cross(row_data[4],row_data[5])
            data=bytearray(row_data)
            uart.write(u_start)
            uart.write(data)
            uart.write(u_over)
            print(row_data)

        print(pin2.value())

代码部分解读

图像类型

(1)sensor.set_pixformat设置的图像类型不同。
<1>我拿官方代码和上面贴出来的那个代码进行了对比,发现了一件事情。他的sensor.set_pixformat是设置成GRAYSCALE图像,而我们这里是设置成RGB565图像。
<2>将图像画质设置成GRAYSCALE好处在于,如果只有两个颜色,更容易进行分辨,而且每个像素所占空间也减少了,可以适当的增加分辨率。但是也有缺点,如果是多颜色识别就会出现问题。
<3>本题只有三种颜色,底板白色,追踪的绿点,被追踪的红点。因为只需要追踪一个颜色,所以各位可以尝试将 sensor.set_pixformat(sensor.RGB565) 改成 sensor.set_pixformat(sensor.GRAYSCALE)

在这里插入图片描述

图像分辨率

(2)图像分辨率,sensor.set_framesize(sensor.QQVGA)
<1>官方例程的分辨率是QQVGA,像素点是160x120。而那个博客的分辨率是QVGA,像素点是 320x240。
<2>更高的分辨率,识别效果更好,但是分辨率也别无脑调高,否则颜色阈值方便会很难设置。

在这里插入图片描述

跳过帧数

(3)跳过帧数,sensor.skip_frames(10)
<1>这个就是给OpenMV初始化一个缓冲时间,他那边是设置的跳过900张图片。官方例程是跳过10个图片。
<2>这个选取看你自己,我感觉没必要900,太多了。

在这里插入图片描述

曝光度设置

(4)sensor.set_auto_exposure(False, 1000)
<1>这个是用于设置曝光度的,曝光过度照片看起来会过亮,曝光不足图片看起来会太暗。
<2>官方例程没有调用这个函数,说明曝光是一直打开的。
<3>C站那位是设置的每1ms曝光一次。你们可以根据自己测试结果来设置。

在这里插入图片描述

白平衡和自增益

(5)sensor.set_auto_whitebal(False)和sensor.set_auto_gain(False)
<1>按理来说颜色识别的话,这两个都需要关闭的。C站另外那个博客就是都关闭了。但是官方只关闭了set_auto_whitebal()白平衡。
<2>我个人建议还是先都关闭

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59406.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2020-2023中国高等级自动驾驶产业发展趋势研究

1.1 概念界定 2020-2023中国高等级自动驾驶产业发展趋势研究Trends in China High-level Autonomous Driving from 2020 to 2023自动驾驶发展过程中&#xff0c;中国出现了诸多专注于研发L3级以上自动驾驶的公司&#xff0c;其在业界地位也越来越重要。本报告围绕“高等级自动…

【雕爷学编程】MicroPython动手做(29)——物联网之SIoT 2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Java实现数据库表中的七种连接【Mysql】

Java实现数据库表中的七种连接【Mysql】 前言版权推荐Java实现数据库表中的七种连接左外连接右外连接其他连接 附录七种连接SQL测试Java测试转换方法类 Cla1类 Cla2类Cla3 最后 前言 2023-8-4 16:51:42 以下内容源自《【Mysql】》 仅供学习交流使用 版权 禁止其他平台发布时…

vue 混入(mixin)的使用

在 vue 组件内&#xff0c;如果想将一些公共功能&#xff0c;如组件、方法、钩子函数等复用&#xff0c;混入是一个很好的选择。 现在开始我们的混入使用吧 1、我们可以创建一个目录mixins&#xff0c;在创建一个comment.js文件如图&#xff1a; // 在 common.js 里写你想共享…

SQL 表别名 和 列别名

列表名 列表名之后 order by 可以用别名 也可以用原名&#xff0c; where 中不能用别名的 SQL语句执行顺序&#xff1a; from–>where–>group by -->having — >select --> order 第一步&#xff1a;from语句&#xff0c;选择要操作的表。 第二步&#xff1…

matlab编程实践18、19

浅水方程 浅水方程可以建立起海啸和浴缸中波浪的数学模型。浅水方程建立了水或者其它不可压缩液体受扰动时传播的模型。隐含的假设是&#xff0c;液体的深度和波浪的长度、扰动等相比是很小的。 在这样的记号下&#xff0c;浅水方程为双曲守恒定律的一个例子。 使用拉克斯-冯特…

ssm机动车维修站车辆维护管理系统java汽车报修备案jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 ssm机动车维修站车辆维护管理系统 系统有2权限&#…

iOS16.0:屏幕旋转

此文写于2022年08月03日&#xff0c;距离iOS16正式版推出还有一个多月的时间&#xff0c;iOS16 beta版本有很多API的修改&#xff0c;今天讨论的是屏幕旋转&#xff0c;基于Xcode 14.0 beta4。 之前的屏幕旋转会报错&#xff1a; [Orientation] BUG IN CLIENT OF UIKIT: Settin…

MinIO

MinIO 1.MinIO安装 Minio 是个基于 Golang 编写的开源对象存储服务&#xff0c;存储非结构化数据&#xff0c;如&#xff1a;图片&#xff0c;视频&#xff0c;音乐等 官网地址&#xff1a;https://min.io/ 中文地址&#xff1a;http://minio.org.cn 官网文档&#xff08; …

Istio 安全 mTLS认证 PeerAuthentication

这里定义了访问www.ck8s.com可以使用http也可以使用https访问&#xff0c;两种方式都可以访问。 那么是否可以强制使用mtls方式去访问&#xff1f; mTLS认证 PeerAuthentication PeerAuthentication的主要作用是别人在和网格里的pod进行通信的时候&#xff0c;是否要求mTLS mTL…

SpringBoot中事务失效的原因

SpringBoot中事务失效的原因 文章目录 SpringBoot中事务失效的原因一、事务方法非public修饰二、非事务方法调用事务方法三、事务方法的异常被捕获四、事务异常类型不对五、事务传播行为不对六、没有被Spring管理6.1、暴漏代理对象6.2、使用代理对象 常见的事务失效原因包括如下…

LeetCode-26-删除有序数组中的重复项

一&#xff1a;题目描述&#xff1a; 给你一个 升序排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯…

【Linux】-进程概念之进程优先级(如何去进行调度以及进程切换),还不进来看看??

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

adb 调试oppo k11过程记录

学习使用appium工具&#xff0c;自动化测试andriod应用程序。 过程记录 背景交代 手机&#xff1a;oppo k11 系统&#xff1a; macOS 手机开启use调试 具体细节&#xff0c;可百度 安装软件 adbappiumappium-inspector adb安装 下载adb工具包platform-tools, 解压。 直…

【网络基础进阶之路】基于MGRE多点协议的实战详解

PS&#xff1a;本要求基于华为的eNSP模拟软件进行 具体要求&#xff1a; 完成步骤&#xff1a; 1、根据上述要求&#xff0c;对各路由器进行地址安排&#xff0c;如下图。 2、进入各路由器&#xff0c;对每个端口进行地址设置。 R1路由器设置&#xff1a; ISP路由器设置&…

CNN-NER论文详解

论文&#xff1a;https://arxiv.org/abs/2208.04534 代码&#xff1a;https://github.com/yhcc/CNN_Nested_NER/tree/master 文章目录 有关工作前期介绍CNN-NER模型介绍 代码讲解主类多头biaffineCNNLoss解码数据传入格式 参考资料 有关工作 前期介绍 过去一共主要有四类方式…

数据结构初阶--二叉树的顺序结构之堆

目录 一.堆的概念及结构 1.1.堆的概念 1.2.堆的存储结构 二.堆的功能实现 2.1.堆的定义 2.2.堆的初始化 2.3.堆的销毁 2.4.堆的打印 2.5.堆的插入 向上调整算法 堆的插入 2.6.堆的删除 向下调整算法 堆的删除 2.7.堆的取堆顶元素 2.8.堆的判空 2.9.堆的求堆的…

MyBatis-Plus实现分页查询

目录 MyBatis-Plus实现分页查询 代码 定义一个MyBatis-Plus拦截器 在连接数据库的配置文件中添加MyBatis-Plus日志查看MyBatis-Plus的SQL语句 测试 运行结果 MyBatis-Plus实现分页查询 代码 定义一个MyBatis-Plus拦截器 package com.dong.config;import com.baomidou.my…

webpack基础知识二:说说webpack的构建流程?

一、运行流程 webpack 的运行流程是一个串行的过程&#xff0c;它的工作流程就是将各个插件串联起来 在运行过程中会广播事件&#xff0c;插件只需要监听它所关心的事件&#xff0c;就能加入到这条webpack机制中&#xff0c;去改变webpack的运作&#xff0c;使得整个系统扩展…

【学习笔记】Java安全之反序列化

文章目录 反序列化方法的对比PHP的反序列化Java的反序列化Python反序列化 URLDNS链利用链分析触发DNS请求 CommonCollections1利用链利用TransformedMap构造POC利用LazyMap构造POCCommonsCollections6 利用链 最近在学习Phith0n师傅的知识星球的Java安全漫谈系列&#xff0c;随…