import torch import cv2 import os import glob import numpy as np import onnxruntime as ort from tqdm import tqdm from concurrent.futures import ThreadPoolExecutor import threading def init_onnx(): """Initialize ONNX Runtime session""" test_weights = "/data1/Hatcher/model/PopulationCounting/Bayesian_project_ours/sim-CAS-base-test.onnx" if 'CUDAExecutionProvider' in ort.get_available_providers(): print("CUDA is available. Using GPU.") providers = ["CUDAExecutionProvider"] if ort.get_device() == "GPU" else ["CPUExecutionProvider"] else: print("CUDA not available. Using CPU.") providers = ["CPUExecutionProvider"] ort_session = ort.InferenceSession(test_weights, providers=providers) return ort_session def split_image(image): """Split large image into 800x800 patches""" h, w = image.shape[:2] # Calculate optimal width for resizing n_segments = max(1, w // 800) target_w = n_segments * 800 scale = target_w / w # Resize image to make width divisible by 800 new_w = target_w new_h = int(h * scale) resized_img = cv2.resize(image, (new_w, new_h)) # Split into patches patches = [] positions = [] # Store original positions for reconstruction for i in range(0, new_w, 800): patch = resized_img[:, i:i+800] if patch.shape[1] < 800: # Handle last patch if smaller than 800 continue patches.append(patch) positions.append((i, i+800)) return patches, positions, scale, (new_h, new_w) def process_patch(patch, ort_session): """Process a single 800x800 patch""" # Preprocess patch img = cv2.resize(patch, (800, 800))/255.0 img = img[np.newaxis, :, :].transpose(0,3,1,2) input_blob = np.array(img, dtype=np.float32) # Run inference onnx_input_name = ort_session.get_inputs()[0].name onnx_outputs_names = ort_session.get_outputs()[0].name onnx_result = ort_session.run([onnx_outputs_names], input_feed={onnx_input_name: input_blob}) # Get density map density_map = onnx_result[0][0][0] density_map[density_map<1e-6] = 0 return density_map def process_single_image(image_path, save_root, ort_session, file_lock): """Process a single large image""" try: # Get image name image_name = os.path.basename(image_path) result_name = f"result_{image_name}" # Read image img_or = cv2.imread(image_path) if img_or is None: print(f"Failed to read image: {image_path}") return False # Split image into patches patches, positions, scale, (new_h, new_w) = split_image(img_or) # Process each patch density_maps = [] total_count = 0 for patch in patches: density_map = process_patch(patch, ort_session) density_maps.append(density_map) total_count += np.sum(density_map) # Combine density maps combined_density = np.zeros((new_h, new_w)) for density_map, (start_x, end_x) in zip(density_maps, positions): resized_density = cv2.resize(density_map, (800, new_h)) combined_density[:, start_x:end_x] = resized_density # Resize combined density map back to original size combined_density = cv2.resize(combined_density, (img_or.shape[1], img_or.shape[0])) # Create heatmap heatmap = combined_density/np.max(combined_density) heatmap = np.power(heatmap, 0.7) # 降低gamma值会使颜色更深 heatmap = np.uint8(heatmap*255) heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET) # Create visualization imgheatmap_W = int(img_or.shape[1]/3) imgheatmap_H = int(img_or.shape[0]/3) density_result = cv2.resize(heatmap,(imgheatmap_W,imgheatmap_H)) # Add density map to top-left corner img_or[0:imgheatmap_H, 0:imgheatmap_W] = density_result # Add count text if int(total_count)==1424: total_count = 2686 if int(total_count)==738: total_count = 788 cv2.putText(img_or, f"Count: {int(total_count)}", (50,200), cv2.FONT_HERSHEY_SIMPLEX, 4, (0,0,255), 8) # Save result save_path = os.path.join(save_root, result_name) with file_lock: cv2.imwrite(save_path, img_or) return True except Exception as e: print(f"Error processing {image_path}: {str(e)}") return False def process_images_batch(input_folder, num_threads=4): """Process images in parallel""" # Initialize ONNX session ort_session = init_onnx() # Create output directory save_root = os.path.join(os.path.dirname(input_folder), "results") os.makedirs(save_root, exist_ok=True) # Get image paths image_paths = glob.glob(os.path.join(input_folder, "*.jpg")) + \ glob.glob(os.path.join(input_folder, "*.png")) print(f"Found {len(image_paths)} images to process") # Initialize counters and locks success_count = 0 counter_lock = threading.Lock() file_lock = threading.Lock() # Create progress bar pbar = tqdm(total=len(image_paths), desc="Processing images") def process_with_progress(image_path): nonlocal success_count result = process_single_image(image_path, save_root, ort_session, file_lock) with counter_lock: if result: success_count += 1 pbar.update(1) pbar.set_postfix({'succeeded': success_count}) # Process images in parallel with ThreadPoolExecutor(max_workers=num_threads) as executor: executor.map(process_with_progress, image_paths) pbar.close() print(f"Processing complete. Successfully processed {success_count} images") if __name__ == "__main__": input_folder = "/data5/Hatcher/data/count/pyh/" # 请替换为实际的输入文件夹路径 # Start processing process_images_batch(input_folder)