crabbly commited on
Commit
3afd2b7
·
verified ·
1 Parent(s): f977b02

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +56 -19
main.py CHANGED
@@ -551,14 +551,48 @@ class WatermelonProcessor:
551
  target_rind_mask, rind_source, rind_overlap_ratio, r_warn = self.choose_target_rind_mask(rind_mask, flesh_combined)
552
  warnings.extend(r_warn)
553
 
554
- # Bridge the gap for the unified flesh boundary (visuals and smoothed fit)
555
- bridge_k = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (45, 45))
556
- flesh_closed = cv2.morphologyEx(flesh_combined, cv2.MORPH_CLOSE, bridge_k)
557
  mark("mask_parse")
558
 
559
- # 3. EXTRACTION
560
  rind_data = self.get_polar_data(target_rind_mask)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  flesh_data = self.get_polar_data(flesh_closed)
 
562
  if rind_data is None:
563
  return fail("No stable perimeter.", measurement_unit="cm" if cm_per_px else "px", scale_source="color_checker" if cm_per_px else "original_pixels", color_checker_found=checker_corners is not None, rind_source=rind_source, rind_overlap_ratio=rind_overlap_ratio)
564
 
@@ -683,46 +717,49 @@ class WatermelonProcessor:
683
 
684
  def draw_base(r_m, f_m):
685
  out = image.copy().astype(np.float32)
686
- alpha = 0.42
687
- # Green tint for rind
688
  out[..., 0] = np.where(r_m > 0, out[..., 0]*(1-alpha) + 0, out[..., 0])
689
  out[..., 1] = np.where(r_m > 0, out[..., 1]*(1-alpha) + 170, out[..., 1])
690
  out[..., 2] = np.where(r_m > 0, out[..., 2]*(1-alpha) + 0, out[..., 2])
691
 
692
- # Orange/Flesh tint for the flesh
693
- out[..., 0] = np.where(f_m > 0, out[..., 0]*(1-alpha) + 60, out[..., 0])
694
- out[..., 1] = np.where(f_m > 0, out[..., 1]*(1-alpha) + 120, out[..., 1])
695
  out[..., 2] = np.where(f_m > 0, out[..., 2]*(1-alpha) + 255, out[..., 2])
696
 
697
  out = np.clip(out, 0, 255).astype(np.uint8)
698
- if checker_corners is not None: cv2.polylines(out, [np.int32(checker_corners)], True, (0, 165, 255), 4)
 
699
  if len(midline) > 1:
700
  cv2.polylines(out, [midline.astype(np.int32)], False, (0, 255, 255), 3)
701
  pt1, pt2 = tuple(midline[0].astype(int)), tuple(midline[-1].astype(int))
702
  for pt in (pt1, pt2):
703
- cv2.circle(out, pt, 8, (0,0,0), 2); cv2.circle(out, pt, 6, (255,255,255), -1)
 
704
  return out
705
 
706
  # RAW
707
  out_raw = draw_base(target_rind_mask, flesh_closed)
708
  cv2.line(out_raw, raw_h_line[0], raw_h_line[1], (255, 100, 255), 2)
709
  cv2.line(out_raw, raw_w_line[0], raw_w_line[1], (255, 255, 100), 2)
710
- # Flesh border first
711
  f_cnts_raw, _ = cv2.findContours(flesh_closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
712
- if f_cnts_raw: cv2.polylines(out_raw, [max(f_cnts_raw, key=cv2.contourArea)], True, (255, 50, 50), 3)
713
- # Rind border
714
- cv2.polylines(out_raw, [raw_rind_cnt], True, (0, 200, 0), 3)
715
  res.image_raw_base64 = encode_img(out_raw)
716
 
717
  # SMOOTH
718
  if sm_rind_cnt is not None:
719
- out_sm = draw_base(sm_rind_mask, sm_flesh_mask)
 
720
  cv2.line(out_sm, sm_h_line[0], sm_h_line[1], (255, 100, 255), 2)
721
  cv2.line(out_sm, sm_w_line[0], sm_w_line[1], (255, 255, 100), 2)
722
 
723
- # Thinner lines, distinct bright colors
724
- if sm_flesh_cnt is not None: cv2.polylines(out_sm, [sm_flesh_cnt], True, (255, 150, 50), 2)
725
- cv2.polylines(out_sm, [sm_rind_cnt], True, (0, 255, 127), 2)
726
  res.image_sm_base64 = encode_img(out_sm)
727
 
728
  mark("render")
 
551
  target_rind_mask, rind_source, rind_overlap_ratio, r_warn = self.choose_target_rind_mask(rind_mask, flesh_combined)
552
  warnings.extend(r_warn)
553
 
 
 
 
554
  mark("mask_parse")
555
 
556
+ # 3. EXTRACTION (Rind First)
557
  rind_data = self.get_polar_data(target_rind_mask)
558
+ if rind_data is None:
559
+ return fail("No stable perimeter.", measurement_unit="cm" if cm_per_px else "px", scale_source="color_checker" if cm_per_px else "original_pixels", color_checker_found=checker_corners is not None, rind_source=rind_source, rind_overlap_ratio=rind_overlap_ratio)
560
+
561
+ t_r, raw_r_r, (cx, cy), raw_rind_cnt = rind_data
562
+ pts_r_raw = raw_rind_cnt.reshape(-1, 2).astype(np.float32)
563
+
564
+ # --- NEW SCAN-LINE FLESH GAP FILLING (Preserves V-shape) ---
565
+ _, (ma, Ma), angle = cv2.fitEllipse(raw_rind_cnt) if len(raw_rind_cnt) > 5 else (None, (0,0), 0)
566
+ rot_angle = angle if ma < Ma else angle + 90
567
+ M_rot = cv2.getRotationMatrix2D((cx, cy), rot_angle, 1.0)
568
+ M_inv = cv2.getRotationMatrix2D((cx, cy), -rot_angle, 1.0)
569
+
570
+ l_rot = cv2.warpAffine(flesh_l_m, M_rot, (w, h))
571
+ r_rot = cv2.warpAffine(flesh_r_m, M_rot, (w, h))
572
+
573
+ l_idx = np.where(l_rot > 0)[1]
574
+ r_idx = np.where(r_rot > 0)[1]
575
+ if len(l_idx) > 0 and len(r_idx) > 0 and np.mean(l_idx) > np.mean(r_idx):
576
+ l_rot, r_rot = r_rot, l_rot
577
+
578
+ flesh_closed_rot = cv2.bitwise_or(l_rot, r_rot)
579
+ y_l, y_r = np.where(l_rot > 0)[0], np.where(r_rot > 0)[0]
580
+ if len(y_l) > 0 and len(y_r) > 0:
581
+ for y in range(max(np.min(y_l), np.min(y_r)), min(np.max(y_l), np.max(y_r))):
582
+ row_l = np.where(l_rot[y, :] > 0)[0]
583
+ row_r = np.where(r_rot[y, :] > 0)[0]
584
+ if len(row_l) > 0 and len(row_r) > 0:
585
+ x_start = row_l[-1]
586
+ x_end = row_r[0]
587
+ if x_start < x_end:
588
+ flesh_closed_rot[y, x_start:x_end] = 255
589
+
590
+ flesh_closed = cv2.warpAffine(flesh_closed_rot, M_inv, (w, h))
591
+ _, flesh_closed = cv2.threshold(flesh_closed, 127, 255, cv2.THRESH_BINARY)
592
+
593
+ # Now extract the unified flesh data
594
  flesh_data = self.get_polar_data(flesh_closed)
595
+ # -----------------------------------------------------------
596
  if rind_data is None:
597
  return fail("No stable perimeter.", measurement_unit="cm" if cm_per_px else "px", scale_source="color_checker" if cm_per_px else "original_pixels", color_checker_found=checker_corners is not None, rind_source=rind_source, rind_overlap_ratio=rind_overlap_ratio)
598
 
 
717
 
718
  def draw_base(r_m, f_m):
719
  out = image.copy().astype(np.float32)
720
+ alpha = 0.21 # Half transparency
721
+ # Rind fill: Green
722
  out[..., 0] = np.where(r_m > 0, out[..., 0]*(1-alpha) + 0, out[..., 0])
723
  out[..., 1] = np.where(r_m > 0, out[..., 1]*(1-alpha) + 170, out[..., 1])
724
  out[..., 2] = np.where(r_m > 0, out[..., 2]*(1-alpha) + 0, out[..., 2])
725
 
726
+ # Flesh fill: Red
727
+ out[..., 0] = np.where(f_m > 0, out[..., 0]*(1-alpha) + 0, out[..., 0])
728
+ out[..., 1] = np.where(f_m > 0, out[..., 1]*(1-alpha) + 0, out[..., 1])
729
  out[..., 2] = np.where(f_m > 0, out[..., 2]*(1-alpha) + 255, out[..., 2])
730
 
731
  out = np.clip(out, 0, 255).astype(np.uint8)
732
+ if checker_corners is not None:
733
+ cv2.polylines(out, [np.int32(checker_corners)], True, (0, 165, 255), 4)
734
  if len(midline) > 1:
735
  cv2.polylines(out, [midline.astype(np.int32)], False, (0, 255, 255), 3)
736
  pt1, pt2 = tuple(midline[0].astype(int)), tuple(midline[-1].astype(int))
737
  for pt in (pt1, pt2):
738
+ cv2.circle(out, pt, 8, (0,0,0), 2)
739
+ cv2.circle(out, pt, 6, (255,255,255), -1)
740
  return out
741
 
742
  # RAW
743
  out_raw = draw_base(target_rind_mask, flesh_closed)
744
  cv2.line(out_raw, raw_h_line[0], raw_h_line[1], (255, 100, 255), 2)
745
  cv2.line(out_raw, raw_w_line[0], raw_w_line[1], (255, 255, 100), 2)
746
+
747
  f_cnts_raw, _ = cv2.findContours(flesh_closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
748
+ if f_cnts_raw:
749
+ cv2.polylines(out_raw, [max(f_cnts_raw, key=cv2.contourArea)], True, (0, 0, 255), 2) # Red, 2px
750
+ cv2.polylines(out_raw, [raw_rind_cnt], True, (0, 200, 0), 2) # Dark Green, 2px
751
  res.image_raw_base64 = encode_img(out_raw)
752
 
753
  # SMOOTH
754
  if sm_rind_cnt is not None:
755
+ # Use raw fills for the smoothed preview (decoupled visual)
756
+ out_sm = draw_base(target_rind_mask, flesh_closed)
757
  cv2.line(out_sm, sm_h_line[0], sm_h_line[1], (255, 100, 255), 2)
758
  cv2.line(out_sm, sm_w_line[0], sm_w_line[1], (255, 255, 100), 2)
759
 
760
+ if sm_flesh_cnt is not None:
761
+ cv2.polylines(out_sm, [sm_flesh_cnt], True, (0, 0, 255), 2) # Red, 2px
762
+ cv2.polylines(out_sm, [sm_rind_cnt], True, (0, 200, 0), 2) # Dark Green, 2px
763
  res.image_sm_base64 = encode_img(out_sm)
764
 
765
  mark("render")