在计算机视觉项目中,文件批量操作和文件批量预处理是必不可少的步骤。它们涉及处理大量的图像文件,包括读取、处理、保存和预处理。本文将介绍一些常见的技术和方法,以帮助您在计算机视觉项目中有效地进行文件批量操作和文件批量预处理。
人工智能就是有多少人工产生多少智能,在计算机视觉项目中,数据集至关重要,下面是如何使用视频抽帧技术实现数据集的制作。以下代码中_videoPlay
函数是实时显示导入的视频,CutVideo
函数实现手动抽帧,在显示时按c
键则抽取当前帧,按Esc
键关闭视频。ExtractAll
函数是自动抽帧功能,frameGap
参数是隔多少帧进行自动抽取。
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("文件中已经存在{}张图片,是否有继续添加"
"(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()
将文件夹下的图片进行升序的重命名。
def statistics(path: Union[str, Path], dstpath: Union[Path, str], count: int = 0, random: bool = False) -> None:
"""
这是存放图片的文件夹安升序重命名
:param path:需要重命名的文件文件
:param count:观察图片总数添加使用
"""
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)
下面的是将文件批量按照一定规则挑选出来放到目标文件夹下。
def choosen(src: Union[str, Path] , folder: Union[Path,str] ,dst: Union[str, Path] , suffix: str) -> None:
"""
1.将xml/jpg文件夹中的文件名字拿出来并且在jpg/xml对应的文件夹中将名称相同的文件挑出来
2.将文件夹中的文件随取出
:param xmlsrc:目标xml文件
:param imgsrc:frameImg文件
:param dst:根据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)
下面将文件按照5位数字的格式进行重命名 1.jpg->00001.jpg
。
def batchrenames(src: Union[str, Path], dst: Union[str, Path], sorted: bool = False) -> None:
"""
进行特定格式的重命名
:param src:原文件
:param dst: 存储文件
:param sorted: 是否已经有顺序,若有学按照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
文件内容的代码。
def revampXml(xml_path: Union[Path, str], update_content: str) -> None:
"""
这是一个修改xml文件内容的方法,将xml文件爱中的类别改称另一个类别
:param xml_path: 存放xml文件的路径
:param xml_dw: xpath关键字
:param update_content: 更新的内容
: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":
# 修改标签内容
sub1.text = update_content
# 保存修改
doc.write(xmlfile)
本文介绍了计算机视觉项目中的文件批量操作与文件批量预处理技术。 掌握这些技术将使您能够高效地处理大规模的图像数据,并为计算机视觉项目的成功实施提供强大的支持。
希望本文对您在计算机视觉项目中的文件批量操作与文件批量预处理有所启发!让我们一起推动计算机视觉的发展,创造更多可能性!
以下是完整代码
# -*- 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("文件中已经存在{}张图片,是否有继续添加"
"(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:观察图片总数添加使用
"""
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海上高速目标检测/val", folder: Union[Path,str]="/home/you/Desktop/2023海上高速目标检测/annotations",dst: Union[str, Path]="/home/you/Desktop/2023海上高速目标检测/train", suffix: str=".xml") -> None:
"""
1.将xml/jpg文件夹中的文件名字拿出来并且在jpg/xml对应的文件夹中将名称相同的文件挑出来
2.将文件夹中的文件随取出
:param xmlsrc:目标xml文件
:param imgsrc:frameImg文件
:param dst:根据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:
"""
进行特定格式的重命名
:param src:原文件
:param dst: 存储文件
:param sorted: 是否已经有顺序,若有学按照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文件内容的方法,将xml文件爱中的类别改称另一个类别
:param xml_path: 存放xml文件的路径
:param xml_dw: xpath关键字
:param update_content: 更新的内容
: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":
# 修改标签内容
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: 目标文件夹路径
: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__":
# 目标视频文件
videopath = Path("videoSet/seabird6.mp4")
# 图片保存文件
savepath = Path("./dataset/imgs")
# xin = Path("./VOC6detect/imgss")
# savepath = Path("frameSave")
# 目标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()
# 根据xml文选出对应的文件
# a.choosen(xmlsrc=xmlpath, imgsrc=savepath, dst=xin)
# 将数字命名的图片按照加上一个数字的方式命名
# a.statistics(path=Path("./DATA/xml"), dstpath=Path("./DATA/t"), count=5305)
# 对已经有顺序或者没顺序的文件进行特定格式的重命名78.jpg -> 00078.jpg
# a.batchrenames(src=new, dst=old, sorted=True)
# a.text("./data1.txt")
# 对xml文件进行修改
# a.revampXml(xml_path= "/home/you/Desktop/tools/dataset/annotations", update_content="speedboat")
# 批量拿到文件夹中的某格式的文件
# a.movefile(folder_path="/home/you/Desktop/网上快艇", dst=pa, suffix=".jpg")