如何将子文件夹中的所有图片按每组8张有序分组(支持MATLAB/Python实现)
Got it, let's tackle your problem step by step. You need to process all images across all categories in order, grouping them into sets of 8 (even if the last set has fewer) and generate 2x4 grids with 144x144 thumbnails. Here are solutions for both MATLAB and Python:
MATLAB Solution
The key here is to leverage the ordered list of all image files from your imageDatastore—since you set IncludeSubfolders=true, the Files property already lists images in the order of your category folders (0000 to 0905) and then alphabetical order within each folder. We can split this list into chunks of 8 and process each chunk:
filepath = 'C:\portrait'; % Use your full path here % Create datastore with subfolders included PortraitIMDS = imageDatastore(filepath, ... 'IncludeSubfolders', true, ... 'LabelSource', 'foldernames'); % Get all image file paths in order allImageFiles = PortraitIMDS.Files; totalImages = length(allImageFiles); % Calculate number of groups (round up for the last partial group) numGroups = ceil(totalImages / 8); % Loop through each group for groupIdx = 1:numGroups % Calculate start and end indices for the current group startIdx = (groupIdx - 1) * 8 + 1; endIdx = min(startIdx + 7, totalImages); % Get the files for this group groupFiles = allImageFiles(startIdx:endIdx); % Generate the 2x4 grid with 144x144 thumbnails % Note: imtile will automatically handle fewer than 8 images by leaving empty spots tileFigure = imtile(groupFiles, 'GridSize', [2 4], 'ThumbnailSize', [144 144]); imshow(tileFigure); title(sprintf('Group %d (Images %d-%d)', groupIdx, startIdx, endIdx)); % Optional: Save the grid to a file % imwrite(tileFigure, sprintf('group_%03d.png', groupIdx)); end
Key Notes:
- The
Filesproperty ofimageDatastoremaintains the order of images as they're found in the folders (category 0000 first, then 0001, etc.), so this ensures sequential processing across categories. ceil(totalImages / 8)ensures we account for the final group even if it has less than 8 images.imtilehandles partial groups gracefully—any empty slots in the 2x4 grid will be filled with a black background.
Python Solution
For Python, we'll use PIL (Pillow) for image handling and grid creation, along with os to walk through folders in order. This approach gives you full control over the image order and grid layout:
First, make sure you have Pillow installed:
pip install pillow
Then use this code:
import os from PIL import Image def create_image_grid(image_paths, grid_size=(2, 4), thumbnail_size=(144, 144)): rows, cols = grid_size thumb_width, thumb_height = thumbnail_size # Create a blank canvas for the grid grid_width = cols * thumb_width grid_height = rows * thumb_height grid_image = Image.new('RGB', (grid_width, grid_height), color='black') # Paste each thumbnail into the grid for idx, img_path in enumerate(image_paths): try: with Image.open(img_path) as img: # Resize to thumbnail size while maintaining aspect ratio img.thumbnail(thumbnail_size) # Calculate position to center the image in its slot paste_x = (idx % cols) * thumb_width + (thumb_width - img.width) // 2 paste_y = (idx // cols) * thumb_height + (thumb_height - img.height) // 2 grid_image.paste(img, (paste_x, paste_y)) except Exception as e: print(f"Error loading {img_path}: {e}") return grid_image # Configuration root_dir = r'C:\portrait' # Your full path here output_dir = 'image_grids' # Optional: Folder to save grids os.makedirs(output_dir, exist_ok=True) # Collect all PNG files in order (category folders 0000 to 0905, then files in each) all_image_files = [] # Sort category folders numerically to ensure proper order category_folders = sorted(os.listdir(root_dir), key=lambda x: int(x)) for folder in category_folders: folder_path = os.path.join(root_dir, folder) if os.path.isdir(folder_path): # Sort files in each folder alphabetically image_files = sorted([f for f in os.listdir(folder_path) if f.lower().endswith('.png')]) for img_file in image_files: all_image_files.append(os.path.join(folder_path, img_file)) # Split into groups of 8 total_images = len(all_image_files) num_groups = (total_images + 7) // 8 # Equivalent to ceil(total_images /8) # Process each group for group_idx in range(num_groups): start_idx = group_idx * 8 end_idx = min(start_idx + 8, total_images) group_files = all_image_files[start_idx:end_idx] # Create and display the grid grid_img = create_image_grid(group_files) grid_img.show(title=f"Group {group_idx+1} (Images {start_idx+1}-{end_idx})") # Optional: Save the grid save_path = os.path.join(output_dir, f'group_{group_idx+1:03d}.png') grid_img.save(save_path)
Key Notes:
- We explicitly sort category folders numerically (
key=lambda x: int(x)) to guarantee 0000 comes before 0001, avoiding any string-sorting oddities. - The
create_image_gridfunction usesthumbnail()to preserve image aspect ratio, so thumbnails won't be stretched. If you want to force an exact 144x144 size (even if it distorts the image), replaceimg.thumbnail(thumbnail_size)withimg = img.resize(thumbnail_size). - Basic error handling is included to skip corrupted images without breaking the entire workflow.
内容的提问来源于stack exchange,提问作者PARCB

