2022年十月份电赛OpenMV巡线方案详细代码分析(1)

news2024/12/27 12:55:37

前言

(1)马上要进行电赛了,机器识别是铁定会使用到的。为了防止出现去年十月份那种特殊的巡线方案。我在此分享出OpenMV巡线方案,并且进行讲解和分析如何更改。
(2)学习本文之前,需要学习:OpenMV串口通讯详解;OpenMV图像处理之后给单片机通讯;OpenMV的单颜色识别讲解;
(3)版权申明:此代码借鉴了淘宝商家—无名创新的代码,已获得许可。未经允许,禁止商用!
(4)注意:他的代码自己创建了一个比较复杂的通讯协议,为了方便新手快速入门,我在他的代码上进行了微调。
(5)先给一颗定心丸,本文学习最多20分钟就能掌握。(前提,OpenMV的颜色识别感兴趣区串口通讯能够熟练使用)
(6)主控代码将会在下一篇中给出,因为C站编辑器字数超过1W字就卡的一批,没办法,只能分成两篇来写。

OpenMV全部代码

(1)先直接上代码,因为可能很多人都是开赛了才看到这一篇博客的,没多少时间了。
(2)OpenMV的函数入口是main.py,从第一行往下执行。所以这个文件要命名为main.py!!!

#main.py -- put your code here!
import cpufreq
import pyb
import sensor,image, time,math
from pyb import LED,Timer,UART

sensor.reset()                      # 重置感光元件,重置摄像机
sensor.set_pixformat(sensor.RGB565) # 设置颜色格式为RGB565,彩色,每个像素16bit。
sensor.set_framesize(sensor.QQQVGA)  # 图像大小为QQQVGA,大小80x60
sensor.skip_frames(time = 2000)     #延时跳过一些帧,等待感光元件变稳定
sensor.set_auto_gain(False)          #黑线不易识别时,将此处写False
sensor.set_auto_whitebal(False)     #颜色识别必须关闭白平衡,会影响颜色识别效果,导致颜色的阈值发生改变
clock = time.clock()                # 创建一个时钟对象来跟踪FPS。
#sensor.set_auto_exposure(True, exposure_us=5000) # 设置自动曝光sensor.get_exposure_us()

red_led = pyb.LED(1)    #下面这三个就是OpenMV上的LED初始化
green_led = pyb.LED(2)
blue_led = pyb.LED(3)
uart=UART(3,115200)   #初始化串口3,波特率为115200,P4为TX连接单片机RX,P5为RX连接单片机TX

class target_check(object):
    x=0          #int16_t,横线上被标记黑点的地方,从左到右依次减少
    y=0          #int8_t,竖线上被标记黑点的地方,从上到下依次减少

target=target_check()


# 绘制水平线
def draw_hori_line(img, x0, x1, y, color):
    for x in range(x0, x1):
        img.set_pixel(x, y, color)
# 绘制竖直线
def draw_vec_line(img, x, y0, y1, color):
    for y in range(y0, y1):
        img.set_pixel(x, y, color)
# 绘制矩形
def draw_rect(img, x, y, w, h, color):
    draw_hori_line(img, x, x+w, y, color)
    draw_hori_line(img, x, x+w, y+h, color)
    draw_vec_line(img, x, y, y+h, color)
    draw_vec_line(img, x+w, y, y+h, color)


#图像大小为QQQVGA,大小80x60
#roi的格式是(x, y, w, h)
track_roi=[(0,25,5,10),
           (5,25,5,10),
           (10,25,5,10),
           (15,25,5,10),
           (20,25,5,10),
           (25,25,5,10),
           (30,25,5,10),
           (35,25,5,10),
           (40,25,5,10),
           (45,25,5,10),
           (50,25,5,10),
           (55,25,5,10),
           (60,25,5,10),
           (65,25,5,10),
           (70,25,5,10),
           (75,25,5,10)]

target_roi=[(70,0,10,12),
           (70,12,10,12),
           (70,24,10,12),
           (70,36,10,12),
           (70,48,10,12)]


thresholds =(0, 30, -30, 30, -30, 30)  #黑色的颜色阈值

hor_bits=['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'] #记录横线16个感兴趣区是否为黑线
ver_bits=['0','0','0','0','0',]  #记录右边5个感兴趣区是否为黑线
#__________________________________________________________________
def findtrack():
    target.x=0
    target.y=0
    img=sensor.snapshot()

    #用于检测黑线
    for i in range(0,16):
        hor_bits[i]=0
        '''
        thresholds表示黑色线阈值,roi为感兴趣区
        merge=True,表示所有合并所有重叠的blob为一个
        margin 边界,如果设置为10,那么两个blobs如果间距10一个像素点,也会被合并。
        '''
        blobs=img.find_blobs([thresholds],roi=track_roi[i],merge=True,margin=10)
        #如果识别到了黑线,hor_bits对应位置1
        for b in blobs:
            hor_bits[i]=1

    #用于检测右侧的黑线
    for i in range(0,5):
        ver_bits[i]=0
        blobs=img.find_blobs([thresholds],roi=target_roi[i],merge=True,margin=10)
        for b in blobs:
            ver_bits[i]=1

    #绘制16个横线红色四个角
    for k in range(0,16):
        if  hor_bits[k]:
            target.x=target.x|(0x01<<(15-k))
            img.draw_circle(int(track_roi[k][0]+track_roi[k][2]*0.5),int(track_roi[k][1]+track_roi[k][3]*0.5),1,(255,0,0))
    #绘制右侧5个红色四个角
    for k in range(0,5):
        if  ver_bits[k]:
            target.y=target.y|(0x01<<(4-k))
            img.draw_circle(int(target_roi[k][0]+target_roi[k][2]*0.5),int(target_roi[k][1]+target_roi[k][3]*0.5),3,(0,255,0))
    #绘制16个横线感兴趣区
    for rec in track_roi:
        img.draw_rectangle(rec, color=(0,0,255))#绘制出roi区域
    #绘制右侧5个横线感兴趣区
    for rec in target_roi:
        img.draw_rectangle(rec, color=(0,255,255))#绘制出roi区域
           #大--小  从左到右                       从上到下
    print((target.x & 0xff00)>>8,target.x & 0xff,target.y)
    uart.write(str((target.x & 0xff00)>>8))
    #uart.write(str(target.x & 0xff))
    #uart.write(str(target.y))
    #uart.write("\r\n")

#__________________________________________________________________
def package_blobs_data():
    return bytearray([target.x >> 8,
                      target.x,
                      target.y])
#__________________________________________________________________
i = 0
while True:
    findtrack()
    uart.write(package_blobs_data())
    uart.write("\r\n")
    i = i + 1
    if i == 50:
        i = 0
        green_led.toggle()
    pyb.delay(10)
    #uart.write("Hello World!\r")
    #uart.write(1+'\n')
    #计算fps
    #print(clock.fps())
#__________________________________________________________________

代码分析

关注点1—图像大小设置

(1)下面这一部分代码,我只会讲解你需要进行更改的部分。
(2)sensor.set_framesize(sensor.QQQVGA)
<1>这个是用于设置图像大小的。首先我们需要知道,对于计算机而言,一个张图片到底是什么东西。
<2>大家都打电赛了,肯定是玩过常见的OLED,或者是点阵屏的。那么我们让OLED或者点阵屏画图是怎么做的呢?很简单,一个像素点一个像素点的画。
<3>比如常见的4脚0.96寸的OLED是128*64像素。这是什么意思呢?他说明了,这款OLED纵向有128个小型的LED,横向有64个小型LED。我们想要绘制一个图像,就是一个一个的点亮这些小型LED。
<3>OpenMV同样也是,不过他的像素大小是可以进行设置的。比如我这里是采用的QQQVGA画质,像素就是80x60,也就是说X轴80个像素点,Y轴60个像素点。
<4>这个有什么用呢?很简单,与后面的感兴趣区设置有关
<5>OpenMV画质设置相关资料:https://book.openmv.cc/image/sensor.html

在这里插入图片描述

<6>感兴趣区相关资料:https://book.openmv.cc/image/statistics.html
<7>可能有些人学颜色识别的时候没有注意看感兴趣区的相关资料。我在此进行简单的说明一下。
<8>我们上面说了,OpenMV可以对图像大小进行设置,如下图,我们将图像大小设置为16*16的像素点大小。
<9>我拍摄到了整个图像,是一朵花。但是如果我们进行特征识别,只想识别这朵花的中心部分(途中蓝色线标记的地方),那么在颜色识别的时候,传入感兴趣值roi=(5,2,6,4)。

在这里插入图片描述


import cpufreq
import pyb
import sensor,image, time,math
from pyb import LED,Timer,UART

sensor.reset()                      # 重置感光元件,重置摄像机
sensor.set_pixformat(sensor.RGB565) # 设置颜色格式为RGB565,彩色,每个像素16bit。
sensor.set_framesize(sensor.QQQVGA)  # 图像大小为QQQVGA,大小80x60
sensor.skip_frames(time = 2000)     #延时跳过一些帧,等待感光元件变稳定
sensor.set_auto_gain(False)          #黑线不易识别时,将此处写False
sensor.set_auto_whitebal(False)     #颜色识别必须关闭白平衡,会影响颜色识别效果,导致颜色的阈值发生改变
clock = time.clock()                # 创建一个时钟对象来跟踪FPS。
#sensor.set_auto_exposure(True, exposure_us=5000) # 设置自动曝光sensor.get_exposure_us()

关注点2—串口波特率设置

(1)首先先说明,pyb.LED这个是什么。
<1>这个其实就是OpenMV上的那唯一一个RGB灯的初始化函数。
<2>为什么我需要初始化RGB呢?因为,为了防止OpenMV突然因为什么原因停止运行,最终没有给主控反馈数据,在排错过程中,无法定位问题。所以我设置了一个RGB闪烁的程序。如果OpenMV正常运转,那么RGB就会闪烁。这样出现问题,也方便定位问题。
(2)UART函数就是串口初始化函数
<1>注意,OpenMV只有一个串口3!请不要自作聪明改第一个参数!
<2>第二个参数是设置波特率的,这个波特率的值需要和主控的波特率值设置一致。
<3>连接方法是:OpenMV的TX(P4)——单片机RX,RX(P5)——单片机TX,GND——GND,3.3V——3.3V

red_led = pyb.LED(1)    #下面这三个就是OpenMV上的LED初始化
green_led = pyb.LED(2)
blue_led = pyb.LED(3)
uart=UART(3,115200)   #初始化串口3,波特率为115200,P4为TX连接单片机RX,P5为RX连接单片机TX

关注点3—巡线数据存储

(1)首先,我们需要知道22年10月份的电赛地图长什么样子。他就是一个倒车入库的题目。
(2)这个题目,明显不能使用光感循迹,否则就会超出车子大小而且不符合题意。
(3)所以我们的OpenMV要斜着放。

在这里插入图片描述

(4)如下为OpenMV实际检测到的结果。我们会看到,只要右边那一条Y轴线检测到了黑色,就说明可以开始准备倒车入库了。
(5)当中心位置的X轴线,右边5个识别区域有数据识别,说明已经车子要倒车入库了。

在这里插入图片描述

(6)因此,我们这里创建了一个类,如果没有python基础的,可以理解为C语言的一个结构体。这个结构体存放x和y轴的数据。
(7)如果需要进行微调,你就看看你的感兴趣区怎么设置

class target_check(object):
    x=0          #int16_t,横线上被标记黑点的地方,从左到右依次减少
    y=0          #int8_t,竖线上被标记黑点的地方,从上到下依次减少

target=target_check()

无需关注的代码,做一个简单讲解

(1)我们能够看到上面的OpenMV识别代码里面,画有一些框框。这个其实只会出现在OpenMV IDE里面,方便我们进行调试。

# 绘制水平线
def draw_hori_line(img, x0, x1, y, color):
    for x in range(x0, x1):
        img.set_pixel(x, y, color)
# 绘制竖直线
def draw_vec_line(img, x, y0, y1, color):
    for y in range(y0, y1):
        img.set_pixel(x, y, color)
# 绘制矩形
def draw_rect(img, x, y, w, h, color):
    draw_hori_line(img, x, x+w, y, color)
    draw_hori_line(img, x, x+w, y+h, color)
    draw_vec_line(img, x, y, y+h, color)
    draw_vec_line(img, x+w, y, y+h, color)

关注点4—感兴趣区设置

(1)我们上面设置了OpenMV的图像大小为QQQVGA,这里像素点大小就是80x60。
(2)然后我们需要设置只识别规定部分,来进行循迹。
(3)先讲解中间的16个识别点,track_roi。
<1>我们X轴要建立16个识别点,而x轴一共有80个像素点,所以w都是5,而x每次以5进行递增
<2>因为我的整个图像y轴有60个像素点。h如果选取太小,主控的反应时间太短了,太大的话,又影响y轴的那8个数据识别,所以我们选取h固定为10。因为y轴60个像素点,所以中心位置像素点是30,因为h选取为10,所以y的起始位置是30-(10/2)=25
(4)现在讲解右侧的5个识别点,target_roi。
<1>理解了上面的讲解之后这里就很好理解了。首先为了防止x轴的宽度w设置太小,不利于识别,太大影响中心16个识别点,所以宽度w都设置为10,而x轴的像素点只有80个,所以x设置为80-10=70
<2>因为右边是5个识别点,然后y轴有60个像素点,所以h设置为60/6=12个,y轴每次递增12

#图像大小为QQQVGA,大小80x60
#roi的格式是(x, y, w, h)
track_roi=[(0,25,5,10),
           (5,25,5,10),
           (10,25,5,10),
           (15,25,5,10),
           (20,25,5,10),
           (25,25,5,10),
           (30,25,5,10),
           (35,25,5,10),
           (40,25,5,10),
           (45,25,5,10),
           (50,25,5,10),
           (55,25,5,10),
           (60,25,5,10),
           (65,25,5,10),
           (70,25,5,10),
           (75,25,5,10)]

target_roi=[(70,0,10,12),
           (70,12,10,12),
           (70,24,10,12),
           (70,36,10,12),
           (70,48,10,12)]

关注点5—黑线颜色阈值

(1)你们只需要按照下面的颜色阈值设置工具,将最终产生的数据传入给thresholds 即可。
(2)颜色阈值设置工具教程:OpenMV颜色阈值设置。

thresholds =(0, 30, -30, 30, -30, 30)  #黑色的颜色阈值

关注点6—感兴趣区数组

(1)你有几种感兴趣区,就建立几个数组。
(2)每种感兴趣区有几个区域,就写几个’0’。

hor_bits=['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'] #记录横线16个感兴趣区是否为黑线
ver_bits=['0','0','0','0','0',]  #记录右边5个感兴趣区是否为黑线

关注点7—循迹部分

(1)这里只会讲解可能需要进行微调的部分
2)arget.x 和 target.y
<1>arget.x和target.y是用于记录x轴16个感兴趣区和y轴右侧的那5个感兴趣区的数据。每次调用这个函数需要进行清零操作,否则数据会受到上一次结果干扰。
<2>这里需要根据你之前设置的关注点3部分的数据信息有关,你设置了几个量,就需要清零几个。
3)for i in range(0,16): 和 for i in range(0,5):
<1>range(0,16)这个就是将就是将0到15这16个数据传递给i。这里的两个for语句内容其实是一样的。你有几中类型数据,就写几个for,然后只需要更改一下range(0,x)中的x。
<2>hor_bits[i]=0首先我们需要将这些数组的数据清空,防止上一次数据造成干扰。不用改。
<3>find_blobs()这个函数,只需要更改roi感兴趣区,将roi设置为你要的感兴趣区即可。
4)for k in range(0,16): 和for k in range(0,5):
<1>这两个for语句作用就是如果识别到了黑线,将数组中的数据存入target.x和target.y。(0x01<<(4-k)和(0x01<<(15-k)部分,这个(0x01<<(x-k)中的x是根据你这个类型感兴趣区有几个决定,比如x轴的有16个,那么x就是15。y轴的有5个,那么x就是4。
<2>draw_circle()函数就是识别到黑线之后OpenMV IDE上就会出现提示,我们如果需要更改,就把传入的四个target_roi[]设置为自己的,如下:
在这里插入图片描述
5)for rec in track_roi: 和 for rec in target_roi:
<1>这个就是画出我们会进行颜色识别的区域,我们如果想要改,只需要将 for语句后面的in 条件改成自己设置的感兴趣区

def findtrack():
    target.x=0
    target.y=0
    img=sensor.snapshot() #这个必须存在,是用于获取图像数据的

    #用于检测黑线
    for i in range(0,16):
        hor_bits[i]=0
        '''
        thresholds表示黑色线阈值,roi为感兴趣区
        merge=True,表示所有合并所有重叠的blob为一个
        margin 边界,如果设置为10,那么两个blobs如果间距10一个像素点,也会被合并。
        '''
        blobs=img.find_blobs([thresholds],roi=track_roi[i],merge=True,margin=10)
        #如果识别到了黑线,hor_bits对应位置1
        for b in blobs:
            hor_bits[i]=1

    #用于检测右侧的黑线
    for i in range(0,5):
        ver_bits[i]=0
        blobs=img.find_blobs([thresholds],roi=target_roi[i],merge=True,margin=10)
        for b in blobs:
            ver_bits[i]=1

    #绘制16个横线红色四个角
    for k in range(0,16):
        if  hor_bits[k]:
            target.x=target.x|(0x01<<(15-k))
            img.draw_circle(int(track_roi[k][0]+track_roi[k][2]*0.5),int(track_roi[k][1]+track_roi[k][3]*0.5),1,(255,0,0))
    #绘制右侧5个红色四个角
    for k in range(0,5):
        if  ver_bits[k]:
            target.y=target.y|(0x01<<(4-k))
            img.draw_circle(int(target_roi[k][0]+target_roi[k][2]*0.5),int(target_roi[k][1]+target_roi[k][3]*0.5),3,(0,255,0))
    #绘制16个横线感兴趣区
    for rec in track_roi:
        img.draw_rectangle(rec, color=(0,0,255))#绘制出roi区域
    #绘制右侧5个横线感兴趣区
    for rec in target_roi:
        img.draw_rectangle(rec, color=(0,255,255))#绘制出roi区域
           #大--小  从左到右                       从上到下
    print((target.x & 0xff00)>>8,target.x & 0xff,target.y)
    uart.write(str((target.x & 0xff00)>>8))

关注点8—OpenMV给串口发送数据

(1)这个函数就是将OpenMV识别到的黑线信息传递给主控。每次发送8bit的数据。
(2)如果需要更改,只需要根据你的需求,更改bytearray函数中的[]。
(3)这里注意一下,数据发送的内容到底是什么,target.x的数据从大到小,是从左到右。target.y的数据从大到小是从上往下的位置。
(4)可能有些人会问为什么,原因很简单,这个和你设置感兴趣区的时候,放置顺序有关。
在这里插入图片描述

def package_blobs_data():
    return bytearray([target.x >> 8,
                      target.x,
                      target.y])

无需关注,有一个简单了解

(1)最后就是一个死循环了。我设置了OpenMV上的RGB灯每隔500ms翻转一次。用于查看OpenMV是否在正常运行。
(2)uart.write()就是将循迹数据传递给主控,因为我采用了正点原子的通讯协议,所以数据帧以"\r\n"结尾。主控代码也要同理采用这个方案。

i = 0
while True:
    findtrack()
    uart.write(package_blobs_data())
    uart.write("\r\n")
    i = i + 1
    if i == 50:
        i = 0
        green_led.toggle()
    pyb.delay(10)   #延时10ms

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过nexus3部署公司内部的私有npm仓库

简介&#xff1a; 登录时使用默认用户admin&#xff0c;密码不知道就需要找默认的&#xff0c;点击Sign in时会提示你路径&#xff0c;这里我是这样查的&#xff0c;在linux服务器上输入以下命令 ​编辑 前言&#xff1a; 准备工作&#xff0c;可能需要一台linux服务器&#x…

Jenkins报警机制的配置与Linux的使用总结

先在钉钉中添加一个机器人 在Configure System中找到机器人选项&#xff0c;并且复制webhook到网络钩子&#xff0c;然后添加机器人的编号、名称和关键词&#xff0c;然后点击测试&#xff0c;如果显示测试成功则表示配置成功&#xff0c;最后保存 再到配置中勾选顶顶机器人的定…

19.matlab数据分析插值(matlab程序)

1.简述 数据插值的计算机制 数据插值是一种函数逼近的方法。 一维插值 Y1interp1(X,Y,X1,method) 二维插值 interp2():二维插值函数。 调用格式: Z1interp2(X,Y,Z,X1,Y1,method) 其中&#xff0c;X、Y是两个向量&#xff0c;表示两个参数的采样点, Z是采样点对应的函数值。X1…

flutter开发实战-Stagger Animation实现水波纹动画

flutter开发实战-实现水波纹动画&#xff0c;使用到了交织动画&#xff0c;实现三个圆逐渐放大与渐变的过程。 一、效果图 二、实现水波纹效果 实现水波纹动画&#xff0c;使用到了交织动画&#xff0c;实现三个圆逐渐放大与渐变的过程。 交织动画 有些时候我们可能会需要一些…

一种具有改进的反向导通、击穿和开关特性的新型4H-SiC沟道MOSFET

标题&#xff1a;A New 4H-SiC Trench MOSFET With Improved Reverse Conduction, Breakdown, and Switching Characteristics 阅读日期&#xff1a;2023.07.23 研究了什么 该文提出并通过TCAD模拟研究了一种带有集成MOS通道二极管&#xff08;MCD&#xff09;的SiC MOSFET&a…

性能测试Ⅵ(总结)

locust&#xff1a;是基于Python语言的性能测试工具&#xff0c;它是基于协程的思想来进行设计的。Python语言是没有办法利用多核的优势&#xff0c;所以了Python为了解决这个问题&#xff0c;设计了协程&#xff0c;作为协程的任务&#xff0c;遇到IO堵塞就立刻切换。 生命是协…

FFmpeg5.0源码阅读—— avcodec_send_frame avcodec_receive_packet

摘要&#xff1a;本文主要描述了FFmpeg中用于编码的接口的具体调用流程&#xff0c;详细描述了该接口被调用时所作的具体工作。   关键字&#xff1a;ffmpeg、avcodec_send_frame、avcodec_receive_packet   读者须知&#xff1a;读者需要了解FFmpeg的基本使用流程&#xf…

AQS概述

基本介绍 队列同步器AbstractQueuedSynchronizer&#xff08;以下简称同步器&#xff09;&#xff0c;是用来构建锁或者其他同步组件的基础框架。 使用了一个int成员变量&#xff08;volatile int state&#xff09;表示同步状态&#xff0c;通过内置的FIFO队列来完成资源获取…

【NLP】如何使用Hugging-Face-Pipelines?

一、说明 随着最近开发的库&#xff0c;执行深度学习分析变得更加容易。其中一个库是拥抱脸。Hugging Face 是一个平台&#xff0c;可为 NLP 任务&#xff08;如文本分类、情感分析等&#xff09;提供预先训练的语言模型。 本博客将引导您了解如何使用拥抱面部管道执行 NLP 任务…

不写代码开启Restful服务

1 前言 很久没有写文章了&#xff0c;不管什么原因&#xff0c;总觉得心里还是觉得有点焦虑&#xff0c;不看看书写点东西就有莫名的焦虑&#xff0c;仿佛只有忙起来才能忘记焦虑。虽然我也知道更重要的是思考方向&#xff0c;但是就像走路&#xff0c;不出发随着时间的流逝&am…

MacBook外接键盘修改键位

众所周知&#xff0c;MacBook的键盘和Windows差别很大&#xff0c;比如我们最常用的ctrlcv在Mac下是commandcv…而外接键盘往往是Windows布局&#xff0c;因此如何修改外接键盘键位就是一件很重要的事情&#xff01; 首先&#xff0c;我们要知道Win键在Mac系统中是多余的&…

微服务一 实用篇 - 5.分布式搜索引擎(ElasticSearch基础)

《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《微服务一 实用篇 - 5.分布式搜索引擎&#xff08;ElasticSearch基础&#xff09;》 《微服务一 实用篇 - 5.分布式搜索…

mysql悲观锁与乐观锁、死锁

mysql悲观锁与乐观锁、死锁 乐观锁的缺点 这个策略源于 mysql 的 mvcc 机制&#xff0c;使用这个策略其实本身没有什么问题&#xff0c;主要的问题就是**对数据表侵入较大&#xff0c;我们要为每个表设计一个版本号字段&#xff0c;然后写一条判断 sql 每次进行判断&#xff…

k8s Service网络详解(一)

有关K8s网络的几个概念 Service&#xff1a;服务 Endpoint&#xff1a;端点 Ingress&#xff1a;和Service类似&#xff0c;基于OSI&#xff08;Open System Interconnection&#xff09;网络模型的七层协议数据&#xff08;如HTTP&#xff09;的转发 Kube Proxy&#xff1…

155、基于STM32单片机老人防跌倒摔倒GSM短信报警系统ADXL345加速度设计(程序+原理图+PCB源文件+参考论文+硬件设计资料+元器件清单等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件方案 二、设计功能 三、实物图 四、原理图 五、PCB图 六、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 单片机主芯片选…

【C语言初阶】指针的运算or数组与指针的关系你了解吗?

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《快速入门C语言》《C语言初阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言&#x1f4ac; 指针运算&#x1f4ad; 指针-整数&#x1f4ad; 指针-指针&#x1f4ad; 指针…

类和对象(中)--运算符重载

目录 1.运算符重载①运算符重载的概念②日期类和运算符重载 2.赋值运算符重载3. 流插入运算符<<重载4.Date类实现5.const成员6.取地址及const取地址操作符重载 1.运算符重载 大家有没有想过内置类型可以使用的运算符是否自定义类型的成员变量也可以使用呢&#xff1f; …

pyqt5-多行文本区QTextEdit实现鼠标滚轮调整文本大小

核心 在 PyQt5 中&#xff0c;你可以通过处理鼠标滚轮事件来设置 QTextEdit 的字体大小。具体做法是在 QTextEdit 上重新实现 wheelEvent 方法&#xff0c;并根据滚轮方向调整字体大小。 代码 import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5…

MATLAB 最小二乘法拟合直线点云 方法一 (26)

MATLAB 最小二乘法拟合直线点云 方法一 (26) 一、算法简介二、算法实现1.代码(详细注释)2.结果展示2.1 拟合效果可视化2.2 对比拟合系数与实际值一、算法简介 提供一组点云(x1 y1 )(x2 y2 )(x3 y3 )…等等多个点… 算法自动拟合直线方程 二维点云的直线方程为:y=kx+…

Mac 预览(Preview)丢失PDF标注恢复

感谢https://blog.csdn.net/yaoyao_chen/article/details/127462497的推荐&#xff01; 辛苦用预览在pdf上做的阅读标记&#xff0c;关闭后打开全丢失了&#xff0c;推荐尝试下网站导入文件进行恢复&#xff1a; 直接使用该网页应用PDF Annotation Recovery 或者访问该项目&a…