导入工具包
import os
import random
from PIL import Image
中心裁剪图片
tartget_size为目标图片大小,进行中心裁剪
def center_crop(img, target_size):
width, height = img.size
left = (width - target_size) // 2
top = (height - target_size) // 2
right = (width + target_size) // 2
bottom = (height + target_size) // 2
return img.crop((left, top, right, bottom))
合成图函数
folder_path | 文件夹路径 |
rice_types | 类别名集合 |
num_images_per_rice_type | 每类集合中个数 |
num_composite_images | 循环次数 |
grid_size | 网格大小,如5,则是5x5网格 |
def combine_images(folder_path, rice_types, num_images_per_rice_type=3000, num_composite_images=10, grid_size=5):
下面代码是在遍历每一种类型(rice_type
)以及每一张对应编号的图像(k
)时,获取图像的宽度和高度,并保留最大的宽度和高度。这样做的目的是为了确保后续合成的图片具有足够的大小,以适应其中最大的图像。在合成过程中,会使用这个最大宽度和高度来创建一个黑色背景的画布,然后将选择的图像粘贴到这个画布上。因此,通过获取最大的宽度和高度,可以确保合成的图片足够大,不会截断任何图像。
for rice_type in rice_types:
for k in range(1, num_images_per_rice_type + 1):
image_path = f"{folder_path}/{rice_type}{k}.jpg"
if os.path.exists(image_path):
img = Image.open(image_path)
max_width = max(max_width, img.width)
max_height = max(max_height, img.height)
循环遍历,两两组合
for i in range(len(rice_types)):
for j in range(i + 1, len(rice_types)):
rice_type1 = rice_types[i]
rice_type2 = rice_types[j]
从同一个文件夹挑出每一类的集合
images_rice_type1 = [f"{rice_type1}{k}.jpg" for k in range(1, num_images_per_rice_type + 1) if
os.path.exists(f"{folder_path}/{rice_type1}{k}.jpg")]
# Randomly shuffle and select images for each rice type
selected_images_rice_type1 = random.sample(images_rice_type1,
min(num_grains_rice_type1, len(images_rice_type1)))
随机打乱顺序如上
随机粘贴图代码如下
已经被贴图的格子被grid_occupied[row][col] = True记下
for img_name in selected_images:
placed = False
while not placed:
row = random.randint(0, grid_size - 1)
col = random.randint(0, grid_size - 1)
if not grid_occupied[row][col]:
img = Image.open(f"{folder_path}/{img_name}")
img = center_crop(img, 900) # Center crop to 900x900 pixels
combined_image.paste(img, (col * max_width, row * max_height))
grid_occupied[row][col] = True
placed = True
附完整代码:
import os
import random
from PIL import Image
def center_crop(img, target_size):
width, height = img.size
left = (width - target_size) // 2
top = (height - target_size) // 2
right = (width + target_size) // 2
bottom = (height + target_size) // 2
return img.crop((left, top, right, bottom))
def combine_images(folder_path, rice_types, num_images_per_rice_type=3000, num_composite_images=10, grid_size=5):
# Find the maximum width and height among all images
max_width = 0
max_height = 0
for rice_type in rice_types:
for k in range(1, num_images_per_rice_type + 1):
image_path = f"{folder_path}/{rice_type}{k}.jpg"
if os.path.exists(image_path):
img = Image.open(image_path)
max_width = max(max_width, img.width)
max_height = max(max_height, img.height)
for i in range(len(rice_types)):
for j in range(i + 1, len(rice_types)):
rice_type1 = rice_types[i]
rice_type2 = rice_types[j]
# Modify the range based on the total number of images for each rice type
images_rice_type1 = [f"{rice_type1}{k}.jpg" for k in range(1, num_images_per_rice_type + 1) if
os.path.exists(f"{folder_path}/{rice_type1}{k}.jpg")]
images_rice_type2 = [f"{rice_type2}{k}.jpg" for k in range(1, num_images_per_rice_type + 1) if
os.path.exists(f"{folder_path}/{rice_type2}{k}.jpg")]
for _ in range(num_composite_images):
combined_image_path = f"{rice_type2}_{rice_type1}_combined_{_ + 1}.jpg"
combined_image = Image.new('RGB', (max_width * grid_size, max_height * grid_size), color="black")
# Randomly choose the number of grains for each rice type
num_grains_rice_type1 = random.randint(1, 2)
# Ensure num_grains_rice_type2 is within the valid range
num_grains_rice_type2 = random.randint(max(6 - num_grains_rice_type1, 1), min(9 - num_grains_rice_type1, len(images_rice_type2)))
# Create a 5x5 array to track whether a cell is occupied
grid_occupied = [[False] * grid_size for _ in range(grid_size)]
# Randomly shuffle and select images for each rice type
selected_images_rice_type1 = random.sample(images_rice_type1,
min(num_grains_rice_type1, len(images_rice_type1)))
selected_images_rice_type2 = random.sample(images_rice_type2,
min(num_grains_rice_type2, len(images_rice_type2)))
print(f"num_grains_rice_type1: {num_grains_rice_type1}")
print(f"num_grains_rice_type2: {num_grains_rice_type2}")
# Create a list to store selected images
selected_images = []
# Add images for the first rice type
selected_images.extend(selected_images_rice_type1)
# Add images for the second rice type
selected_images.extend(selected_images_rice_type2)
# Shuffle the list to create a random arrangement
random.shuffle(selected_images)
# Paste the shuffled and center-cropped images into the combined image in a 5x5 grid
for img_name in selected_images:
placed = False
while not placed:
row = random.randint(0, grid_size - 1)
col = random.randint(0, grid_size - 1)
if not grid_occupied[row][col]:
img = Image.open(f"{folder_path}/{img_name}")
img = center_crop(img, 900) # Center crop to 900x900 pixels
combined_image.paste(img, (col * max_width, row * max_height))
grid_occupied[row][col] = True
placed = True
# combined_image.show() # Display the combined image for debugging
combined_image.save(f"blend2/{combined_image_path}")
if __name__ == "__main__":
folder_path = "rice_ghost/datasets/images/train"
rice_types = ["GD", "NM", "PJX", "WC", "WN",
"YB"]
combine_images(folder_path, rice_types, num_composite_images=10, grid_size=5)