183 lines
6.1 KiB
Python
183 lines
6.1 KiB
Python
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) |