本文在ChatGPT 3.5的辅助下对CARPK数据集和PUCPR+数据集进行了预处理,包括划分数据集和将数据集内的框标注转换为点标注。
1 数据集介绍
在简书上找到了它们的下载地址:https://www.jianshu.com/p/f1b32e948136
CARPK数据集和PUCPR+数据集由Hsieh等人[1]在2017年中提出,其中CARPK数据集包含使用无人机拍摄的989张训练图像和459张测试图像,包含89777辆汽车的信息。PUCPR+数据集是原始PUCPR数据集的修订版本,由fxe相机捕获,包含100张训练图像和25张测试图像,共有17000辆汽车信息。上述数据集涉及车辆照明、黑暗程度和背景等方面的显著变化,部分展示图见图1和图2。
图1 CARPK数据集展示
图2 PUCPR+数据集展示
CARPK数据集和PUCPR+数据集内部结构一样,分为三个文件夹Annotations、Images和ImageSets。Annotations存放了各个图像的车辆框标注信息,与图像同名;Images中存放了图像;ImageSets存放了训练集和测试集的图像名,如图3所示。
图3 数据集结构图
2 划分数据集
根据ImageSets里的训练集和测试集信息将对应图片和txt提取出来便可将数据集进行划分。
首先询问ChatGPT:python实现,根据txt里存储的文件名称(无后缀)将一个文件夹中的文件提取到新的文件夹中。
答复如下:
要实现根据txt文件中存储的文件名称(无后缀)将一个文件夹中的文件提取到新的文件夹中,你可以使用Python的shutil库来完成。下面是一个示例代码,假设txt文件中每行包含一个文件名(无后缀),文件夹中的文件也都是以这些文件名命名的。
import os
import shutil
def extract_files(source_folder, destination_folder, txt_file_path):
with open(txt_file_path, 'r') as txt_file:
for line in txt_file:
file_name = line.strip() # Remove newline characters or spaces
source_file_path = os.path.join(source_folder, file_name)
destination_file_path = os.path.join(destination_folder, file_name)
try:
shutil.move(source_file_path, destination_file_path)
print(f"Moved {file_name} to {destination_folder}")
except FileNotFoundError:
print(f"File {file_name} not found in {source_folder}")
except shutil.Error as e:
print(f"Error moving {file_name}: {e}")
# 示例用法
source_folder = '/path/to/source_folder'
destination_folder = '/path/to/destination_folder'
txt_file_path = '/path/to/file_names.txt'
extract_files(source_folder, destination_folder, txt_file_path)
请注意,在运行代码之前,确保替换/path/to/source_folder、/path/to/destination_folder和/path/to/file_names.txt为实际的文件夹路径和txt文件路径。此代码将逐行读取txt文件中的文件名,并将相应的文件从源文件夹移动到目标文件夹。如果文件名对应的文件不存在或移动过程中出现错误,将会显示相应的错误消息。
然后本文根据ChatGPT提供的复制语法实现了将图片和标注文件提取到训练集文件夹和测试集文件夹的语法,详情看注释即可,值得注意的是本文将图片和标注文件分到两个文件夹中了。
# 根据给定的train.txt 和 test.txt提取图片
import os
import shutil
def select_and_copy_images(txt_file, source_folder, destination_folder_img,destination_folder_ann):
# 创建目标文件夹(如果不存在)
if not os.path.exists(destination_folder_img):
os.makedirs(destination_folder_img)
if not os.path.exists(destination_folder_ann):
os.makedirs(destination_folder_ann)
# 读取txt文件中的图片名
with open(txt_file, 'r') as file:
image_names = file.read().splitlines()
# 从源文件夹中选择并复制图片到目标文件夹
for image_name in image_names:
source_path = os.path.join(os.path.join(source_folder,'Images'), image_name+'.png')
print(source_path)
destination_path = os.path.join(destination_folder_img, image_name+'.png')
if os.path.exists(source_path):
shutil.copyfile(source_path, destination_path)
print("已复制图片: "+image_name)
else:
print("找不到图片: "+image_name)
# 从源文件夹中选择并复制标注文件到目标文件夹
for image_name in image_names:
source_path = os.path.join(os.path.join(source_folder,'Annotations'), image_name+'.txt')
print(source_path)
destination_path = os.path.join(destination_folder_ann, image_name+'.txt')
if os.path.exists(source_path):
shutil.copyfile(source_path, destination_path)
print("已复制标注文件: "+image_name)
else:
print("找不到标注文件: "+image_name)
file=['train','test']
for i in file:#遍历训练集和测试集
txt_file = os.path.join(r'/CARPKandPUCPR/CARPK_devkit/data/ImageSets',i+'.txt') # 训练集=测试集txt的存放地址
source_folder = os.path.join(r'/CARPKandPUCPR/CARPK_devkit/data') # 源路径
destination_folder_img = os.path.join(r'/CARPKandPUCPR/CARPK_devkit/data/destination_folder', i,'img') # 目的路径-图片
destination_folder_ann = os.path.join(r'/CARPKandPUCPR/CARPK_devkit/data/destination_folder', i,'ann')# 目的路径-标注文件
select_and_copy_images(txt_file, source_folder, destination_folder_img,destination_folder_ann)
接着需要将训练集划分出验证集,
首先询问ChatGPT:python实现,从第一个图片开始每隔几个文件抽取一个文件并复制到目标文件夹
答复如下:
要实现从第一个图片开始每隔几个文件抽取一个文件并复制到目标文件夹,你可以使用Python的shutil库来进行文件复制。下面是一个示例代码:
import os
import shutil
def extract_images_with_interval(source_folder, destination_folder, interval):
file_list = sorted(os.listdir(source_folder)) # 获取源文件夹中的所有文件,并按名称排序
for i in range(0, len(file_list), interval):
source_file_path = os.path.join(source_folder, file_list[i])
destination_file_path = os.path.join(destination_folder, file_list[i])
try:
shutil.copyfile(source_file_path, destination_file_path)
print(f"Copied {file_list[i]} to {destination_folder}")
except FileNotFoundError:
print(f"File {file_list[i]} not found in {source_folder}")
except shutil.Error as e:
print(f"Error copying {file_list[i]}: {e}")
# 示例用法
source_folder = '/path/to/source_folder'
destination_folder = '/path/to/destination_folder'
interval = 3 # 设置复制间隔为3个文件
extract_images_with_interval(source_folder, destination_folder, interval)
请注意,在运行代码之前,确保替换/path/to/source_folder和/path/to/destination_folder为实际的文件夹路径,并根据需要设置复制的间隔数(interval)。此代码将从源文件夹中按照指定的间隔抽取图片并复制到目标文件夹,并在控制台上显示复制的文件名。例如,如果设置间隔为3,那么代码将从第一个文件开始,每隔两个文件复制一个文件到目标文件夹。
这上面提供的语法已经很完善了,根据具体情况可以具体处理,本文根据此实现了将文件夹中的图片抽取一部分到另一个文件夹中。
# 根据一定间隔提取图片
import os
import shutil
def extract_images(source_folder, destination_folder, interval):
# 创建目标文件夹(如果不存在)
if not os.path.exists(destination_folder):
os.makedirs(destination_folder)
# 获取源文件夹中的所有图片文件,并按文件名排序
image_files = sorted([file for file in os.listdir(source_folder) if file.endswith('.jpg') or file.endswith('.png')])
# 从第一个图片开始每隔一定间隔抽取图片并复制到目标文件夹
for i in range(0, len(image_files), interval):
image_name = image_files[i]
source_path = os.path.join(source_folder, image_name)
destination_path = os.path.join(destination_folder, image_name)
shutil.copyfile(source_path, destination_path)
# os.remove(source_path) #删除源图片
source_folder = r'Images' # 源图片所在文件夹路径
destination_folder = r'valImages' # 抽取后存储图片的目标文件夹路径
interval = 10 # 抽取间隔
extract_images(source_folder, destination_folder, interval)```
3 将数据集中的框标注转换为点标注
首先确认框标注文件的格式,根据官方源码可知,标注文件的格式是x1 y1 x2 y2,对应着框的左上角坐标和右下角坐标。
##------------------官方代码:部分----------------------
for idx, obj in enumerate(objs):
info = re.findall('\d+', obj)
x1 = float(info[0])
y1 = float(info[1])
x2 = float(info[2])
y2 = float(info[3])
gtBBs[idx, :] = [x1, y1, x2, y2]
##------------------官方代码:部分----------------------
然后
询问ChatGPT:将一个文件夹中的框标注文件转换为点标注文件并转移到新的文件夹中。其中框标注文件是.txt后缀,每一个框标注文件含有多行x1 y1 x2 y2信息,对应着框的左上角坐标和右下角坐标。
答复如下:
import os
import shutil
def convert_bbox_to_points(bbox_file_path):
# 读取框标注文件
with open(bbox_file_path, 'r') as file:
lines = file.readlines()
points = []
for line in lines:
# 解析x1 y1 x2 y2信息并计算框的中心点坐标
x1, y1, x2, y2 = map(int, line.strip().split())
center_x = (x1 + x2) // 2
center_y = (y1 + y2) // 2
points.append((center_x, center_y))
return points
def main():
# 原始文件夹路径和目标文件夹路径
source_folder = 'path/to/source_folder'
destination_folder = 'path/to/destination_folder'
# 创建目标文件夹(如果不存在)
if not os.path.exists(destination_folder):
os.makedirs(destination_folder)
# 遍历原始文件夹中的所有框标注文件
for filename in os.listdir(source_folder):
if filename.endswith('.txt'):
# 构建完整路径
bbox_file_path = os.path.join(source_folder, filename)
# 将框标注文件转换为点标注列表
points = convert_bbox_to_points(bbox_file_path)
# 构建新的点标注文件名
point_file_name = filename
# 构建新的点标注文件路径
point_file_path = os.path.join(destination_folder, point_file_name)
# 将点标注写入新的文件
with open(point_file_path, 'w') as point_file:
for point in points:
point_file.write(f"{point[0]} {point[1]}\n")
# 移动原始框标注文件到目标文件夹
shutil.move(bbox_file_path, os.path.join(destination_folder, filename))
if __name__ == "__main__":
main()
本文感觉这里给的不太对,就自己重写了一份:
import cv2
import numpy as np
import os
import re
import argparse
from PIL import Image
import scipy
def changeLine(lines,w,h):
lines = lines.split(' ')
x1 = int(lines[0])
y1 = int(lines[1])
x2 = int(lines[2])
y2 = int(lines[3])
Kx = (x1+x2)/2
ky = (y1+y2)/2
return str( 1 ) +' ' + str(Kx/w) +' ' + str(ky/h) + ' \n'
txt_data = r'/data/txttxt' # 保存为所需的yolo标注文件
ann_data = r'/data/Annotations' # 框标注文件路径
files = os.listdir(ann_data)
for file in files:
ann_path = os.path.join(ann_data,file)
img_path = ann_path.replace('Annotations','Images').replace('.txt','.jpg')
img = cv2.imread(img_path, 1)
h,w = img.shape[0],img.shape[1]
ann = open(ann_path, encoding='utf-8')
annLines = ann.readlines()
result = []
for lines in annLines:
resultL = changeLine(lines,w,h) #这里计算出点坐标相对图像长宽的比例信息。
result.append(resultL)
print(result)
#result里存储着需要另存的txt文件
with open(os.path.join(txt_data, file), 'w') as f:
f.writelines(result)
转换后的点标注格式如下:
至此,对CARPK数据集和PUCPR+数据集的预处理操作就此结束。
[1] Meng-RuHsieh,Yen-LiangLin,WinstonH.Hsu.Drone-based Object Counting by Spatially Regularized Regional Proposal Networks , ICCV2017