import cv2 import numpy as np import os import logging from utils import read_yaml, file_exists logging_str = "[%(asctime)s: %(levelname)s: %(module)s]: %(message)s" log_dir = "logs" os.makedirs(log_dir, exist_ok=True) logging.basicConfig(filename=os.path.join(log_dir,"ekyc_logs.log"), level=logging.INFO, format=logging_str, filemode="a") config_path = "config.yaml" config = read_yaml(config_path) artifacts = config['artifacts'] intermediate_dir_path = artifacts['INTERMIDEIATE_DIR'] conour_file_name = artifacts['CONTOUR_FILE'] def read_image(image_path, is_uploaded=False): if is_uploaded: try: # Read image using OpenCV image_bytes = image_path.read() img = cv2.imdecode(np.frombuffer(image_bytes, np.uint8), cv2.IMREAD_COLOR) if img is None: logging.info("Failed to read image: {}".format(image_path)) raise Exception("Failed to read image: {}".format(image_path)) return img except Exception as e: logging.info(f"Error reading image: {e}") print("Error reading image:", e) return None else: try: img = cv2.imread(image_path) if img is None: logging.info("Failed to read image: {}".format(image_path)) raise Exception("Failed to read image: {}".format(image_path)) return img except Exception as e: logging.info(f"Error reading image: {e}") print("Error reading image:", e) return None def extract_id_card(img): """ Extracts the ID card from an image containing other backgrounds. Args: img (np.ndarray): The input image. Returns: np.ndarray: The cropped image containing the ID card, or None if no ID card is detected. """ # Convert image to grayscale gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Noise reduction blur = cv2.GaussianBlur(gray_img, (5, 5), 0) # Adaptive thresholding thresh = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) # Find contours contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Select the largest contour (assuming the ID card is the largest object) largest_contour = None largest_area = 0 for cnt in contours: area = cv2.contourArea(cnt) if area > largest_area: largest_contour = cnt largest_area = area # If no large contour is found, assume no ID card is present if not largest_contour.any(): return None # Get bounding rectangle of the largest contour x, y, w, h = cv2.boundingRect(largest_contour) logging.info(f"contours are found at, {(x, y, w, h)}") # logging.info("Area largest_area) # Apply additional filtering (optional): # - Apply bilateral filtering for noise reduction # filtered_img = cv2.bilateralFiltering(img[y:y+h, x:x+w], 9, 75, 75) # - Morphological operations (e.g., erosion, dilation) for shape refinement current_wd = os.getcwd() filename = os.path.join(current_wd,intermediate_dir_path, conour_file_name) contour_id = img[y:y+h, x:x+w] is_exists = file_exists(filename) if is_exists: # Remove the existing file os.remove(filename) cv2.imwrite(filename, contour_id) return contour_id, filename def save_image(image, filename, path="."): """ Saves an image to a specified path with the given filename. Args: image (np.ndarray): The image data (NumPy array). filename (str): The desired filename for the saved image. path (str, optional): The directory path to save the image. Defaults to "." (current directory). """ # Construct the full path full_path = os.path.join(path, filename) is_exists = file_exists(full_path) if is_exists: # Remove the existing file os.remove(full_path) # Save the image using cv2.imwrite cv2.imwrite(full_path, image) logging.info(f"Image saved successfully: {full_path}") return full_path