harelcain commited on
Commit
727e6ff
·
verified ·
1 Parent(s): 62dca07

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -9
app.py CHANGED
@@ -68,6 +68,14 @@ def compute_homography(kp1, kp2, matches, ransac_reproj_thresh=8.0, confidence=0
68
  return H, mask
69
 
70
 
 
 
 
 
 
 
 
 
71
  def create_inlier_mask(keypoints, matches, inlier_mask, image_shape, radius=50):
72
  h, w = image_shape[:2]
73
  mask_img = np.zeros((h, w), dtype=np.uint8)
@@ -444,26 +452,35 @@ def align_image(source_img, target_img, pp_level=2, paste_back=True):
444
  matches = match_features(desc_src, desc_tgt)
445
 
446
  color_mask = None
 
 
447
  if len(matches) >= 4:
448
  H, mask = compute_homography(kp_src, kp_tgt, matches)
449
  if H is not None and mask is not None:
450
- inlier_mask = mask.ravel()
451
- aligned = cv2.warpPerspective(source_resized, H, target_size,
452
- flags=cv2.INTER_LANCZOS4,
453
- borderMode=cv2.BORDER_REPLICATE)
454
- color_mask = create_inlier_mask(kp_tgt, matches, inlier_mask,
455
- target_img.shape, radius=50)
 
 
 
 
 
456
  else:
 
457
  aligned = source_resized
458
  else:
 
459
  aligned = source_resized
460
 
461
  result = fast_color_transfer(aligned, target_img, mask=color_mask)
462
 
463
- # Optionally paste back unedited regions from target
464
  pre_paste = result.copy()
465
  unedited_mask = None
466
- if paste_back:
467
  unedited_mask = detect_unedited_mask(result, target_img)
468
  result = paste_unedited_regions(result, target_img, unedited_mask)
469
 
@@ -471,7 +488,7 @@ def align_image(source_img, target_img, pp_level=2, paste_back=True):
471
  pp_result = None
472
  if pp_level > 0:
473
  pp_result = postprocess_foreground(result, target_img, level=pp_level)
474
- if paste_back and unedited_mask is not None:
475
  pp_result = paste_unedited_regions(pp_result, target_img, unedited_mask)
476
 
477
  final = pp_result if pp_result is not None else result
 
68
  return H, mask
69
 
70
 
71
+ def homography_deviation(H, width, height):
72
+ H_norm = H / H[2, 2]
73
+ corners = np.float32([[0, 0], [width, 0], [width, height], [0, height]]).reshape(-1, 1, 2)
74
+ warped = cv2.perspectiveTransform(corners, H_norm)
75
+ displacement = np.sqrt(np.sum((warped.reshape(-1, 2) - corners.reshape(-1, 2)) ** 2, axis=1))
76
+ return float(np.mean(displacement))
77
+
78
+
79
  def create_inlier_mask(keypoints, matches, inlier_mask, image_shape, radius=50):
80
  h, w = image_shape[:2]
81
  mask_img = np.zeros((h, w), dtype=np.uint8)
 
452
  matches = match_features(desc_src, desc_tgt)
453
 
454
  color_mask = None
455
+ skip_warp = False
456
+ max_deviation_px = 100
457
  if len(matches) >= 4:
458
  H, mask = compute_homography(kp_src, kp_tgt, matches)
459
  if H is not None and mask is not None:
460
+ deviation = homography_deviation(H, target_w, target_h)
461
+ if deviation > max_deviation_px:
462
+ skip_warp = True
463
+ aligned = source_resized
464
+ else:
465
+ inlier_mask = mask.ravel()
466
+ aligned = cv2.warpPerspective(source_resized, H, target_size,
467
+ flags=cv2.INTER_LANCZOS4,
468
+ borderMode=cv2.BORDER_REPLICATE)
469
+ color_mask = create_inlier_mask(kp_tgt, matches, inlier_mask,
470
+ target_img.shape, radius=50)
471
  else:
472
+ skip_warp = True
473
  aligned = source_resized
474
  else:
475
+ skip_warp = True
476
  aligned = source_resized
477
 
478
  result = fast_color_transfer(aligned, target_img, mask=color_mask)
479
 
480
+ # Paste back unedited regions from target (skip if warp was skipped)
481
  pre_paste = result.copy()
482
  unedited_mask = None
483
+ if paste_back and not skip_warp:
484
  unedited_mask = detect_unedited_mask(result, target_img)
485
  result = paste_unedited_regions(result, target_img, unedited_mask)
486
 
 
488
  pp_result = None
489
  if pp_level > 0:
490
  pp_result = postprocess_foreground(result, target_img, level=pp_level)
491
+ if paste_back and not skip_warp and unedited_mask is not None:
492
  pp_result = paste_unedited_regions(pp_result, target_img, unedited_mask)
493
 
494
  final = pp_result if pp_result is not None else result