【萬字長文】深度學習2 yolov5修改為自己的數據集

數據預處理

使用labelme可以直接導出適用于yolo模型的txt文本數據,也可以直接導出默認的json數據結構,后面我會提供代碼進行轉換。自行進行標注,圖片與標注一一對應,更多要求不贅述。因為我做最簡單的檢索模型,不做切割,所以用矩形框進行框選就可以。
我的數據集大致如下,老師給的真實數據不能外泄,里面就是一些標注位置及類型:

格式轉換:

1、新建目錄

標注好的數據放在原始數據集original_datasest里面,注意英文路徑下。新建data目錄。

2、新建下面四個包存放數據

Annotations:存放轉換之后圖片的xml文件,images:存放數據集的圖片文件,ImageSets :存放數據集按比例分割之后自動生成的train.txt,val.txt,test.txt和trainval.txt四個文件,labels:存放xml文件轉換后的txt標準格式標簽。

3、json轉xml

import os
import xml.domimport numpy as np
import codecs
import json
import glob
import cv2
import shutil# 1.標簽路徑
labelme_path = r"D:\something\homework\deeplearning\Mydataset\original_dataset\Thyroid"  # 原始json、bmp標注數據路徑,需要更換成自己的數據集名稱
saved_path = r"D:\something\homework\deeplearning\Mydataset\data\Annotations"  # 保存路徑# 2.獲取待處理文件
files = glob.glob("%s/*.json" % (labelme_path))# 3.讀取標注信息并寫入 xml
for json_filename in files:json_file = json.load(open(json_filename, "r", encoding="utf-8"))i = 0# 圖像名字,若圖像格式不是jpg,需要修改此處img_name = json_filename.replace(".json", ".jpg")height, width, channels = cv2.imread(img_name).shape# xml名字xmlName = os.path.join(saved_path, json_filename.split("\\")[-1].replace(".json", ".xml"))with codecs.open(xmlName, "w", "utf-8") as xml:print(2)xml.write('<annotation>\n')xml.write('\t<folder>' + 'jpg' + '</folder>\n')xml.write('\t<filename>' + img_name + '</filename>\n')# -------------------------------------------------xml.write('\t<source>\n')xml.write('\t\t<database>hulan</database>\n')# --------------------------------------------------xml.write('\t</source>\n')# -----------------------------------------------------------xml.write('\t<size>\n')xml.write('\t\t<width>' + str(width) + '</width>\n')xml.write('\t\t<height>' + str(height) + '</height>\n')xml.write('\t\t<depth>' + str(channels) + '</depth>\n')# ------------------------------------------------xml.write('\t</size>\n')xml.write('\t\t<segmented>0</segmented>\n')# 節點判斷for multi in json_file["shapes"]:points = np.array(multi["points"])xmin = min(points[:, 0])xmax = max(points[:, 0])ymin = min(points[:, 1])ymax = max(points[:, 1])label = multi["label"]if xmax <= xmin:passelif ymax <= ymin:passelse:xml.write('\t<object>\n')xml.write('\t\t<name>' + json_file["shapes"][i]["label"] + '</name>\n')xml.write('\t\t<pose>Unspecified</pose>\n')xml.write('\t\t<truncated>0</truncated>\n')xml.write('\t\t<difficult>0</difficult>\n')xml.write('\t\t<bndbox>\n')xml.write('\t\t\t<xmin>' + str(xmin) + '</xmin>\n')xml.write('\t\t\t<ymin>' + str(ymin) + '</ymin>\n')xml.write('\t\t\t<xmax>' + str(xmax) + '</xmax>\n')xml.write('\t\t\t<ymax>' + str(ymax) + '</ymax>\n')xml.write('\t\t</bndbox>\n')xml.write('\t</object>\n')print(json_filename, xmin, ymin, xmax, ymax, label)i = i + 1xml.write('</annotation>')# 復制圖片newImgName = os.path.join('D:/something/homework/deeplearning/Mydataset/data/images', img_name.split("\\")[-1])shutil.copy(img_name, newImgName)

自行修改地址,還有倒數第二行地址。

結果:xml文件在如下圖:

4、劃分數據集

(注釋是因為一開始用相對路徑有問題,后面全部改成絕對路徑了)

import os
import randomtrainval_percent = 0.9
train_percent = 0.9
# 1. 獲取腳本所在目錄作為基礎路徑
base_dir = os.path.dirname(os.path.abspath(__file__))# 2. 定義所有路徑(基于腳本所在目錄)
xmlfilepath = os.path.join(base_dir, 'data', 'Annotations')
imagesets_dir = os.path.join(base_dir, 'data', 'ImageSets')# 3. 確保ImageSets目錄存在
os.makedirs(imagesets_dir, exist_ok=True)# 4. 列出XML文件(添加錯誤檢查)
try:total_xml = os.listdir(xmlfilepath)
except FileNotFoundError:print(f"錯誤:目錄不存在 - {xmlfilepath}")exit(1)# 5. 避免使用關鍵字"list"作為變量名
file_count = len(total_xml)
file_indices = range(file_count)# 6. 計算分割點
trainval_percent = 0.9
train_percent = 0.9
tv = int(file_count * trainval_percent)
tr = int(tv * train_percent)# xmlfilepath = 'data/Annotations'
# total_xml = os.listdir(xmlfilepath)# num = len(total_xml)
# list = range(num)
# tv = int(num * trainval_percent)
# tr = int(tv * train_percent)# 7. 創建樣本集
trainval = random.sample(file_indices, tv)
train = random.sample(trainval, tr)# 8. 創建文件路徑(使用完整路徑)
trainval_path = os.path.join(imagesets_dir, 'trainval.txt')
test_path = os.path.join(imagesets_dir, 'test.txt')
train_path = os.path.join(imagesets_dir, 'train.txt')
val_path = os.path.join(imagesets_dir, 'val.txt')# 9. 安全地打開文件(使用with語句自動關閉)
with open(trainval_path, 'w') as ftrainval, \open(test_path, 'w') as ftest, \open(train_path, 'w') as ftrain, \open(val_path, 'w') as fval:for i in file_indices:# 10. 提取文件名(不含擴展名)file_name = os.path.splitext(total_xml[i])[0]if i in trainval:ftrainval.write(file_name + '\n')if i in train:ftrain.write(file_name + '\n')else:fval.write(file_name + '\n')else:ftest.write(file_name + '\n')print("數據集分割完成!")
print(f"總文件數: {file_count}")
print(f"訓練驗證集: {tv} 個文件")
print(f"測試集: {file_count - tv} 個文件")
print(f"訓練集: {tr} 個文件")
print(f"驗證集: {tv - tr} 個文件")# trainval = random.sample(list, tv)
# train = random.sample(trainval, tr)# ftrainval = open('data/ImageSets/trainval.txt', 'w')
# ftest = open('data/ImageSets/test.txt', 'w')
# ftrain = open('data/ImageSets/train.txt', 'w')
# fval = open('data/ImageSets/val.txt', 'w')# for i in list:
#     name = total_xml[i][:-4] + '\n'
#     if i in trainval:
#         ftrainval.write(name)
#         if i in train:
#             ftrain.write(name)
#         else:
#             fval.write(name)
#     else:
#         ftest.write(name)# ftrainval.close()
# ftrain.close()
# fval.close()
# ftest.close()

結果:(里面保存的就是劃分圖片的名字)


5、xml轉txt

yolo用得是txt格式的數據,要進行歸一化等,如下:
?

# # xml解析包
# import xml.etree.ElementTree as ET
# import pickle
# import os
# from os import listdir, getcwd
# from os.path import join# sets = ['train', 'test', 'val']
# # classes = ['round', 'square', 'rectangular', 'flat_elliptical', 'mantou', 'groove', 'regular_triangle', 'd_shaped', 'angle']
# classes=['0', '1', '2', '3', '4', '5']  # 類別名稱,0-5對應類別# # 進行歸一化操作
# def convert(size, box): # size:(原圖w,原圖h) , box:(xmin,xmax,ymin,ymax)
#     dw = 1./size[0]     # 1/w
#     dh = 1./size[1]     # 1/h
#     x = (box[0] + box[1])/2.0   # 物體在圖中的中心點x坐標
#     y = (box[2] + box[3])/2.0   # 物體在圖中的中心點y坐標
#     w = box[1] - box[0]         # 物體實際像素寬度
#     h = box[3] - box[2]         # 物體實際像素高度
#     x = x*dw    # 物體中心點x的坐標比(相當于 x/原圖w)
#     w = w*dw    # 物體寬度的寬度比(相當于 w/原圖w)
#     y = y*dh    # 物體中心點y的坐標比(相當于 y/原圖h)
#     h = h*dh    # 物體寬度的寬度比(相當于 h/原圖h)
#     return (x, y, w, h)    # 返回 相對于原圖的物體中心點的x坐標比,y坐標比,寬度比,高度比,取值范圍[0-1]# # year ='2012', 對應圖片的id(文件名)
# def convert_annotation(image_id):
#     '''
#     將對應文件名的xml文件轉化為label文件,xml文件包含了對應的bunding框以及圖片長款大小等信息,
#     通過對其解析,然后進行歸一化最終讀到label文件中去,也就是說
#     一張圖片文件對應一個xml文件,然后通過解析和歸一化,能夠將對應的信息保存到唯一一個label文件中去
#     labal文件中的格式:calss x y w h  同時,一張圖片對應的類別有多個,所以對應的bunding的信息也有多個
#     '''
#     # 對應的通過year 找到相應的文件夾,并且打開相應image_id的xml文件,其對應bund文件
#     in_file = open('data/Annotations/%s.xml' % (image_id), encoding='utf-8')
#     # 準備在對應的image_id 中寫入對應的label,分別為
#     # <object-class> <x> <y> <width> <height>
#     out_file = open('data/labels/%s.txt' % (image_id), 'w', encoding='utf-8')
#     # 解析xml文件
#     tree = ET.parse(in_file)
#     # 獲得對應的鍵值對
#     root = tree.getroot()
#     # 獲得圖片的尺寸大小
#     size = root.find('size')
#     # 如果xml內的標記為空,增加判斷條件
#     if size != None:
#         # 獲得寬
#         w = int(size.find('width').text)
#         # 獲得高
#         h = int(size.find('height').text)
#         # 遍歷目標obj
#         for obj in root.iter('object'):
#             # 獲得difficult ??
#             difficult = obj.find('difficult').text
#             # 獲得類別 =string 類型
#             cls = obj.find('name').text
#             # 如果類別不是對應在我們預定好的class文件中,或difficult==1則跳過
#             if cls not in classes or int(difficult) == 1:
#                 continue
#             # 通過類別名稱找到id
#             cls_id = classes.index(cls)
#             # 找到bndbox 對象
#             xmlbox = obj.find('bndbox')
#             # 獲取對應的bndbox的數組 = ['xmin','xmax','ymin','ymax']
#             b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
#                  float(xmlbox.find('ymax').text))
#             print(image_id, cls, b)
#             # 帶入進行歸一化操作
#             # w = 寬, h = 高, b= bndbox的數組 = ['xmin','xmax','ymin','ymax']
#             bb = convert((w, h), b)
#             # bb 對應的是歸一化后的(x,y,w,h)
#             # 生成 calss x y w h 在label文件中
#             out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')# # 返回當前工作目錄
# wd = getcwd()
# print(wd)# for image_set in sets:
#     '''
#     對所有的文件數據集進行遍歷
#     做了兩個工作:
#     1.將所有圖片文件都遍歷一遍,并且將其所有的全路徑都寫在對應的txt文件中去,方便定位
#     2.同時對所有的圖片文件進行解析和轉化,將其對應的bundingbox 以及類別的信息全部解析寫到label 文件中去
#          最后再通過直接讀取文件,就能找到對應的label 信息
#     '''
#     # 先找labels文件夾如果不存在則創建
#     if not os.path.exists('data/labels/'):
#         os.makedirs('data/labels/')
#     # 讀取在ImageSets/Main 中的train、test..等文件的內容
#     # 包含對應的文件名稱
#     image_ids = open('data/ImageSets/%s.txt' % (image_set)).read().strip().split()
#     # 打開對應的2012_train.txt 文件對其進行寫入準備
#     list_file = open('data/%s.txt' % (image_set), 'w')
#     # 將對應的文件_id以及全路徑寫進去并換行
#     for image_id in image_ids:
#         list_file.write('E:/Mydataset/data/images/%s.bmp\n' % (image_id))
#         # 調用  year = 年份  image_id = 對應的文件名_id
#         convert_annotation(image_id)
#     # 關閉文件
#     list_file.close()import xml.etree.ElementTree as ET
import pickle
import os
import random
from os import listdir, getcwd
from os.path import join, abspath, dirname# 0. 獲取腳本所在目錄作為基礎路徑
base_dir = dirname(abspath(__file__))# 1. 創建所有必要的目錄
required_dirs = ['data/Annotations','data/labels','data/ImageSets','data/images'
]for dir_path in required_dirs:full_path = join(base_dir, dir_path)os.makedirs(full_path, exist_ok=True)print(f"已創建目錄: {full_path}")# 2. 定義數據集和類別
sets = ['train', 'test', 'val']
classes = ['0', '1', '2', '3', '4', '5']  # 類別名稱# 3. 歸一化函數(保持不變)
def convert(size, box):dw = 1./size[0]dh = 1./size[1]x = (box[0] + box[1])/2.0y = (box[2] + box[3])/2.0w = box[1] - box[0]h = box[3] - box[2]x = x*dww = w*dwy = y*dhh = h*dhreturn (x, y, w, h)# 4. 修改convert_annotation函數使用絕對路徑
def convert_annotation(image_id):# 使用絕對路徑xml_path = join(base_dir, 'data', 'Annotations', f'{image_id}.xml')label_path = join(base_dir, 'data', 'labels', f'{image_id}.txt')# 檢查XML文件是否存在if not os.path.exists(xml_path):print(f"警告: XML文件不存在 - {xml_path}")returntry:tree = ET.parse(xml_path)root = tree.getroot()size = root.find('size')if size is None:print(f"警告: {xml_path} 中沒有找到size元素")returnw = int(size.find('width').text)h = int(size.find('height').text)with open(label_path, 'w', encoding='utf-8') as out_file:for obj in root.iter('object'):difficult = obj.find('difficult').textcls = obj.find('name').textif cls not in classes or (difficult and int(difficult) == 1):continuecls_id = classes.index(cls)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))bb = convert((w, h), b)out_file.write(f"{cls_id} {' '.join(map(str, bb))}\n")print(f"已處理: {image_id}")except Exception as e:print(f"處理 {xml_path} 時出錯: {str(e)}")# 5. 主程序
if __name__ == "__main__":print(f"腳本目錄: {base_dir}")print(f"當前工作目錄: {getcwd()}")# 檢查ImageSets目錄中的txt文件是否存在imagesets_dir = join(base_dir, 'data', 'ImageSets')for set_name in sets:txt_path = join(imagesets_dir, f'{set_name}.txt')if not os.path.exists(txt_path):print(f"警告: {txt_path} 不存在,將自動創建空的")open(txt_path, 'w').close()# 處理每個數據集for image_set in sets:txt_path = join(imagesets_dir, f'{image_set}.txt')try:with open(txt_path, 'r', encoding='utf-8') as f:image_ids = [line.strip() for line in f.readlines() if line.strip()]if not image_ids:print(f"警告: {txt_path} 是空的,跳過")continueprint(f"處理 {image_set} 集,共 {len(image_ids)} 個圖像")list_file_path = join(base_dir, 'data', f'{image_set}.txt')with open(list_file_path, 'w', encoding='utf-8') as list_file:for image_id in image_ids:# 使用相對路徑或絕對路徑# 相對路徑(推薦,便于在不同機器上使用)# image_path = join('data', 'images', f'{image_id}.bmp')# 絕對路徑(根據實際情況修改)image_path = join(base_dir, 'data', 'images', f'{image_id}.jpg')list_file.write(f"{image_path}\n")# 處理標注convert_annotation(image_id)print(f"完成 {image_set} 集處理")except Exception as e:print(f"處理 {image_set} 集時出錯: {str(e)}")print("所有處理完成!")

結果:

數據集分割完成!

總文件數: 100

訓練驗證集: 90 個文件

測試集: 10 個文件

訓練集: 81 個文件

驗證集: 9 個文件

6、數據類別

運行腳本知道甲狀腺結節類別:['1', '3', '5', '4', '2', '0']

腳本如下(如果知道自己有哪些類別的,就可以不用運行如下代碼):

import xml.dom.minidom as xmldom
import osbase_dir = os.path.dirname(os.path.abspath(__file__))# 2. 定義所有路徑(基于腳本所在目錄)
annotation_path = os.path.join(base_dir, 'data', 'Annotations')
# voc數據集獲取所有標簽的所有類別數"
# annotation_path = "./data/Annotations/"annotation_names = [os.path.join(annotation_path, i) for i in os.listdir(annotation_path)]labels = list()
for names in annotation_names:xmlfilepath = namesdomobj = xmldom.parse(xmlfilepath)# 得到元素對象elementobj = domobj.documentElement# 獲得子標簽subElementObj = elementobj.getElementsByTagName("object")for s in subElementObj:label = s.getElementsByTagName("name")[0].firstChild.data# print(label)if label not in labels:labels.append(label)
print(labels)

開始訓練

1、測試

接前文【長文】深度學習小白第一次完整跑通項目全過程,可以先運行一下detect.py進行測試,防止依賴版本等錯誤

2、參數設置

parser.add_argument('--workers', type=int, default=8, help='max dataloader workers (per RANK in DDP mode)')
改為0線程,后面避免問題。


3、寫配置文件

(注意冒號后面要有空格)

分別是自己的訓練測試驗證集地址和類別。

4、加載配置文件

放到代碼的data目錄下面

在train.py文件中將如下地方改成自己的配置數據集名字。

運行結果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88086.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu18編譯RealSense SDK 2.0

參考文章&#xff1a;https://dev.intelrealsense.com/docs/compiling-librealsense-for-linux-ubuntu-guide1、安裝依賴 sudo apt-get update && sudo apt-get upgrade && sudo apt-get dist-upgrade sudo apt-get install libssl-dev libusb-1.0-0-dev libud…

算法學習筆記:9.Kruskal 算法——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在圖論的眾多算法中&#xff0c;Kruskal 算法以其簡潔高效的特性&#xff0c;成為求解最小生成樹&#xff08;Minimum Spanning Tree&#xff0c;MST&#xff09;的經典方法。無論是在通信網絡的優化設計、電路布線的成本控制&#xff0c;還是在計算機考研 408 的備考過程中&am…

Vue+Openlayers加載OSM、加載天地圖

文章目錄1. 介紹2. 加載底圖2.1 加載默認OSM地圖2.2 加載天地圖1. 介紹 Openlayers官網&#xff1a;https://openlayers.org/ 安裝依賴&#xff1a;npm i ol 2. 加載底圖 參考博客&#xff1a; vueopenlayers環境配置&#xff1a;https://blog.csdn.net/cuclife/article/det…

Python處理電子表格文件庫之pyexcel使用詳解

概要 pyexcel是一個功能強大的Python第三方庫,專門用于處理各種格式的電子表格文件。核心價值在于提供了統一的接口來讀取、寫入和操作Excel、CSV、ODS等多種電子表格格式,極大簡化了數據處理工作流程。與傳統的單一格式處理庫不同,pyexcel采用了插件化架構,使開發者能夠通…

【網絡安全】惡意 Python 包“psslib”仿冒 passlib,可導致 Windows 系統關閉

文章目錄惡意 Python 包“psslib”仿冒 passlib如何避免psslib的威脅惡意 Python 包“psslib”仿冒 passlib Socket 的威脅研究團隊發現了一個名為 psslib 的惡意 Python 包&#xff0c;旨在以提供密碼安全功能為幌子突然關閉 Windows 系統。 該軟件包由威脅行為者使用別名 u…

ai之對接電信ds后端服務,通過nginx代理轉發https為http,對外請求,保持到達第三方后請求頭不變

前置環境&#xff1a; 在微信小程序中嵌入H5頁面&#xff08;智能客服&#xff09;&#xff0c;需要讓h5頁面在https的域名服務器上。即通過 nginx 部署成web服務&#xff0c;還得配置域名和端口443訪問。電信的第三方deepseek服務 &#xff0c;只接收http請求&#xff0c;暫未…

第十四節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - Flask 后端 生產部署講解

Vben5 系列文章目錄 ?? 基礎篇 ? 第一節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 ? 第二節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入門 - Python Flask 后端開發詳解(附源碼) ? 第三節:Vben Admin 最新 v5.0 (vben5) + Python Flask 快速入…

Unity開發如何解決iOS閃退問題

一、iOS閃退常見原因及排查方法1. 內存問題&#xff08;最常見原因&#xff09; 癥狀表現&#xff1a; 設備發熱后閃退 加載大型場景時崩潰 控制臺出現EXC_RESOURCE RESOURCE_TYPE_MEMORY日志 解決方案&#xff1a; // 內存監控代碼 void Update() { Debug.Log($"內存使用…

【機器學習筆記 Ⅲ】5 強化學習

強化學習&#xff08;Reinforcement Learning, RL&#xff09; 強化學習是機器學習的一個分支&#xff0c;其核心思想是讓智能體&#xff08;Agent&#xff09;通過與環境&#xff08;Environment&#xff09;的交互學習最優策略&#xff08;Policy&#xff09;&#xff0c;以最…

pytorch深度學習-卷積神經網絡CNN-MNIST-gpu加速

一、為什么需要 CNN&#xff1f;從圖像識別的 “麻煩” 說起假設你想讓電腦識別一張圖片里有沒有貓。 如果用傳統神經網絡&#xff1a;一張 100100 的彩色圖片&#xff0c;有 100100330000 個像素點&#xff0c;每個像素點都是一個輸入神經元。傳統網絡需要每個輸入神經元和隱藏…

【阿里巴巴JAVA開發手冊】IDE的text file encoding設置為UTF-8; IDE中文件的換行符使用Unix格式,不要使用Windows格式。

問題&#xff1a;當使用 IDEA SSH 遠程開發時&#xff0c;SFTP 同步的 Windows 本地編輯的 config/plugin_config 文件文本內容中 “換行符”與 Unix、Linux 的文件文本內容換行符字符集不一致&#xff0c;導致 docker 容器中自定義 /opt/seatunnel/bin/install_plugin 在執行以…

自動駕駛ROS2應用技術詳解

自動駕駛ROS2應用技術詳解 目錄 自動駕駛ROS2節點工作流程自動駕駛感知融合技術詳解多傳感器數據同步技術詳解ROS2多節點協作與自動駕駛系統最小節點集 1. 自動駕駛ROS2節點工作流程 1.1 感知輸出Topic的后續處理 在自動駕駛系統中&#xff0c;感知節點輸出的各種Topic會被…

Redis底層實現原理之訂閱發布機制

文章目錄1. 通知類型2. 實現原理2.1 Pub/Sub2.1.1 基礎知識點2.1.2 頻道和訂閱者的存儲通知原理2.1.3 鍵空間通知2.1.4 客戶端消費2.1.5 缺陷2.2 Redis Stream2.2.1 基礎知識點2.2.2 基礎數據結構2.2.3 消費者組管理2.2.4 消息和消費者持久化2.2.5 消息生產和消費2.2.6 消費者拉…

【MATLAB代碼】AOA與TDOA混合定位例程,自適應基站數量,二維,可調節錨點數量。訂閱專欄后,可直接查看matlab源代碼

本文給出一個matlab代碼,用于在二維平面上,使用AOA的角度測量和TDOA的到達時間差的測量,來達到對未知點的精確定位。最后輸出定位示意圖、真實點坐標、僅AOA定位坐標與誤差、僅TDOA定位的坐標與誤差、AOA+TDOA混合定位的坐標與誤差。訂閱專欄后可直接查看源代碼,粘貼到MATL…

Node.js 所有主要版本的發布時間、穩定版本(Stable)和長期支持版本(LTS) 的整理

以下是 Node.js 所有主要版本的發布時間、穩定版本&#xff08;Stable&#xff09;和長期支持版本&#xff08;LTS&#xff09; 的整理&#xff0c;涵蓋從早期版本到當前最新版本的信息。 &#x1f4c5; Node.js 版本發布規律 每 6 個月發布一個新主版本&#xff08;偶數月&am…

【牛客刷題】小紅的v三元組

文章目錄 一、題目介紹1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 示例二、解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、算法實現四、算法分析4.1 時間復雜度4.2 空間復雜度4.3 正確性證明五、為什么選擇離散化+樹狀數組的解法?5.1 問題本質分析5.2 解法設計思…

c語言學習_函數遞歸

今天學習函數遞歸。函數遞歸通俗來說就是函數自己調用自己&#xff0c;遞歸的主要思考方式在于&#xff1a;把大事化小。例子&#xff1a;接受一個整型值&#xff0c;按照順序打印它的每一位。void print(unsigned int n) {if (n > 9){print(n / 10);}printf("%d"…

Bash與Zsh與Fish:在Linux中你應該使用哪個Shell

命令行 shell 是與操作系統交互的重要工具&#xff0c;使用戶能夠高效地執行命令、自動化任務和運行腳本。 雖然有各種外殼選項可供選擇&#xff0c;但Bash、Zsh和Fish作為最受歡迎的選擇脫穎而出&#xff0c;每種都提供獨特的功能&#xff0c;因此理解它們的差異對于選擇適合…

Peek-Ubuntu上Gif錄制工具-24.04LTS可裝

安裝方法&#xff08;Ubuntu24.04.2LTS測試通過&#xff09; sudo apt update sudo apt install peek純無語&#xff0c;&#x1f9df; 一個軟件&#xff0c;仨網站&#xff0c;四份重復的教程&#xff1a; 添加 PPA更新源報錯&#xff08;不支持 noble&#xff09;搜到 4 篇教…

DVWA靶場通關筆記-驗證碼繞過reCAPTCHA(High級別)

目錄 一、reCAPTCHA 二、代碼審計&#xff08;High級別&#xff09; 1、滲透準備 &#xff08;1&#xff09;配置security為High級別。 &#xff08;2&#xff09;配置RECAPTCHA參數 &#xff08;3&#xff09;再次打開靶場 2、源碼分析 &#xff08;1&#xff09;inde…