Spaces:
Running
Running
File size: 5,055 Bytes
e735bf3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
import os
import cv2
import numpy as np
from finger_detector import FingerDetector
from models import FingerQualityResult
from quality_analyzer import QualityAnalyzer, QualityConfig
from utils import finger_quality_result_to_json
from visualizer import Visualizer
class FingerQualityAssessor:
"""
End-to-end finger quality computation on single-finger mobile images.
"""
def __init__(self, config: QualityConfig):
self.config = config
self.detector = FingerDetector(min_contour_area_ratio=0.02)
self.analyzer = QualityAnalyzer(config)
def assess(self, bgr: np.ndarray, draw_debug: bool = False):
if bgr is None or bgr.size == 0:
raise ValueError("Input image is empty")
img = self.analyzer.resize_keep_aspect(bgr, self.config.target_width)
h, w = img.shape[:2]
frame_area = float(h * w)
mask = self.detector.segment_skin_ycbcr(img)
contour = self.detector.find_largest_contour(mask, frame_area)
if contour is None:
result = FingerQualityResult(
blur_score=0.0,
illumination_score=0.0,
coverage_ratio=0.0,
orientation_angle_deg=0.0,
blur_pass=False,
illumination_pass=False,
coverage_pass=False,
orientation_pass=False,
quality_score=0.0,
overall_pass=False,
bbox=None,
contour_area=0.0,
)
feedback = self.analyzer.generate_feedback(result)
return result, feedback, (img if draw_debug else None)
contour_area = float(cv2.contourArea(contour))
bbox = self.detector.bounding_box(contour)
x, y, w_box, h_box = bbox
roi = img[y:y + h_box, x:x + w_box]
roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
mask_roi = mask[y:y + h_box, x:x + w_box]
blur_score = self.analyzer.blur_score_laplacian(roi_gray)
illumination_score = float(roi_gray.mean())
coverage_ratio = float(np.count_nonzero(mask_roi)) / float(frame_area)
orientation_angle_deg = self.detector.orientation_pca_deg(contour)
blur_pass = blur_score >= self.config.blur_min
illum_pass = self.config.illum_min <= illumination_score <= self.config.illum_max
coverage_pass = coverage_ratio >= self.config.coverage_min
orientation_pass = self.analyzer.orientation_pass(orientation_angle_deg)
quality_score = self.analyzer.compute_quality_score(
blur_score=blur_score,
illumination_score=illumination_score,
coverage_ratio=coverage_ratio,
orientation_ok=orientation_pass,
)
overall_pass = quality_score >= self.config.overall_quality_threshold
result = FingerQualityResult(
blur_score=float(blur_score),
illumination_score=float(illumination_score),
coverage_ratio=float(coverage_ratio),
orientation_angle_deg=float(orientation_angle_deg),
blur_pass=bool(blur_pass),
illumination_pass=bool(illum_pass),
coverage_pass=bool(coverage_pass),
orientation_pass=bool(orientation_pass),
quality_score=float(quality_score),
overall_pass=bool(overall_pass),
bbox=bbox,
contour_area=contour_area,
feedback=None
)
feedback = self.analyzer.generate_feedback(result)
# NEW: embed feedback into result
result.feedback = feedback
debug_img = None
if draw_debug and contour is not None and result.bbox is not None:
debug_img = Visualizer.draw_debug(img, contour, bbox, orientation_angle_deg, result)
return result, feedback, debug_img
def main():
image_path = r"C:\SagarKV\sol9x\ContactlessFinger\TRACK_A\finger_inputs\OM_TH.jpg"
img = cv2.imread(image_path)
if img is None:
raise RuntimeError("Image not found or path is wrong")
config = QualityConfig(
target_width=640,
blur_min=60.0,
illum_min=50.0,
illum_max=200.0,
coverage_min=0.10,
orientation_max_deviation=45.0,
vertical_expected=True,
overall_quality_threshold=0.70,
)
assessor = FingerQualityAssessor(config)
result, feedback, debug_image = assessor.assess(img, draw_debug=True)
os.makedirs("results", exist_ok=True)
quality_json = finger_quality_result_to_json(result)
with open("results/finger_quality_result.json", "w", encoding="utf-8") as f:
f.write(quality_json)
# Print JSON + feedback
print(quality_json)
for m in feedback.messages:
print(f"[{m.severity.upper()}] {m.category}: {m.message}")
print("Acceptable:", feedback.is_acceptable)
if debug_image is not None:
cv2.imshow("Finger Quality Debug", debug_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
|