【深度学习】跌倒识别 Yolov5(带数据集和源码)从0到1,内含很多数据处理的坑点和技巧,收获满满

news2024/11/22 20:33:29

文章目录

  • 前言
  • 1. 数据集
    • 1.1 数据初探
    • 1.2 数据处理
    • 1.3 训练前验证图片
    • 1.4 翻车教训和进阶知识
  • 2. 训练
  • 3.效果展示


前言

又要到做跌倒识别了。

主流方案有两种:
1.基于关键点的识别,然后做业务判断,判断跌倒,用openpose可以做到。但这种适合背景比较干净的,类似抖音尬舞的输出;
2.基于目标监测的,有人躺下就标注为跌倒

第二种方案,适合在工地,或者工厂上班的情况,因为很容易有人围观,聚集起来,方案1就容易误报,因为它为了保障速度,使用的是自下而上的方式。很容易将不同人的关键点张冠李戴,造成误报。
因此我们使用方案2。


1. 数据集

1.1 数据初探

数据集是不缺少的,我找到了两个,一个是paddle的,一个是阿里的。

在这里插入图片描述
两份都是带标注的,可是问题是,他们划分的类别并不统一,pp_fall 只标注了跌倒的部分,其它的人和物都是背景类。
fall文件夹则标注了:10+(超过10个人),down,dog,people(能分开的人)四类。
这两个数据集一个1k+,一个8k+, 都是xml标注的。
外圈那个就是10个人,标注了10+
第一个文件夹:
在这里插入图片描述
第二个文件夹:
违规了图片。。。反正就是两个文件夹

1.2 数据处理

既然知道了两者的数据特点,就可以做数据合并了。
那必须是抽取bbox,只选取down的部分做目标,其它都做背景类。
同时把voc的xml格式转换成yolov的txt格式。
我个人习惯是,把数据集合并起来,原数据集保持不变。
合并策略:
建立两个文件夹 first_dir/images first_dir/labels 下面再分 train 和 val 比例9:1
第二个和第一个保持一致,
第一个文件夹过滤出down的标注
第二个文件夹过滤出fall的标注,并生成相应的yolov txt格式的文件,
0.5% 的抽样率看看生成的标注和图片能不能对上.
在这里插入图片描述

核心代码如下:

# 创建文件夹
import os
import shutil
import cv2
import glob
import random
import traceback
base_label_dir = r"D:\Dataset\zhongwaiyun\fall\labels"
base_img_dir = r"D:\Dataset\zhongwaiyun\fall\images"
# 已经明确知道,两个文件夹只有这两个标签和迭代有关系,所以把他们过滤出来
classes = ["fall", "down"]


def convert(size, box):
    dw = 1. / size[0]
    dh = 1. / size[1]
    x = (box[0] + box[1]) / 2.0
    y = (box[2] + box[3]) / 2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x, y, w, h)


def copy_pic_to_dest(raw_img_path, dst_img_path):
    """
    移动图片
    :param raw_img_path:
    :param dst_img_path:
    :return:
    """
    shutil.copy(raw_img_path, dst_img_path)
    return dst_img_path


def create_txt_to_dest(raw_xml_path, dst_img_path):
    """
    在目标处生成txt文件
    :param raw_xml_path:
    :param dst_img_path:
    :return:
    """

    tree = ET.parse(raw_xml_path)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)
    dst_txt_path = dst_img_path.replace("images", "labels").replace(".jpg", ".txt")
    show_pic_flag = random.randint(1, 1000) > 995
    img = cv2.imread(dst_img_path)
    if img is None:
        print(dst_img_path,"is none")
        return False
    h,w,_ = img.shape
    if show_pic_flag:
        pass
    with open(dst_txt_path, "w") as out_file:
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in classes or int(difficult) == 1:
                #过滤非跌倒和难例的图片
                continue
            # 跌倒目标类都是0
            cls_id = 0
            xmlbox = obj.find('bndbox')
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            print("bbbbbbbbb", b)
            x_top_left, y_top_left, x_bottom_right, y_bottom_right = int(b[0]), int(b[2]), int(b[1]), int(b[3])
            try:
                bb = convert((w, h), b)
            except:
                print(traceback.format_exc())
                print("raw_xml_path:::",raw_xml_path)
                return False

            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
            if show_pic_flag:
                cv2.putText(img, cls, (x_top_left, y_top_left), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
                cv2.rectangle(img, (x_top_left, y_top_left), (x_bottom_right, y_bottom_right), (0, 0, 255), thickness=2)
    if show_pic_flag:
        cv2.imshow("image", img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()


第一个文件夹调用:

# 第一个数据源:
source_img_dir1 = r"D:\日常资料\01项目\中外运\20230524人员跌倒\fall"
count_num = 0
for xml_path in glob.glob(source_img_dir1 + "\*.xml"):
    if count_num%10==0:
        dst_img_path = os.path.join(base_img_dir,"val",str(count_num) + ".jpg")
    else:
        dst_img_path = os.path.join(base_img_dir,"train",str(count_num) + ".jpg")
    raw_img_path = xml_path.replace(".xml",".jpg")
    if not os.path.exists(raw_img_path):
        print("{} 不存在".format(raw_img_path))
        continue
    copy_pic_to_dest(raw_img_path, dst_img_path)
    create_txt_to_dest(xml_path, dst_img_path)
    count_num += 1
    print(count_num)

验证结果:
在这里插入图片描述

在这里插入图片描述
空白背景类
是个jc的图片

第二个文件夹调用:

# 第二个数据源:
source_img_dir1 = r"D:\日常资料\01项目\中外运\20230524人员跌倒\pp_fall\Annotations"
count_num = 8000
for xml_path in glob.glob(source_img_dir1 + "\*.xml"):
    if count_num%10==0:
        dst_img_path = os.path.join(base_img_dir,"val",str(count_num) + ".jpg")
    else:
        dst_img_path = os.path.join(base_img_dir,"train",str(count_num) + ".jpg")
    raw_img_path = xml_path.replace(".xml",".jpg").replace("Annotations","images")
    if not os.path.exists(raw_img_path):
        print("{} 不存在".format(raw_img_path))
        continue
    copy_pic_to_dest(raw_img_path, dst_img_path)
    create_txt_to_dest(xml_path, dst_img_path)
    count_num += 1
    print(count_num)

1.3 训练前验证图片

# 跑一遍标签的数量,实例数量,和背景类数据
base_dir = r"D:\Dataset\zhongwaiyun\fall"
txt_path_list = glob.glob(base_dir + "\**\*.txt",recursive=True)
img_path_list = glob.glob(base_dir + "\**\*.jpg",recursive=True)
total_info = {}
txt_count = len(txt_path_list)
img_count = len(img_path_list)
# 标签数量
total_info["txt_count"] = txt_count
# 图片数量
total_info["img_count"] = img_count
# 只有图片而没有标签
total_info["img_without_txt_list"] = []
# 只有标签而没有图片
total_info["txt_without_img_list"] = []
# class_set
total_info["class_set"] = set()
# 每个类有多少个实例
total_info["instance_count_per_class"] = dict()
total_info["background_count"] = 0
txt_path_error = []
img_path_error = []
count_num = 0
for txt_path in txt_path_list:
    if count_num !=0:
        # continue
        pass

    if not os.path.exists(txt_path):
        txt_path_error.append(txt_path)
    img_path = txt_path.replace("labels", "images").replace(".txt", ".jpg")
    if not os.path.exists(img_path):
        total_info["txt_without_img_list"].append(txt_path)
    show_flag = False
    if count_num % 3000==0:
        show_flag = True
        print(img_path)
    cv2_img = cv2.imread(img_path)
    if cv2_img is None:
        img_path_error.append(img_path)
        continue
    height, width, _ = cv2_img.shape
    print(height, width, _)

    with open(txt_path) as f:
        line_list = f.readlines()
        print(line_list)
        for line_str in line_list:
            info_list = line_str.strip().split(" ")
            class_id = int(info_list[0])
            total_info["class_set"].add(class_id)
            x, y, w, h = map(float, info_list[1:])  # 目标中心点坐标和宽高比例
            if class_id not in total_info["instance_count_per_class"].keys():
                total_info["instance_count_per_class"][class_id] = 1

            else:
                total_info["instance_count_per_class"][class_id] += 1
            if show_flag:
                # 计算出左上角和右下角坐标
                left = int((x - w / 2) * width)
                top = int((y - h / 2) * height)
                right = int((x + w / 2) * width)
                bottom = int((y + h / 2) * height)
                print("--===---",(left, top), (right, bottom),class_id)
                # 绘制矩形框和类别标签
                cv2.rectangle(cv2_img, (left, top), (right, bottom), (0, 255, 0), 2)
                label = class_id
                cv2.putText(cv2_img, str(label), (left, top), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        if len(line_list) == 0:
            total_info["background_count"] += 1
        if show_flag:
            cv2.imshow('image', cv2_img)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
        count_num+=1

print(txt_path_error,img_path_error,total_info)

在这里插入图片描述
以标注为中心跑:
背景图片650张
实例图片:0(迭倒)==》 10493张
opencv 不能打开的图片:

 ['D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\1979.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\2233.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\2371.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\3268.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\3746.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\4876.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\5204.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\5364.jpg', 'D:\\Dataset\\zhongwaiyun\\fall\\images\\train\\6418.jpg']

这个其实是一张动图,
在这里插入图片描述
在这里插入图片描述
第二个不知道咋回事,opencv和pil都打不开
所以我懒一下,把这几个图片和标注都del

for img_path in img_path_error:
    os.remove(img_path)
    txt_path = img_path.replace("images","labels").replace(".jpg",".txt")
    if os.path.exists(txt_path):
        os.remove(txt_path)
        print(txt_path)

1.4 翻车教训和进阶知识

  1. img = cv2.imread(xxxx)
    h,w,c = img.shape
    一定要记住h,w,c 它和 PIL 是不一样的
    pil_img = Image.open(xxxx)
    w,h = pil_img.size()
    另外,目录参数,cv2.imread() 也未必能成功,还是要尽快找出一个万全之策。
  2. 现在已经拿到图片的数据描述了,多少张、多少实例、每类的分布,后面要判断出,多少小目标、类的均衡性(单一类别无所谓)、目标的密集度、分布度、曝光强度等,类别间相似度,一共是8个维度。
  3. 对场景识别的,漏报要分析原因,是8个维度的那个维度造成的。
  4. 对误报背景当成某一类,或者类A,当成类别B,要增加数据集。但是要
  5. 一个一个的验证太慢了,cv2.show() 要改成 Img.grid 的方式,一次性展示多张比较妥当。

2. 训练

fall.yaml

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# COCO128 dataset https://www.kaggle.com/ultralytics/coco128 (first 128 images from COCO train2017) by Ultralytics
# Example usage: python train.py --data coco128.yaml
# parent
# ├── yolov5
# └── datasets
#     └── coco128  ← downloads here (7 MB)


# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]

train: ["/data_share/data_share/zhongwaiyun/fall/images/train"]
val: ["/data_share/data_share/zhongwaiyun/fall/images/val"]
test:  # test images (optional)
# xxx/a/imag
# xxx/a/labels
## [xxx/a/images, xxx/b/images,...,....]
## [ xxx/a/labels]
# Classes
names:
  0: fall
# Download script/URL (optional)
# download: https://ultralytics.com/assets/coco128.zip

训练命令,2张卡,用多卡训练

python -m torch.distributed.launch --nproc_per_node=2  train.py --img 640 --batch 48 --epochs 100 --dat                                                                                                 a fall.yaml --weights weights/yolov5m6.pt  --workers 8 --save-period 20

训练过程中的warning:


train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/75.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7599.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7602.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7608.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7618.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7671.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7696.jpg: ignoring corrupt image/label: image file is truncated (53 bytes not processed)
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7704.jpg: corrupt JPEG restored and saved
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7707.jpg: ignoring corrupt image/label: image file is truncated (16 bytes not processed)
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/7717.jpg: ignoring corrupt image/label: image file is truncated (6 bytes not processed)


libpng warning: iCCP: known incorrect sRGB profile
val: Scanning '/data_share/data_share/zhongwaiyun/fall/labels/val' images and labels...922 found, 0 missing, 72 empty, 0 corrupt: 100%|██████████| 922/922 [00:01<00:00, 598.34it/s]
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1070.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1480.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1550.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1580.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1630.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1650.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/1690.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/2580.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/4850.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/4880.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/4940.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/650.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/7410.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/7600.jpg: corrupt JPEG restored and saved
val: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/val/8460.jpg: corrupt JPEG restored and saved

是因为图片损坏所致,不影响训练,但warning说明图片已损坏,可能影响最终效果
解决方案:

import glob
from PIL import Image
base_dir = r"D:\Dataset\zhongwaiyun\fall"
# txt_path_list = glob.glob(base_dir + "\**\*.txt",recursive=True)
img_path_list = glob.glob(base_dir + "\**\*.jpg",recursive=True)
import os

for img_path in img_path_list:
    try:
        # 打开图片文件
        img = Image.open(img_path)

        # 检查图像模式,并转换为RGB,如果不是RGB模式
        if img.mode != 'RGB':
            img = img.convert('RGB')
        # 将其保存为JPEG格式
        img.save(img_path, 'JPEG')
    except Exception as e:
        os.remove(img_path)
        txt_path = img_path.replace("images","labels").replace(".jpg",".txt")
        os.remove(txt_path)
        print(e,txt_path,img_path)

bug:https://zhuanlan.zhihu.com/p/132554622
Image file is truncated( bytes not processed)
这个是图片太大所致,找到它,把它删除,或者ImageFile.LOAD_TRUNCATED_IMAGES = True 设置一下即可。

经过以上操作后,图片损坏的warning没有了:


Transferred 619/627 items from weights/yolov5m6.pt
AMP: checks passed ✅
optimizer: SGD(lr=0.01) with parameter groups 103 weight(decay=0.0), 107 weight(decay=0.000375), 107 bias
train: Scanning '/data_share/data_share/zhongwaiyun/fall/labels/train' images and labels...8289 found, 0 missing, 578 empty, 1 corrupt: 100%|██████████| 8289/8289 [00:09<00:00, 8
train: WARNING ⚠️ /data_share/data_share/zhongwaiyun/fall/images/train/1185.jpg: ignoring corrupt image/label: non-normalized or out of bounds coordinates [     1.0163]
train: New cache created: /data_share/data_share/zhongwaiyun/fall/labels/train.cache
val: Scanning '/data_share/data_share/zhongwaiyun/fall/labels/val' images and labels...922 found, 0 missing, 72 empty, 0 corrupt: 100%|██████████| 922/922 [00:00<00:00, 1016.17it
val: New cache created: /data_share/data_share/zhongwaiyun/fall/labels/val.cache

AutoAnchor: 6.63 anchors/target, 1.000 Best Possible Recall (BPR). Current anchors are a good fit to dataset ✅
Plotting labels to runs/train/exp3/labels.jpg...
Image sizes 640 train, 640 val
Using 8 dataloader workers
Logging results to runs/train/exp3
Starting training for 100 epochs...

训练时的bug:

RuntimeError: Address already in use pytorch分布式训练

分布式训练时会遇到,说是端口占用,指引在这里:https://github.com/NVIDIA/tacotron2/issues/181

Your previous execution is not completely terminated.
netstat -nltp this command will show process lists which are listen ports. Now, you have to kill process which is listen 54321 port. kill -9 PID. in this case. kill -9 1594. Then try to start training.

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

实在不行,reboot肯定好用。

两张卡都没闲着
在这里插入图片描述

3.效果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
epochs 在60~80 的时候是不错的。
代码和数据集整理中。。。待续
这次时间主要花在了数据集的整理上,因为是两份数据集拼合起来的。标注的类名称啥的不尽相同,合并和验证花了不少时间。收获也不小,大家加油!

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

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

相关文章

干货分享 | CloudQuery 数据保护能力之动态数据脱敏!

在企业数字化转型的过程中&#xff0c;尤其随着互联网、云计算、大数据等信息技术与通信技术的迅猛发展&#xff0c;海量数据在各种信息系统上被存储和处理&#xff0c;其中包含大量有价值的敏感数据&#xff0c;这意味着数据泄露的风险也不断增加。 数据泄露可能由各种因素引…

【项目】实现web服务器

目录 1.需要实现的项目需求&#xff08;web服务器的工作原理&#xff09; 2.实现过程&#xff1a; 1.编写套接字 2.多线程的代码和任务类 3.文件描述符的处理方法的框架 4.读取请求 4.1.读取请求行 4.2.读取请求报头 4.3.分析请求行和报头 请求行的方法、URI、版本…

桌面图标删不掉?试试这几个解决办法!

案例&#xff1a;我想对电脑桌面上的应用进行删除&#xff0c;但是我怎么删也删不掉应用的图标&#xff1f;有人知道这是怎么回事吗&#xff1f;怎样才能成功删除桌面图标&#xff1f;求一个解决办法&#xff01; 有时候我们可能会遇到桌面图标无法删除的困扰&#xff0c;桌面…

【已解决】Macbook pro/Macbook air 电脑过热问题(附软件下载地址)

问题&#xff1a; 今天早上一上班打开我的macbook air&#xff0c;刚开机了十来分钟&#xff0c;就觉得左上角位置特别的热&#xff0c;耳朵凑近风扇处&#xff0c;基本听不到风扇的声音&#xff0c;风扇的转速太慢&#xff0c;导致cpu温度堆积造成温度升高。 解决办法&#…

【JS】1705- 重学 JavaScript API - Fullscreen API

❝ 前期回顾&#xff1a; 1. Page Visibility API 2. Broadcast Channel API 3. Beacon API 4. Resize Observer API 5. Clipboard API 6. Fetch API 7. Performance API 8. WebStorage API 9. WebSockets API ❞ 本文中&#xff0c;我们将探索 Fullscreen API 的概念、使用方法…

SpringBoot+Vue 的简历招聘系统

文章目录 1、效果演示2、 前言介绍3、主要技术4 **系统设计**4.1 系统体系结构4.2开发流程设计4.3 数据库设计原则4.4 数据表 5 **系统详细设计**5.1管理员功能模块5.2用户功能模块5.3前台首页功能模块 6、源码获取 1、效果演示 2、 前言介绍 随着科学技术的飞速发展&#xff…

加速5G部署,到底该怎么做?

今天&#xff0c;第31届中国国际信息通信展&#xff08;PT展&#xff09;在北京国家会议中心圆满落幕。 这次通信展&#xff0c;在举办日期上有着特殊的意义。因为&#xff0c;今年的6月6日&#xff0c;正好是国内5G牌照正式发放的四周年纪念日。而且&#xff0c;去年大概这个时…

DETR模型转RKNN

目录 1.前言 2.准备工作 3.开始转模型 4.测试代码 5.不想转&#xff0c;直接用也可以&#xff0c;转好的给你&#xff0c;请关注评论一下 1.前言 RKNN出最新版本了&#xff0c;测试了一下&#xff0c;rk在transformer方面做了很多的工作&#xff0c;至少之前不能转的模型&am…

ReadProcessMemory可不是一个进程间通信的好方法

有时候我看到有人会使用 ReadProcessMemory 这个 API 来实现进程间通信&#xff0c;老实说吧&#xff0c;我觉得这不是一个明智的选择&#xff0c;原因有如下几条。 首先&#xff0c;你不能使用 ReadProcessMemory 来跨越安全上下文 (Security Contexts)&#xff0c;至少你需要…

SpringCloud入门实战(八)- Gateway服务网关集成

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我&#xff0c;不迷路 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术…

macOS Sonoma 14.0 (23A5257q) Beta1 带 OC 引导双分区黑苹果镜像

6月6日&#xff0c;在WWDC2023开发者大会上&#xff0c;苹果带来了全新Mac系统&#xff0c;命名为macOS Sonoma。该系统最大的亮点是带来了小组件&#xff0c;macOS Sonoma可以添加手机上的所有小组件&#xff0c;包括车辆小组件。 镜像下载&#xff1a; 微信公众号&#xff1…

聚观早报 | 苹果发XR头显Vision Pro;英特尔将出售部分Mobileye股票

今日要闻&#xff1a;苹果发XR头显Vision Pro&#xff1b;英特尔将出售部分Mobileye股票&#xff1b;华为已申请注册两枚NETGPT&#xff1b;瑞幸咖啡全国门店数量突破1万家&#xff1b;iPhone15系列本月将在郑州富士康量产 苹果发XR头显Vision Pro 6 月 6 日&#xff0c;苹果 …

从零手写操作系统之RVOS环境搭建-01

从零手写操作系统之RVOS环境搭建-01 背景介绍操作系统的定义操作系统的分类典型的 RTOS 介绍课程系统RVOS简介 Hello WorldQEMU介绍QEMU-virt 地址映射 系统引导引导程序要做哪些事情如何判断当前hart是不是第一个hart?如何初始化栈? 如何在屏幕输出Hello World通过串口输出U…

基于java SpringBoot框架和Vue的智能停车场管理系统

近年来&#xff0c;中国不仅综合国力大幅提升&#xff0c;国民经济也快速增长&#xff0c;推动了中国汽车工业的发展。技术的飞速发展逐渐降低了汽车的制造成本&#xff0c;越来越受欢迎。今天&#xff0c;大多数家庭都有能力购买汽车&#xff0c;因此&#xff0c;中国城市的汽…

R语言手动绘制连续线条的校准曲线(Calibration curve)(4)

校准曲线图表示的是预测值和实际值的差距&#xff0c;作为预测模型的重要部分&#xff0c;目前很多函数能绘制校准曲线。 一般分为两种&#xff0c;一种是通过Hosmer-Lemeshow检验&#xff0c;把P值分为10等分&#xff0c;求出每等分的预测值和实际值的差距。 我们既往已经通…

基于组件化开发思想的微信小程序开发框架

跨端框架的出现为小程序应用的开发带来了巨大的便利性和灵活性。它们提供了统一的开发方式、代码复用的能力&#xff0c;并且与小程序容器技术紧密结合&#xff0c;实现了一次编码、多端运行的目标。开发者可以根据项目需求和团队技术栈选择合适的跨端框架&#xff0c;从而在不…

【大数据工具】Spark 伪分布式、分布式集群搭建

Spark 集群搭建 Spark 安装包下载地址&#xff1a;https://archive.apache.org/dist/spark/ 1. Spark 伪分布式安装 安装前提&#xff1a;安装 Spark 前需要先安装好 JDK 1. 上传并解压 Spark 安装包 使用 fileZilla 或其他文件传输工具上传 Spark 安装包&#xff1a;spar…

简单易懂的 nvm 和 Node.js 版本控制指南

NVM是Node.js的版本管理工具&#xff0c;可以方便地在不同版本的Node.js之间切换。它可以通过命令行或者脚本来管理Node.js的版本&#xff0c;支持在同一台机器上安装多个版本的Node.js&#xff0c;并能够方便地切换它们。 NVM的主要功能包括&#xff1a; 安装和卸载Node.js的不…

2022年国赛高教杯数学建模A题波浪能最大输出功率设计解题全过程文档及程序

2022年国赛高教杯数学建模 A题 波浪能最大输出功率设计 原题再现 随着经济和社会的发展&#xff0c;人类面临能源需求和环境污染的双重挑战&#xff0c;发展可再生能源产业已成为世界各国的共识。波浪能作为一种重要的海洋可再生能源&#xff0c;分布广泛&#xff0c;储量丰富…

DevExpress WinForms v23.1新功能抢先看——支持系统强调色更改

DevExpress WinForm 下一个主要版本&#xff08;v23.1&#xff09;将在6月份左右发布&#xff0c;本文将为大家介绍在早期访问预览版&#xff08;EAP&#xff09;中包含的新功能。 PS&#xff1a;DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具…