三维重构终版
65
OpenCV/convert_jpeg_to_jpg.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import os
|
||||
from PIL import Image
|
||||
from tqdm import tqdm
|
||||
|
||||
# --- 配置 ---
|
||||
# 1. 设置您的图片文件夹路径
|
||||
# 根据您的项目结构,这个路径应该是 'VOCdevkit/VOC2007/JPEGImages'
|
||||
image_folder = '../label/up'
|
||||
|
||||
# 2. 是否删除转换后的原始 .jpeg 文件
|
||||
delete_original = True
|
||||
|
||||
|
||||
# --- 配置结束 ---
|
||||
|
||||
|
||||
def convert_jpeg_to_jpg(folder_path, delete_original_file=True):
|
||||
"""
|
||||
将指定文件夹内的 .jpeg 图片转换为 .jpg 格式。
|
||||
|
||||
:param folder_path: 包含图片的文件夹路径。
|
||||
:param delete_original_file: 是否删除原始的 .jpeg 文件。
|
||||
"""
|
||||
if not os.path.isdir(folder_path):
|
||||
print(f"错误:文件夹 '{folder_path}' 不存在。")
|
||||
return
|
||||
|
||||
# 找出所有.jpeg或.JPEG结尾的文件
|
||||
jpeg_files = [f for f in os.listdir(folder_path) if f.lower().endswith('.jpeg')]
|
||||
|
||||
if not jpeg_files:
|
||||
print(f"在 '{folder_path}' 中没有找到 .jpeg 文件。")
|
||||
return
|
||||
|
||||
print(f"找到 {len(jpeg_files)} 个 .jpeg 文件,开始转换...")
|
||||
|
||||
for filename in tqdm(jpeg_files, desc="转换进度"):
|
||||
jpeg_path = os.path.join(folder_path, filename)
|
||||
|
||||
# 构建新的 .jpg 文件名
|
||||
base_name = os.path.splitext(filename)[0]
|
||||
jpg_filename = f"{base_name}.jpg"
|
||||
jpg_path = os.path.join(folder_path, jpg_filename)
|
||||
|
||||
try:
|
||||
with Image.open(jpeg_path) as img:
|
||||
# 确保图像是RGB模式,因为JPG不支持透明度
|
||||
if img.mode != 'RGB':
|
||||
img = img.convert('RGB')
|
||||
|
||||
# 以高质量保存为 .jpg
|
||||
img.save(jpg_path, 'jpeg', quality=95)
|
||||
|
||||
# 如果转换成功且设置为删除,则删除原始文件
|
||||
if delete_original_file:
|
||||
os.remove(jpeg_path)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n处理文件 '{filename}' 时出错: {e}")
|
||||
|
||||
print("\n转换完成!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
convert_jpeg_to_jpg(image_folder, delete_original)
|
||||
192
OpenCV/convert_to_voc.py
Normal file
@@ -0,0 +1,192 @@
|
||||
import os
|
||||
import json
|
||||
import xml.etree.ElementTree as ET
|
||||
from xml.dom import minidom
|
||||
from tqdm import tqdm
|
||||
import re # 引入正则表达式库
|
||||
|
||||
# --- 配置参数 ---
|
||||
# 1. 原始JSON文件所在的文件夹路径
|
||||
json_folder = '../label/up_json' # 示例路径,请修改为您的JSON文件夹
|
||||
|
||||
# 2. 原始图片文件所在的文件夹路径 (用于获取图片尺寸)
|
||||
image_folder = '../label/up' # 示例路径,请修改为您的图片文件夹
|
||||
|
||||
# 3. 生成的XML文件要保存的文件夹路径
|
||||
output_xml_folder = '../label/up_xml'
|
||||
|
||||
# 4. 您要检测的目标类别名称 (对应 label "3")
|
||||
class_name_for_label_3 = "Space weld workpiece" # 这是您XML示例中的名称
|
||||
|
||||
# 5. 分组的大小
|
||||
group_size = 5
|
||||
|
||||
|
||||
# --- 配置结束 ---
|
||||
|
||||
|
||||
def create_xml_annotation(image_info, objects_info):
|
||||
"""
|
||||
根据传入的信息生成XML树对象
|
||||
:param image_info: 包含图片文件名、尺寸等信息的字典
|
||||
:param objects_info: 包含多个物体信息的列表,每个物体是一个字典
|
||||
:return: XML ElementTree对象
|
||||
"""
|
||||
# 创建根节点
|
||||
annotation = ET.Element('annotation')
|
||||
|
||||
# 子节点 - folder
|
||||
folder = ET.SubElement(annotation, 'folder')
|
||||
folder.text = 'JPEGImages'
|
||||
|
||||
# 子节点 - filename
|
||||
filename_node = ET.SubElement(annotation, 'filename')
|
||||
filename_node.text = image_info['filename']
|
||||
|
||||
# 子节点 - path (路径通常不那么重要,但最好有一个)
|
||||
path = ET.SubElement(annotation, 'path')
|
||||
# 路径指向JPEGImages文件夹
|
||||
image_path_in_voc = os.path.join('..', 'JPEGImages', image_info['filename'])
|
||||
path.text = image_path_in_voc
|
||||
|
||||
# 子节点 - source
|
||||
source = ET.SubElement(annotation, 'source')
|
||||
database = ET.SubElement(source, 'database')
|
||||
database.text = 'Unknown'
|
||||
|
||||
# 子节点 - size
|
||||
size = ET.SubElement(annotation, 'size')
|
||||
width = ET.SubElement(size, 'width')
|
||||
width.text = str(image_info['width'])
|
||||
height = ET.SubElement(size, 'height')
|
||||
height.text = str(image_info['height'])
|
||||
depth = ET.SubElement(size, 'depth')
|
||||
depth.text = str(image_info.get('depth', 3))
|
||||
|
||||
# 子节点 - segmented
|
||||
segmented = ET.SubElement(annotation, 'segmented')
|
||||
segmented.text = '0'
|
||||
|
||||
# 为每个物体添加 object 节点
|
||||
for obj in objects_info:
|
||||
object_node = ET.SubElement(annotation, 'object')
|
||||
name = ET.SubElement(object_node, 'name')
|
||||
name.text = obj['name']
|
||||
pose = ET.SubElement(object_node, 'pose')
|
||||
pose.text = 'Unspecified'
|
||||
truncated = ET.SubElement(object_node, 'truncated')
|
||||
truncated.text = '0'
|
||||
difficult = ET.SubElement(object_node, 'difficult')
|
||||
difficult.text = '0'
|
||||
bndbox = ET.SubElement(object_node, 'bndbox')
|
||||
xmin = ET.SubElement(bndbox, 'xmin')
|
||||
xmin.text = str(int(obj['xmin']))
|
||||
ymin = ET.SubElement(bndbox, 'ymin')
|
||||
ymin.text = str(int(obj['ymin']))
|
||||
xmax = ET.SubElement(bndbox, 'xmax')
|
||||
xmax.text = str(int(obj['xmax']))
|
||||
ymax = ET.SubElement(bndbox, 'ymax')
|
||||
ymax.text = str(int(obj['ymax']))
|
||||
|
||||
return annotation
|
||||
|
||||
|
||||
def prettify_xml(elem):
|
||||
"""
|
||||
格式化XML输出,使其更易读
|
||||
"""
|
||||
rough_string = ET.tostring(elem, 'utf-8')
|
||||
reparsed = minidom.parseString(rough_string)
|
||||
return reparsed.toprettyxml(indent=" ")
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists(output_xml_folder):
|
||||
os.makedirs(output_xml_folder)
|
||||
print(f"创建输出文件夹: {output_xml_folder}")
|
||||
|
||||
json_files = sorted([f for f in os.listdir(json_folder) if f.endswith('.json')])
|
||||
|
||||
print(f"找到 {len(json_files)} 个JSON文件,开始转换...")
|
||||
|
||||
for json_file in tqdm(json_files, desc="处理JSON文件"):
|
||||
base_name = os.path.splitext(json_file)[0]
|
||||
|
||||
# 使用正则表达式匹配前缀和数字
|
||||
match = re.match(r'([a-zA-Z]+)(\d+)', base_name)
|
||||
|
||||
# 1. 检查当前文件是否是一个分组的起始文件
|
||||
is_group_start_file = False
|
||||
if match:
|
||||
num = int(match.group(2))
|
||||
# 如果数字是 1, 6, 11, ... 这样的,就认为是起始文件
|
||||
if (num - 1) % group_size == 0:
|
||||
is_group_start_file = True
|
||||
else:
|
||||
# 如果文件名不符合 l1, r5 这种格式,我们认为它是“普通”文件,自己就是一个组
|
||||
is_group_start_file = True
|
||||
|
||||
if not is_group_start_file:
|
||||
# 如果不是起始文件(如l2, l3...),则跳过,因为它的标注已由l1处理
|
||||
continue
|
||||
|
||||
# --- 是起始文件,处理这个分组 ---
|
||||
json_path = os.path.join(json_folder, json_file)
|
||||
|
||||
with open(json_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
# 2. 从起始文件中提取所有符合条件的标注对象
|
||||
objects_to_write = []
|
||||
for shape in data.get('shapes', []):
|
||||
if shape.get('label') == '1' and shape.get('shape_type') == 'rectangle':
|
||||
points = shape.get('points', [])
|
||||
if len(points) == 2:
|
||||
x_coords = sorted([p[0] for p in points])
|
||||
y_coords = sorted([p[1] for p in points])
|
||||
objects_to_write.append({
|
||||
'name': class_name_for_label_3,
|
||||
'xmin': x_coords[0], 'ymin': y_coords[0],
|
||||
'xmax': x_coords[1], 'ymax': y_coords[1],
|
||||
})
|
||||
|
||||
if not objects_to_write:
|
||||
continue
|
||||
|
||||
# 3. 确定该标注要应用到哪些图片上
|
||||
target_image_names = []
|
||||
if match:
|
||||
# 文件名符合 l1, r6 等格式
|
||||
prefix = match.group(1)
|
||||
start_num = int(match.group(2))
|
||||
for i in range(group_size):
|
||||
# 假设图片格式为 .jpg
|
||||
target_image_names.append(f"{prefix}{start_num + i}.jpg")
|
||||
else:
|
||||
# 普通文件,只应用到同名文件
|
||||
# 假设图片格式为 .jpg
|
||||
target_image_names.append(f"{base_name}.jpg")
|
||||
|
||||
# 4. 为分组内的每个目标图片生成XML文件
|
||||
for image_name in target_image_names:
|
||||
image_path = os.path.join(image_folder, image_name)
|
||||
if not os.path.exists(image_path):
|
||||
print(f"\n警告:找不到图片 '{image_name}',跳过生成其XML文件。")
|
||||
continue
|
||||
|
||||
# 使用JSON中的尺寸信息
|
||||
image_info = {'filename': image_name, 'width': data['imageWidth'], 'height': data['imageHeight']}
|
||||
|
||||
xml_tree = create_xml_annotation(image_info, objects_to_write)
|
||||
xml_string = prettify_xml(xml_tree)
|
||||
xml_filename = os.path.splitext(image_name)[0] + '.xml'
|
||||
output_path = os.path.join(output_xml_folder, xml_filename)
|
||||
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
f.write(xml_string)
|
||||
|
||||
print("转换完成!所有XML文件已保存在: ", output_xml_folder)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
Before Width: | Height: | Size: 424 KiB |
|
Before Width: | Height: | Size: 422 KiB |
|
Before Width: | Height: | Size: 415 KiB |
|
Before Width: | Height: | Size: 409 KiB |
|
Before Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 415 KiB |
|
Before Width: | Height: | Size: 413 KiB |
|
Before Width: | Height: | Size: 421 KiB |
|
Before Width: | Height: | Size: 420 KiB |
|
Before Width: | Height: | Size: 412 KiB |
|
Before Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 402 KiB |
|
Before Width: | Height: | Size: 441 KiB |
|
Before Width: | Height: | Size: 438 KiB |
|
Before Width: | Height: | Size: 434 KiB |
|
Before Width: | Height: | Size: 433 KiB |
|
Before Width: | Height: | Size: 425 KiB |
|
Before Width: | Height: | Size: 424 KiB |
|
Before Width: | Height: | Size: 421 KiB |
|
Before Width: | Height: | Size: 409 KiB |
|
Before Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 394 KiB |
|
Before Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 411 KiB |
|
Before Width: | Height: | Size: 411 KiB |
|
Before Width: | Height: | Size: 416 KiB |
|
Before Width: | Height: | Size: 420 KiB |
|
Before Width: | Height: | Size: 413 KiB |
|
Before Width: | Height: | Size: 409 KiB |
|
Before Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 406 KiB |
|
Before Width: | Height: | Size: 382 KiB |
|
Before Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 278 KiB |
|
Before Width: | Height: | Size: 252 KiB |
|
Before Width: | Height: | Size: 239 KiB |
|
Before Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 213 KiB |
|
Before Width: | Height: | Size: 366 KiB |
|
Before Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 385 KiB |
|
Before Width: | Height: | Size: 414 KiB |
|
Before Width: | Height: | Size: 427 KiB |
|
Before Width: | Height: | Size: 427 KiB |
|
Before Width: | Height: | Size: 329 KiB |
|
Before Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 337 KiB |
|
Before Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 294 KiB |
|
Before Width: | Height: | Size: 353 KiB |
|
Before Width: | Height: | Size: 367 KiB |
|
Before Width: | Height: | Size: 375 KiB |
|
Before Width: | Height: | Size: 383 KiB |
|
Before Width: | Height: | Size: 389 KiB |
|
Before Width: | Height: | Size: 328 KiB |
|
Before Width: | Height: | Size: 394 KiB |
|
Before Width: | Height: | Size: 420 KiB |
|
Before Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 410 KiB |
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 379 KiB |
|
Before Width: | Height: | Size: 351 KiB |
|
Before Width: | Height: | Size: 351 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 355 KiB |
|
Before Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 329 KiB |
|
Before Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 362 KiB |
|
Before Width: | Height: | Size: 362 KiB |
|
Before Width: | Height: | Size: 349 KiB |
|
Before Width: | Height: | Size: 335 KiB |
|
Before Width: | Height: | Size: 323 KiB |
|
Before Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 324 KiB |
|
Before Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 348 KiB |
|
Before Width: | Height: | Size: 360 KiB |
|
Before Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 303 KiB |