YOLOv5实战记录05 Pyside6可视化界面

news2024/11/19 22:54:21

个人打卡,慎看。

指路大佬:【手把手带你实战YOLOv5-入门篇】YOLOv5 Pyside6可视化界面_哔哩哔哩_bilibili

零、虚拟环境迁移路径后pip报错解决

yolov5-master文件夹我换位置后,无法pip install了。解决如下:

  • activate.bat中修改:@set "VIRTUAL_ENV=D:\yolov5-master\venv"
  • activate中修改:VIRTUAL_ENV='D:\yolov5-master\venv'
  • 更新pip:python -m pip install --upgrade pip

参考:Python 虚拟环境迁移路径后pip报错解决记录_pybot移动路径后-CSDN博客

 

【建议挂v,速度会快】

一、环境安装

  • 下载Pyside6:  pip install pyside6

我的pyside6不在Python.exe的上级文件夹的子目录下,packages和python.exe的位置也不同,发现解释器的位置设置错了,之前一直提示我Invalid,我也没有注意。

一般python.exe和site-packages的位置关系是,python.exe和它的上级在同一文件夹下。

比如anaconda下python.exe, lib

lib下site-packages ,也可以输入以下命令,查找site-packages的位置。

import site
print(site.getsitepackages())

以后安装了包,但是无法import,也可以查找site-packages的位置,很有可能这里面没有那个包。是python.exe选取的错误,修改为对应的python.exe即可。

  • 找到pyside6/designer.exe,将快捷方式发送到桌面。
  • up主用vscode安装了qt for python插件,但是我使用的是Pycharm,vscode不熟练,在pycharm中,设置setting->tools->external tools,点击+ ,添加,在Program中,输入designer.exe的位置。name和group随便设置,点击ok。

二、设计UI

  1. 新建mainwindow
  2. 把两个textlabel拖到mainwindow中【存放图片】,用vertical line隔离他们。拖两个pushbutton【按钮】。
  3. 勾选scaledcontents可以实现label中存放内容缩放。将alignment设置水平中心对齐。
  4. 修改对象的名字,便于记忆。比如label1改成input
  5. 保存到yolov5-master文件夹下,修改名字为main_window

三、将ui转换成py

添加external tool

我的血泪教训,改这个错改了40min:

  1. program不要选site-packages\Pyside6\uic.exe 这样转换出来的结果可能是C++代码。
  2. 选\Scripts\pyside6-uic.exe这个文件

  • Program: D:\anaconda\Scripts\pyside6-uic.exe 【输入自己的pyside6-uic.exe文件路径】
  • Arguments: $FileName$ -o $FileNameWithoutExtension$.py
  • working directory: $FileDir$

四、调用mainwindow

import sys

from PySide6.QtWidgets import QMainWindow, QApplication

from main_window import Ui_MainWindow
#这里的main_window是你的ui转换成的py名字
#Ui_MainWindow是main_window里的class名字

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()   #self后不要加(),我加了()报错无法调用mainwindow
        self.setupUi(self)

if __name__=="__main__":
    app=QApplication(sys.argv)

    window1 = MainWindow()
    window1.show()

    app.exec()

运行上面的指令即可弹出UI设计界面。

五、关联按钮和代码

bing_slots()函数负责绑定。det_image和pushButton_2【忘改了】是那两个按钮的名字。

import sys

from PySide6.QtWidgets import QMainWindow, QApplication,QFileDialog
#QFileDialog可以访问文件资源管理器


from main_window import Ui_MainWindow

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)
        self.bind_slots()  #不要忘记调用,不写这句话无法显示。

    def open_image(self):
        print("点击显示图片!")


    def open_video(self):
        print("点击显示视频!")

    def bind_slots(self):
        #绑定
        self.det_image.clicked.connect(self.open_image)
        self.pushButton_2.clicked.connect(self.open_video)


if __name__=="__main__":
    app=QApplication(sys.argv)

    window1 = MainWindow()
    window1.show()

    app.exec()

六、获取图片

  • 一开始无法显示,我设置QPixmap("./datasets/images/train/30.jpg")发现可以显示,于是判断是filepath格式的问题;
  • QPixmap的参数是string类型的。打印file_path[0]发现打印出来的仍然是list格式。
  • 于是转换list为string类型。filePath=','.join(file_path[0])
#与上个代码省略了相同的部分,方便理解。

from PySide6.QtGui import QPixmap
#显示图片

    def open_image(self):
        file_path=QFileDialog.getOpenFileNames(self,dir="./datasets/images/train",filter="*.jpg;*.png")
        #设置从dir里找图片, filter分号隔离不同格式
        #file_path返回的是有两个元素的数组,我们运行后,发现第一个元素是路径,第二个元素是格式。我们只输出路径。
        if file_path[0]:
            filePath=','.join(file_path[0])
            print(file_path[0])
            print(filePath)
            self.input.setPixmap(QPixmap(filePath))  #图片显示

七、训练图片

  • 首先,遇到了问题,我运行页面卡住了,一直在下载某个包,经查找,发现是下面这行代码的问题。我运行提示卡在了“'Downloading torch-2.2.2-cp310-cp310-win_amd64.whl (198.6 MB)”,
  • model = torch.hub.load("./","custom",path="runs/train/exp2/weights/best.pt",trust_repo=True, source="local") 运行这行代码时卡住了,其他代码不会卡。
  • 已解决:下载几个包即可:pip install torch torchvision torchaudio
  • 参考:通过pip安装pytorch超时问题解决 - 知乎 (zhihu.com)

运行代码:

import sys
import torch
from PySide6.QtWidgets import QMainWindow, QApplication,QFileDialog
#QFileDialog可以访问文件资源管理器

from PySide6.QtGui import QPixmap,QImage
#显示图片

from main_window import Ui_MainWindow

def convert2QImage(img):
    height,width,channel=img.shape
    return QImage(img,width,height,width*channel,QImage.Format_RGB888)

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)
        self.model=torch.hub.load("./","custom",path="runs/train/exp2/weights/best.pt",source="local")
        self.bind_slots()  #不要忘记调用,不写这句话无法显示

    def image_pred(self,filePath):
        results=self.model(filePath)
        image=results.render()[0]
        return convert2QImage(image)
        #检测后的图片

    def open_image(self):
        file_path=QFileDialog.getOpenFileNames(self,dir="./datasets/images/train",filter="*.jpg;*.png")
        #设置从dir里找图片, filter分号隔离不同格式
        #file_path返回的是有两个元素的数组,我们运行后,发现第一个元素是路径,第二个元素是格式。我们只输出路径。
        if file_path[0]:
            filePath=','.join(file_path[0])
            qimage=self.image_pred(filePath)
            self.input.setPixmap(QPixmap(filePath))
            self.output.setPixmap(QPixmap.fromImage(qimage))


    def open_video(self):
        print("点击显示视频!")

    def bind_slots(self):
        #绑定
        self.det_image.clicked.connect(self.open_image)
        self.pushButton_2.clicked.connect(self.open_video)


if __name__=="__main__":
    app=QApplication(sys.argv)
    window1 = MainWindow()
    window1.show()

    app.exec()

八、训练视频

仍然遇到了报错:Traceback (most recent call last):
  File "D:\yolov5-master\yolov5-master\base_ui.py", line 57, in open_video
    self.input.setPixmap(QPixmap(convert2QImage(filePath)))
  File "D:\yolov5-master\yolov5-master\base_ui.py", line 13, in convert2QImage
    height,width,channel=imag.shape
AttributeError: 'str' object has no attribute 'shape'

但是我训练图片时, height,width,channel=imag.shape这行代码就没有出现问题,于是查找包含改行代码的函数调用的参数,果然写错了self.input.setPixmap(QPixmap(convert2QImage(frame)))是frame不是filePath。 一定要细心!!!

import sys
import cv2
import torch
from PySide6.QtWidgets import QMainWindow, QApplication,QFileDialog
#QFileDialog可以访问文件资源管理器

from PySide6.QtGui import QPixmap,QImage
#显示图片

from main_window import Ui_MainWindow

def convert2QImage(imag):
    height,width,channel=imag.shape
    return QImage(imag,width,height,width*channel,QImage.Format_RGB888)

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)
        self.model=torch.hub.load("./","custom",path="runs/train/exp2/weights/best.pt",source="local")
        self.bind_slots()  #不要忘记调用,不写这句话无法显示

    def image_pred(self,filePath):
        results=self.model(filePath)
        image=results.render()[0]
        return convert2QImage(image)
        #检测后的图片
    def video_pred(self,img):
        results=self.model(img)
        image=results.render()[0]
        return convert2QImage(image)

    def open_image(self):
        file_path=QFileDialog.getOpenFileNames(self,dir="./datasets/images/train",filter="*.jpg;*.png")
        #设置从dir里找图片, filter分号隔离不同格式
        #file_path返回的是有两个元素的数组,我们运行后,发现第一个元素是路径,第二个元素是格式。我们只输出路径。
        if file_path[0]:
            filePath=','.join(file_path[0])
            qimage=self.image_pred(filePath)
            self.input.setPixmap(QPixmap(filePath))
            self.output.setPixmap(QPixmap.fromImage(qimage))


    def open_video(self):#视频检测是一帧一帧地检测,利用opencv抽帧。
        file_path = QFileDialog.getOpenFileNames(self, dir="./datasets", filter="*.mp4")

        if file_path[0]:
            filePath=','.join(file_path[0])
            print(filePath)
            video = cv2.VideoCapture(filePath)
            while True:
                ret,frame=video.read()
                if not ret:
                    break
                frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
                qimage=self.video_pred(frame)
                self.input.setPixmap(QPixmap(convert2QImage(frame)))
                self.output.setPixmap(QPixmap.fromImage(qimage))


        print("点击显示视频!")

    def bind_slots(self):
        #绑定
        self.det_image.clicked.connect(self.open_image)
        self.pushButton_2.clicked.connect(self.open_video)


if __name__=="__main__":
    app=QApplication(sys.argv)
    window1 = MainWindow()
    window1.show()

    app.exec()

不过我运行后很慢,并且只显示了视频最后一帧的检测结果和原图片。

问题:界面刷新不及时。

解决:加入计时器from PySide6.QtCore import QTimer
 

import sys
import cv2
import torch
from PySide6.QtWidgets import QMainWindow, QApplication,QFileDialog
#QFileDialog可以访问文件资源管理器

from PySide6.QtGui import QPixmap,QImage
#显示图片
from PySide6.QtCore import QTimer
#计时器

from main_window import Ui_MainWindow

def convert2QImage(imag):
    height,width,channel=imag.shape
    return QImage(imag,width,height,width*channel,QImage.Format_RGB888)

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)
        self.model=torch.hub.load("./","custom",path="runs/train/exp2/weights/best.pt",source="local")
        self.timer=QTimer()
        self.timer.setInterval(100) #时间间隔。默认单位毫秒ms ,可以设置的小一点儿,视频更加丝滑。
        self.bind_slots()  #不要忘记调用,不写这句话无法显示

    def image_pred(self,filePath):
        results=self.model(filePath)
        image=results.render()[0]
        return convert2QImage(image)
        #检测后的图片
    def video_pred(self):
        ret, frame = self.video.read()
        if not ret:
            self.timer.stop()
        else:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            self.input.setPixmap(QPixmap.fromImage(convert2QImage(frame)))#放在这儿而不是self.output上面,因为可能受检测的图像影响。在检测之前先显示出来。

            results=self.model(frame)
            image=results.render()[0]
            
            self.output.setPixmap(QPixmap.fromImage(convert2QImage(image)))

    def open_image(self):
        file_path=QFileDialog.getOpenFileNames(self,dir="./datasets/images/train",filter="*.jpg;*.png")
        #设置从dir里找图片, filter分号隔离不同格式
        #file_path返回的是有两个元素的数组,我们运行后,发现第一个元素是路径,第二个元素是格式。我们只输出路径。
        if file_path[0]:
            filePath=','.join(file_path[0])
            qimage=self.image_pred(filePath)
            self.input.setPixmap(QPixmap(filePath))
            self.output.setPixmap(QPixmap.fromImage(qimage))


    def open_video(self):#视频检测是一帧一帧地检测,利用opencv抽帧。
        file_path = QFileDialog.getOpenFileNames(self, dir="./datasets", filter="*.mp4")

        if file_path[0]:
            filePath=','.join(file_path[0])
            print(filePath)
            self.video = cv2.VideoCapture(filePath)
            self.timer.start()

            # while True:
            #     ret,frame=video.read()
            #
            #     if not ret:
            #         break
            #     frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
            #     qimage=self.video_pred(frame)
            #     self.input.setPixmap(QPixmap(convert2QImage(frame)))
            #     self.output.setPixmap(QPixmap.fromImage(qimage))


        print("点击显示视频!")

    def bind_slots(self):
        #绑定
        self.det_image.clicked.connect(self.open_image)
        self.pushButton_2.clicked.connect(self.open_video)
        self.timer.timeout.connect(self.video_pred)


if __name__=="__main__":
    app=QApplication(sys.argv)
    window1 = MainWindow()
    window1.show()

    app.exec()

仍然存在问题,如果再点击“图片检测”按钮,不会停下,这是因为计时器没有停。

解决方案:在打开图片时,关闭计时器,def open_image(self): self.timer.stop()

全部代码:

import sys
import cv2
import torch
from PySide6.QtWidgets import QMainWindow, QApplication,QFileDialog
#QFileDialog可以访问文件资源管理器

from PySide6.QtGui import QPixmap,QImage
#显示图片
from PySide6.QtCore import QTimer
#计时器

from main_window import Ui_MainWindow

def convert2QImage(imag):
    height,width,channel=imag.shape
    return QImage(imag,width,height,width*channel,QImage.Format_RGB888)

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(MainWindow,self).__init__()
        self.setupUi(self)
        self.model=torch.hub.load("./","custom",path="runs/train/exp2/weights/best.pt",source="local")
        self.timer=QTimer()
        self.timer.setInterval(1) #默认单位毫秒ms
        self.bind_slots()  #不要忘记调用,不写这句话无法显示

    def image_pred(self,filePath):
        results=self.model(filePath)
        image=results.render()[0]
        return convert2QImage(image)
        #检测后的图片
    def video_pred(self):
        ret, frame = self.video.read()
        if not ret:
            self.timer.stop()
        else:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            self.input.setPixmap(QPixmap.fromImage(convert2QImage(frame)))
            # 放在这儿而不是self.output上面,因为可能受检测的图像影响。在检测之前先显示出来。
            results=self.model(frame)
            image=results.render()[0]
            self.output.setPixmap(QPixmap.fromImage(convert2QImage(image)))

    def open_image(self):
        self.timer.stop()
        file_path=QFileDialog.getOpenFileNames(self,dir="./datasets/images/train",filter="*.jpg;*.png")
        #设置从dir里找图片, filter分号隔离不同格式
        #file_path返回的是有两个元素的数组,我们运行后,发现第一个元素是路径,第二个元素是格式。我们只输出路径。
        if file_path[0]:
            filePath=','.join(file_path[0])
            qimage=self.video_pred(filePath)
            self.input.setPixmap(QPixmap(filePath))
            self.output.setPixmap(QPixmap.fromImage(qimage))


    def open_video(self):#视频检测是一帧一帧地检测,利用opencv抽帧。
        file_path = QFileDialog.getOpenFileNames(self, dir="./datasets", filter="*.mp4")

        if file_path[0]:
            filePath=','.join(file_path[0])
            print(filePath)
            self.video = cv2.VideoCapture(filePath)
            self.timer.start()

            # while True:
            #     ret,frame=video.read()
            #
            #     if not ret:
            #         break
            #     frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
            #     qimage=self.video_pred(frame)
            #     self.input.setPixmap(QPixmap(convert2QImage(frame)))
            #     self.output.setPixmap(QPixmap.fromImage(qimage))


        print("点击显示视频!")

    def bind_slots(self):
        #绑定
        self.det_image.clicked.connect(self.open_image)
        self.pushButton_2.clicked.connect(self.open_video)
        self.timer.timeout.connect(self.video_pred)


if __name__=="__main__":
    app=QApplication(sys.argv)
    window1 = MainWindow()
    window1.show()

    app.exec()

九、复盘

  1. 首先利用Pyside6的designer设计了UI界面。两个button,两个label,一条线。导出生成ui文件。将ui文件编译生成成py文件,注意external tool选的是pyside6-uic.exe,不是uic.exe!!!
  2. 构建程序,设计函数:初始化;绑定按键与函数事件;打开图片;打开视频;图片预测;视频预测【预测部分利用了torch.hub,实际上是对每一帧的图片进行预测,利用了计时器】


今天最大的收获就是可以平静地对待报错了,之前从大一开始每次改报错都特别烦躁,今天竟然可以平静地坐着改几个小时的bug。我之前特别怵头以后做机器学习、python相关的研究,现在不怕了。

要相信你遇到的问题,别人也遇到过,并且他们解决了。

如果别人没有遇到过,那正好,你会是第一个发现问题并解决的人,之后的人都会借鉴你的解决方案。

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

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

相关文章

关系型数据库与非关系型数据库、Redis数据库

相比于其他的内存/缓存数据库,redis可以方便的实现持久化的功能(保存至磁盘中) 一、关系数据库与非关系型数据库 1.1 关系型数据库 一个结构化的数据库,创建在关系模型基础上一般面向于记录 SQL语句 (标准数据查询语言) 就是一种…

11-pyspark的RDD的变换与动作算子总结

目录 前言 变换算子动作算子 前言 一般来说,RDD包括两个操作算子: 变换(Transformations):变换算子的特点是懒执行,变换操作并不会立刻执行,而是需要等到有动作(Actions)…

大语言模型落地的关键技术:RAG

1、什么是RAG? RAG 是检索增强生成(Retrieval-Augmented Generation)的简称,是当前最火热的大语言模型应用落地的关键技术,主要用于提高语言模型的效果和准确性。它结合了两种主要的NLP方法:检索&#xff…

【智能排班系统】AOP实现操作日志自动记录

文章目录 操作日志介绍自动保存操作日志基本实现思路定义注解枚举业务类型枚举操作人员类型枚举 AOP具体实现方法上添加注解 日志增删改查日志表sql实体类ServiceControllerVo 操作日志介绍 操作日志是对系统或应用程序中所有用户操作、系统事件、后台任务等进行详细记录的文本…

代码随想录算法训练营Day46|LC139 单词拆分

一句话总结:完全背包! 原题链接:139 单词拆分 动态规划之完全背包五部曲: 确定dp数组与下标含义:表示字符串长度为i时,dp[i] true 的话,可以拆分为一个或多个在字典中出现的单词。确定递归公…

贪心算法|122.买卖股票的最佳时机II

力扣题目链接 class Solution { public:int maxProfit(vector<int>& prices) {int result 0;for (int i 1; i < prices.size(); i) {result max(prices[i] - prices[i - 1], 0);}return result;} }; 贪心思路出来了&#xff0c;代码居然如此简单啊&#xff0…

16.Python多线程

如果想让我们的程序同时执行多个任务&#xff0c;就需要使用多线程技术了 。到目前为止&#xff0c;我们编写的程序都是单线程的&#xff0c;在运行时一次只能执行 一个任务。 1 线程相关的知识 1.1 进程 一个进程就是一个正在执行的程序&#xff0c;每一个进程都有自己独立…

软考高级架构师:嵌入式处理器体系结构

一、AI 讲解 嵌入式处理器体系结构中&#xff0c;冯诺依曼结构和哈佛结构是两种最基本的设计模式&#xff0c;它们各有特点和典型应用场景。 结构定义特点典型应用冯诺依曼结构一种将程序存储器和数据存储器合并在同一存储器中的计算机体系结构。这意味着指令和数据共享同一个…

基于javassm实现的水果销售管理网站

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

【C++航海王:追寻罗杰的编程之路】C++的类型转换

目录 1 -> C语言中的类型转换 2 -> 为什么C需要四种类型转换 3 -> C强制类型转换 3.1 -> static_cast 3.2 -> reinterpret_cast 3.3 -> const_cast 3.4 -> dynamic_cast 4 -> RTTI 1 -> C语言中的类型转换 在C语言中&#xff0c;如果赋值运…

【攻防世界】FlatScience

dirsearch 扫描发现四个文件 在login.php 中发现 输入 http://61.147.171.105:61912/login.php/?debug 发现源码 <?php if(isset($_POST[usr]) && isset($_POST[pw])){$user $_POST[usr];$pass $_POST[pw];$db new SQLite3(../fancy.db);$res $db->query(…

【STM32】存储器和位带映射(bit band mapping)

文章目录 0 前言1 关于地址和存储器2 STM32内部存储器3 位带映射&#xff08;bit band mapping&#xff09;4 扩展&#xff1a;IAP 0 前言 最近在研究stm32标准库&#xff0c;对使用宏定义实现位操作的函数非常感兴趣&#xff0c;简单的一句PAout(1) 0;就能实现某个引脚电平的…

【JavaWeb】Day35.MySQL概述——数据库设计-DDL(二)

表操作 关于表结构的操作也是包含四个部分&#xff1a;创建表、查询表、修改表、删除表。 1.创建 语法 create table 表名( 字段1 字段1类型 [约束] [comment 字段1注释 ], 字段2 字段2类型 [约束] [comment 字段2注释 ], ...... 字段n 字段n类型 [约束] [comment …

phpstorm设置头部注释和自定义注释内容

先说设置位置&#xff1a; PhpStorm中文件、类、函数等注释的设置在&#xff1a;setting-》Editor-》FIle and Code Template-》Includes-》PHP Function Doc Comment下设置即可&#xff0c;其中方法的默认是这样的&#xff1a; /** ${PARAM_DOC} #if (${TYPE_HINT} ! "…

SpringBoot新增员工模块开发

需求分析与设计 一&#xff1a;产品原型 一般在做需求分析时&#xff0c;往往都是对照着产品原型进行分析&#xff0c;因为产品原型比较直观&#xff0c;便于我们理解业务。 后台系统中可以管理员工信息&#xff0c;通过新增员工来添加后台系统用户。 新增员工原型&#xf…

4.1 JavaScript的使用

JavaScript有两种使用方式&#xff1a;一是在HTML文档中直接添加代码&#xff1b;二是将JavaScript脚本代码写到外部的JavaScript文件中&#xff0c;再在HTML文档中引用该文件的路径地址。 这两种使用方式的效果完全相同&#xff0c;可以根据使用率和代码量选择相应的开发方式。…

【ControlNet v3版本论文阅读】

网络部分最好有LDM或者Stable Diffusion的基础&#xff0c;有基础的话会看的很轻松 Abstract 1.提出了一种网络结构支持额外输入条件控制大型预训练的扩散模型。利用预训练模型学习一组不同的条件控制。 2.ControlNet对于小型&#xff08;<50k&#xff09;或大型&#xff…

经典机器学习模型(九)EM算法在高斯混合模型中的应用

经典机器学习模型(九)EM算法在高斯混合模型中的应用 EM算法的推导可以参考&#xff1a; 经典机器学习模型(九)EM算法的推导 若随机变量X服从一个数学期望为 μ μ μ、方差为 σ 2 σ^2 σ2的正态分布&#xff0c;可以记为 N ( μ &#xff0c; σ 2 ) N(μ&#xff0c;σ2)…

二叉树进阶——手撕二叉搜索树

troop主页&#xff1a;troop 手撕二叉搜索树 1.二叉搜索树的定义2.实现&#xff08;非递归&#xff09;补充结构2.1查找2.2插入2.3删除&#xff08;重要&#xff09;情况1(无孩子&&一个孩子&#xff09; 3.二叉搜索树的应用3.1K模型3.2KV模型3.2.1KV模型的实现 总结二叉…

「每日跟读」英语常用句型公式 第4篇

「每日跟读」英语常用句型公式 第4篇 1. I’ve decided to ____ 我决定要____了 I’ve decided to take a vacation (我决定要去度假) I’ve decided to change my lifestyle (我决定要改变我的生活方式) I’ve decided to adopt a dog (我决定要收养一条狗了) I’ve dec…