| |
| """Continue processing synthetic images through stage0/stage1. |
| Skips already processed images. Uses single GPU (runs alongside training).""" |
|
|
| import os |
| import sys |
| import cv2 |
| import numpy as np |
| import torch |
| from pathlib import Path |
| from tqdm import tqdm |
|
|
| |
| INPUT_RAW = '/data/ecg-digitization/synthetic_0001/raw' |
| INPUT_GT = '/data/ecg-digitization/synthetic_0001/gt' |
| OUTPUT_RAW = '/data/ecg-digitization/synthetic_0001_processed/raw' |
| OUTPUT_GT = '/data/ecg-digitization/synthetic_0001_processed/gt' |
| BASELINE_PATH = '/data/ecg-digitization/hengck23' |
|
|
| def main(): |
| |
| Path(OUTPUT_RAW).mkdir(parents=True, exist_ok=True) |
| Path(OUTPUT_GT).mkdir(parents=True, exist_ok=True) |
| |
| |
| all_images = sorted(Path(INPUT_RAW).glob('*.png')) |
| processed = set(p.name for p in Path(OUTPUT_RAW).glob('*.png')) |
| |
| to_process = [p for p in all_images if p.name not in processed] |
| |
| print(f"Total images: {len(all_images)}") |
| print(f"Already processed: {len(processed)}") |
| print(f"To process: {len(to_process)}") |
| |
| if len(to_process) == 0: |
| print("All done!") |
| return |
| |
| |
| os.environ['CUDA_VISIBLE_DEVICES'] = '0' |
| device = torch.device('cuda') |
| |
| |
| sys.path.insert(0, BASELINE_PATH) |
| from stage0_model import Net as Stage0Net |
| from stage0_common import image_to_batch, output_to_predict, normalise_by_homography, load_net |
| from stage1_model import Net as Stage1Net |
| from stage1_common import output_to_predict as stage1_output_to_predict, rectify_image |
| |
| |
| print("Loading Stage 0...") |
| stage0_net = Stage0Net(pretrained=False) |
| stage0_net = load_net(stage0_net, f'{BASELINE_PATH}/weight/stage0-last.checkpoint.pth') |
| stage0_net.to(device).eval() |
| |
| print("Loading Stage 1...") |
| stage1_net = Stage1Net(pretrained=False) |
| stage1_net = load_net(stage1_net, f'{BASELINE_PATH}/weight/stage1-last.checkpoint.pth') |
| stage1_net.to(device).eval() |
| |
| @torch.no_grad() |
| def process_image(image_rgb): |
| """Process through stage0 and stage1.""" |
| |
| batch = image_to_batch(image_rgb) |
| with torch.amp.autocast('cuda', dtype=torch.float32): |
| output = stage0_net(batch) |
| rotated, keypoint = output_to_predict(image_rgb, batch, output) |
| normalized, _, _ = normalise_by_homography(rotated, keypoint) |
| |
| |
| batch = {'image': torch.from_numpy(np.ascontiguousarray(normalized.transpose(2, 0, 1))).unsqueeze(0)} |
| with torch.amp.autocast('cuda', dtype=torch.float32): |
| output = stage1_net(batch) |
| gridpoint_xy, _ = stage1_output_to_predict(normalized, batch, output) |
| rectified = rectify_image(normalized, gridpoint_xy) |
| |
| return rectified |
| |
| success = 0 |
| failed = 0 |
| |
| for img_path in tqdm(to_process, desc="Processing"): |
| gt_csv_path = Path(INPUT_GT) / f"{img_path.stem}.csv" |
| out_img_path = Path(OUTPUT_RAW) / img_path.name |
| out_gt_path = Path(OUTPUT_GT) / f"{img_path.stem}.csv" |
| |
| |
| image = cv2.imread(str(img_path)) |
| if image is None: |
| failed += 1 |
| continue |
| image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) |
| |
| try: |
| |
| rectified = process_image(image_rgb) |
| |
| |
| cv2.imwrite(str(out_img_path), cv2.cvtColor(rectified, cv2.COLOR_RGB2BGR)) |
| |
| |
| if gt_csv_path.exists(): |
| import shutil |
| shutil.copy(gt_csv_path, out_gt_path) |
| |
| success += 1 |
| except Exception as e: |
| failed += 1 |
| if failed <= 5: |
| print(f" Failed {img_path.name}: {e}") |
| |
| print(f"\nDone: {success} success, {failed} failed") |
| print(f"Total processed: {len(processed) + success}") |
|
|
|
|
| if __name__ == '__main__': |
| main() |
|
|