數(shù)據(jù)集制作的工具箱
目錄
- 環(huán)境準(zhǔn)備
- 數(shù)據(jù)集制作
- 文件批量重命名
- 文件批量移動
- 將文件批量按照一定格式進(jìn)行重命名
- 修改xml文件內(nèi)容的方法
- Pathlib庫的常用接口
引言
在計算機(jī)視覺項目中,文件批量操作和文件批量預(yù)處理是必不可少的步驟。它們涉及處理大量的圖像文件,包括讀取、處理、保存和預(yù)處理。本文將介紹一些常見的技術(shù)和方法,以幫助您在計算機(jī)視覺項目中有效地進(jìn)行文件批量操作和文件批量預(yù)處理。
環(huán)境準(zhǔn)備
from pathlib import Path, PurePath
import xml.etree.ElementTree as ET
from typing import Union
import numpy as np
from tqdm import tqdm
import time
import cv2
import os
數(shù)據(jù)集制作
人工智能就是有多少人工產(chǎn)生多少智能,在計算機(jī)視覺項目中,數(shù)據(jù)集至關(guān)重要,下面是如何使用視頻抽幀技術(shù)實現(xiàn)數(shù)據(jù)集的制作。以下代碼中_videoPlay
函數(shù)是實時顯示導(dǎo)入的視頻,CutVideo
函數(shù)實現(xiàn)手動抽幀,在顯示時按c
鍵則抽取當(dāng)前幀,按Esc
鍵關(guān)閉視頻。ExtractAll
函數(shù)是自動抽幀功能,frameGap
參數(shù)是隔多少幀進(jìn)行自動抽取。
class ExtractImg(object):
def __init__(self, videopath: Path, savepath: Path, delay: int = 1) -> None:
self.spath = savepath
self.vpath = videopath
self.delay = delay
cv2.namedWindow("cv", cv2.WINDOW_NORMAL)
cv2.resizeWindow("cv", 640, 480)
self.cap = cv2.VideoCapture(str(self.vpath))
self._timeflag = 0
if not savepath.exists():
os.mkdir(Path(savepath))
def _videoPlay(self, size: list) -> None:
self.cap.set(3, size[0])
self.cap.set(4, size[1])
while self.cap.isOpened():
ret, frame = self.cap.read()
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cv2.imshow("cv", frame)
if cv2.waitKey(self.delay) & 0xFF == ord('c'):
cv2.imwrite(str(PurePath.joinpath(self.spath,
"{}.jpg".format(str(time.time())))), frame)
print("保存成功")
time.sleep(1)
elif cv2.waitKey(self.delay) & 0xFF == 27:
break
def ExtractAll(self, frameGap: int = 3) -> None:
"""
這是將視頻流中的幀全部抽出
:frame: 跳幀
:return:
"""
while self.cap.isOpened():
self._timeflag += 1
ret, frame = self.cap.read()
if ret:
cv2.imshow("cv", frame)
if self._timeflag % frameGap == 0:
cv2.imwrite(str(PurePath.joinpath(self.spath,
"{}.jpg".format(str(time.time())))), frame)
print("保存成功")
if (cv2.waitKey(self.delay) & 0xFF == 27) or not ret:
break
cv2.destroyAllWindows()
self.cap.release()
self._timeflag = 0
def CutVideo(self) -> None:
"""
這是手動抽幀
:return:
"""
ifm = input("文件中已經(jīng)存在{}張圖片,是否有繼續(xù)添加"
"(Y or N):".format(len(os.listdir(self.spath))))
if self.spath.exists() and ifm == 'Y':
self._videoPlay(size=[640, 480])
elif self.spath.exists() and ifm == 'N':
return None
else:
print("\n請輸入Y(yes)或者N(no)")
cv2.destroyAllWindows()
self.cap.release()
文件批量重命名
將文件夾下的圖片進(jìn)行升序的重命名。
def statistics(path: Union[str, Path], dstpath: Union[Path, str], count: int = 0, random: bool = False) -> None:
"""
這是存放圖片的文件夾安升序重命名
:param path:需要重命名的文件文件
:param count:觀察圖片總數(shù)添加使用
"""
assert isinstance(path, (Path, str)), print("請輸入的路徑")
l = os.listdir(str(path))
if not Path.exists(dstpath):
Path.mkdir(dstpath)
# l = sorted(l)
print(l)
# print(l)
print("存在文件{}張!".format(len(l)))
if random:
np.random.shuffle(l)
# print(l)
# 將保存圖片文件中的圖片按照升序的方法重命名
suffix = Path(l[0]).suffix
for file in tqdm(l):
src = PurePath.joinpath(path, file)
dst = PurePath.joinpath(dstpath, Path(str(count + int(Path(file).stem))).with_suffix(suffix))
os.rename(src, dst)
文件批量移動
下面的是將文件批量按照一定規(guī)則挑選出來放到目標(biāo)文件夾下。
def choosen(src: Union[str, Path] , folder: Union[Path,str] ,dst: Union[str, Path] , suffix: str) -> None:
"""
1.將xml/jpg文件夾中的文件名字拿出來并且在jpg/xml對應(yīng)的文件夾中將名稱相同的文件挑出來
2.將文件夾中的文件隨取出
:param xmlsrc:目標(biāo)xml文件
:param imgsrc:frameImg文件
:param dst:根據(jù)xml挑選出的img文件
:return: None
"""
# l = os.listdir(str(xmlsrc))
if not isinstance(folder,Path):
pa = Path(folder)
if not isinstance(src,Path):
l = Path(src)
# parent = src.parent
for i in l.iterdir():
file = Path(i.name).with_suffix(suffix)
(pa / file).rename(Path(dst) / file)
將文件批量按照一定格式進(jìn)行重命名
下面將文件按照5位數(shù)字的格式進(jìn)行重命名 1.jpg->00001.jpg
。
def batchrenames(src: Union[str, Path], dst: Union[str, Path], sorted: bool = False) -> None:
"""
進(jìn)行特定格式的重命名
:param src:原文件
:param dst: 存儲文件
:param sorted: 是否已經(jīng)有順序,若有學(xué)按照1.jpg ->00001.jpg
:return: None
"""
d = {1: "0000", # 這是命名格式的字典
2: "000",
3: "00",
4: "0",
5: ""}
l = os.listdir(src)
suffix = Path(l[0]).suffix
l.sort(key=lambda x: int(x.split('.')[0]))
if sorted:
for obj in tqdm(l):
old = PurePath.joinpath(src, obj)
new = PurePath.joinpath(dst, d[len(obj.split('.')[0])] + obj.split('.')[0] + suffix)
os.rename(old, new)
else:
# for c, i in tqdm(enumerate(l)):
pass
修改xml文件內(nèi)容的方法
這是修改xml
文件內(nèi)容的代碼。
def revampXml(xml_path: Union[Path, str], update_content: str) -> None:
"""
這是一個修改xml文件內(nèi)容的方法,將xml文件愛中的類別改稱另一個類別
:param xml_path: 存放xml文件的路徑
:param xml_dw: xpath關(guān)鍵字
:param update_content: 更新的內(nèi)容
:return:None
"""
# 打開xml文檔
if not isinstance(xml_path, Path):
xml_path = Path(xml_path)
for i in tqdm(xml_path.iterdir()):
xmlfile = xml_path / f"{i}"
doc = ET.parse(xmlfile)
root = doc.getroot()
# 查找修改路勁
for obj in root.iter("object"):
sub1 = obj.find("name")
if sub1.text == "motorboat":
# 修改標(biāo)簽內(nèi)容
sub1.text = update_content
# 保存修改
doc.write(xmlfile)
Pathlib庫以及os庫的常用文件操作API
pathlib是 標(biāo)準(zhǔn)庫之一,用于操作文件系統(tǒng)路徑。該庫可以方便地進(jìn)行路徑的拼接、文件/目錄的創(chuàng)建、復(fù)制/移動、刪除等操作。
功能描述 | pathlib操作 | os及os.path操作 |
---|---|---|
獲得絕對路徑 | Path.resolve() | os.path.abspath() |
修改文件權(quán)限和時間戳 | Path.chmod() | os.chmod() |
創(chuàng)建目錄 | Path.mkdir() | os.mkdir() |
文件或文件夾重命名,如果路徑不同,會移動并重新命名 | Path.rename() | os.rename() |
文件或文件夾重命名,如果路徑不同,會移動并重新命名,如果存在,則破壞現(xiàn)有目標(biāo) | Path.replace() | os.replace() |
刪除目錄 | Path.rmdir() | os.rmdir() |
刪除一個文件 | Path.unlink() | os.remove() |
刪除一個文件 | Path.unlink() | os.unlink() |
獲得當(dāng)前工作目錄 | Path.cwd() | os.getcwd() |
判斷是否存在文件或目錄name | Path.exists() | os.path.exists() |
返回電腦的用戶目錄 | Path.home() | os.path.expanduser() |
檢驗給出的路徑是一個文件 | Path.is_dir() | os.path.isdir() |
檢驗給出的路徑是一個目錄 | Path.is_file() | os.path.isfile() |
檢驗給出的路徑是一個符號鏈接 | Path.is_symlink() | os.path.islink() |
獲得文件屬性 | Path.stat() | os.stat() |
判斷是否為絕對路徑 | PurePath.is_absolute() | os.path.isabs() |
連接目錄與文件名或目錄 | PurePath.joinpath() | os.path.join() |
返回文件名 | PurePath.name | os.path.basename() |
返回文件路徑 | PurePath.parent | os.path.dirname() |
判斷兩個路徑是否相同 | Path.samefile() | os.path.samefile() |
分離文件名和擴(kuò)展名 | PurePath.suffix | os.path.splitext() |
總結(jié)
本文介紹了計算機(jī)視覺項目中的文件批量操作與文件批量預(yù)處理技術(shù)。 掌握這些技術(shù)將使您能夠高效地處理大規(guī)模的圖像數(shù)據(jù),并為計算機(jī)視覺項目的成功實施提供強(qiáng)大的支持。
希望本文對您在計算機(jī)視覺項目中的文件批量操作與文件批量預(yù)處理有所啟發(fā)!文章來源:http://www.zghlxwxcb.cn/news/detail-697055.html
以下是完整代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-697055.html
# -*- coding: utf-8 -*-
# @Author : cvYouTian
# @Software: PyCharm
from pathlib import Path, PurePath
import xml.etree.ElementTree as ET
from typing import Union
import numpy as np
# import torch
from tqdm import tqdm
import time
import cv2
import os
class ExtractImg(object):
def __init__(self, videopath: Path, savepath: Path, delay: int = 1) -> None:
self.spath = savepath
self.vpath = videopath
self.delay = delay
cv2.namedWindow("cv", cv2.WINDOW_NORMAL)
cv2.resizeWindow("cv", 640, 480)
self.cap = cv2.VideoCapture(str(self.vpath))
self._timeflag = 0
if not savepath.exists():
os.mkdir(Path(savepath))
def _videoPlay(self, size: list) -> None:
self.cap.set(3, size[0])
self.cap.set(4, size[1])
while self.cap.isOpened():
ret, frame = self.cap.read()
# frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cv2.imshow("cv", frame)
if cv2.waitKey(self.delay) & 0xFF == ord('c'):
cv2.imwrite(str(PurePath.joinpath(self.spath,
"{}.jpg".format(str(time.time())))), frame)
print("保存成功")
time.sleep(1)
elif cv2.waitKey(self.delay) & 0xFF == 27:
break
def ExtractAll(self, frameGap: int = 3) -> None:
"""
這是將視頻流中的幀全部抽出
:frame: 跳幀
:return:
"""
while self.cap.isOpened():
self._timeflag += 1
ret, frame = self.cap.read()
if ret:
cv2.imshow("cv", frame)
if self._timeflag % frameGap == 0:
cv2.imwrite(str(PurePath.joinpath(self.spath,
"{}.jpg".format(str(time.time())))), frame)
print("保存成功")
if (cv2.waitKey(self.delay) & 0xFF == 27) or not ret:
break
cv2.destroyAllWindows()
self.cap.release()
self._timeflag = 0
def CutVideo(self) -> None:
"""
這是手動抽幀
:return:
"""
ifm = input("文件中已經(jīng)存在{}張圖片,是否有繼續(xù)添加"
"(Y or N):".format(len(os.listdir(self.spath))))
if self.spath.exists() and ifm == 'Y':
self._videoPlay(size=[640, 480])
elif self.spath.exists() and ifm == 'N':
return None
else:
print("\n請輸入Y(yes)或者N(no)")
cv2.destroyAllWindows()
self.cap.release()
@staticmethod
def statistics(path: Union[str, Path], dstpath: Union[Path, str], count: int = 5305, random: bool = False) -> None:
"""
這是存放圖片的文件夾安升序重命名
:param path:需要重命名的文件文件
:param count:觀察圖片總數(shù)添加使用
"""
assert isinstance(path, (Path, str)), print("請輸入的路徑")
l = os.listdir(str(path))
if not Path.exists(dstpath):
Path.mkdir(dstpath)
# l = sorted(l)
print(l)
# print(l)
print("存在文件{}張!".format(len(l)))
if random:
np.random.shuffle(l)
# print(l)
# 將保存圖片文件中的圖片按照升序的方法重命名
suffix = Path(l[0]).suffix
for file in tqdm(l):
src = PurePath.joinpath(path, file)
dst = PurePath.joinpath(dstpath, Path(str(count + int(Path(file).stem))).with_suffix(suffix))
os.rename(src, dst)
@staticmethod
def choosen(src: Union[str, Path]="/home/you/Desktop/2023海上高速目標(biāo)檢測/val", folder: Union[Path,str]="/home/you/Desktop/2023海上高速目標(biāo)檢測/annotations",dst: Union[str, Path]="/home/you/Desktop/2023海上高速目標(biāo)檢測/train", suffix: str=".xml") -> None:
"""
1.將xml/jpg文件夾中的文件名字拿出來并且在jpg/xml對應(yīng)的文件夾中將名稱相同的文件挑出來
2.將文件夾中的文件隨取出
:param xmlsrc:目標(biāo)xml文件
:param imgsrc:frameImg文件
:param dst:根據(jù)xml挑選出的img文件
:return: None
"""
# l = os.listdir(str(xmlsrc))
if not isinstance(folder,Path):
pa = Path(folder)
if not isinstance(src,Path):
l = Path(src)
# parent = src.parent
for i in l.iterdir():
file = Path(i.name).with_suffix(suffix)
(pa / file).rename(Path(dst) / file)
@staticmethod
def batchrenames(src: Union[str, Path], dst: Union[str, Path], sorted: bool = False) -> None:
"""
進(jìn)行特定格式的重命名
:param src:原文件
:param dst: 存儲文件
:param sorted: 是否已經(jīng)有順序,若有學(xué)按照1.jpg ->00001.jpg
:return: None
"""
d = {1: "0000", # 這是命名格式的字典
2: "000",
3: "00",
4: "0",
5: ""}
l = os.listdir(src)
suffix = Path(l[0]).suffix
l.sort(key=lambda x: int(x.split('.')[0]))
if sorted:
for obj in tqdm(l):
old = PurePath.joinpath(src, obj)
new = PurePath.joinpath(dst, d[len(obj.split('.')[0])] + obj.split('.')[0] + suffix)
os.rename(old, new)
else:
# for c, i in tqdm(enumerate(l)):
pass
@staticmethod
def text(file: Union[Path, str]):
l = []
f = open(file)
for i in f.readlines():
i = i.strip()
stem = Path(i).stem
suffix = Path(i).suffix
n1, n2 = int(stem) - 1, int(stem) + 1
l.append(str(n1) + ".xml")
l.append(str(n2) + ".xml")
print(l)
@staticmethod
def revampXml(xml_path: Union[Path, str], update_content: str) -> None:
"""
這是一個修改xml文件內(nèi)容的方法,將xml文件愛中的類別改稱另一個類別
:param xml_path: 存放xml文件的路徑
:param xml_dw: xpath關(guān)鍵字
:param update_content: 更新的內(nèi)容
:return:None
"""
# 打開xml文檔
if not isinstance(xml_path, Path):
xml_path = Path(xml_path)
for i in tqdm(xml_path.iterdir()):
xmlfile = xml_path / f"{i}"
doc = ET.parse(xmlfile)
root = doc.getroot()
# 查找修改路勁
for obj in root.iter("object"):
sub1 = obj.find("name")
if sub1.text == "motorboat":
# 修改標(biāo)簽內(nèi)容
sub1.text = update_content
# 保存修改
doc.write(xmlfile)
@staticmethod
def movefile(folder_path: Union[Path, str], dst: Union[Path, str], suffix: str) -> None:
"""
批量移動剪切文件
:param folder_path: 原文件夾路徑
:param dst: 目標(biāo)文件夾路徑
:param suffix: 移動的文件格式/后綴
:return:
"""
if not isinstance(folder_path, Path):
folder_path = Path(folder_path)
# for i in folder_path.iterdir():
# if i.is_dir():
# ExtractImg.movefile(folder_path / i, suffix, res)
# else:
# if i.suffix == suffix:
# res.append(str(i))
# # return res if suffix is None or suffix == "" else list(filter(lambda x: str(x).endswith(suffix),res))
# return res
for i in tqdm(folder_path.rglob(f"*{suffix}")):
i.rename(dst / i.name)
@staticmethod
def convert_box(size, box):
dw, dh = 1. / size[0], 1. / size[1]
x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2]
return x * dw, y * dh, w * dw, h * dh
if __name__ == "__main__":
# 目標(biāo)視頻文件
videopath = Path("videoSet/seabird6.mp4")
# 圖片保存文件
savepath = Path("./dataset/imgs")
# xin = Path("./VOC6detect/imgss")
# savepath = Path("frameSave")
# 目標(biāo)xml文件
# xmlpath = Path("./VOC6detect/annotations")
# old = Path("/home/you/Desktop/dateset/20(pass)/seabird5")
# new = Path("/home/you/Desktop/dateset/11(pass)/temp")
# pa = Path("./labels/")
# xin = Path()
# renamepath = Path("/home/you/Desktop/dateset/4(pass)/a-1")
# 實例化
a = ExtractImg(videopath=videopath, savepath=savepath)
a.choosen()
# VOC2YOLO
# a.convert_label()
# 將幀全部抽出
# a.ExtractAll(frameGap=8)
# 手動抽幀
# a.CutVideo()
# 根據(jù)xml文選出對應(yīng)的文件
# a.choosen(xmlsrc=xmlpath, imgsrc=savepath, dst=xin)
# 將數(shù)字命名的圖片按照加上一個數(shù)字的方式命名
# a.statistics(path=Path("./DATA/xml"), dstpath=Path("./DATA/t"), count=5305)
# 對已經(jīng)有順序或者沒順序的文件進(jìn)行特定格式的重命名78.jpg -> 00078.jpg
# a.batchrenames(src=new, dst=old, sorted=True)
# a.text("./data1.txt")
# 對xml文件進(jìn)行修改
# a.revampXml(xml_path= "/home/you/Desktop/tools/dataset/annotations", update_content="speedboat")
# 批量拿到文件夾中的某格式的文件
# a.movefile(folder_path="/home/you/Desktop/網(wǎng)上快艇", dst=pa, suffix=".jpg")
到了這里,關(guān)于python實現(xiàn)視頻抽幀,文件批量操作,文件批量處理(數(shù)據(jù)集制作的工具箱)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!