| import cv2
|
| import numpy as np
|
| import matplotlib.pyplot as plt
|
| from scipy.signal import find_peaks
|
| from PIL import Image
|
|
|
| def qualitative_analysis(image_path):
|
| """Performs qualitative analysis by detecting lines on hCG test strips."""
|
|
|
|
|
| image = cv2.imread(image_path)
|
| if image is None:
|
| raise FileNotFoundError(f"Image not found at {image_path}")
|
|
|
|
|
| gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
|
|
|
|
| edges = cv2.Canny(gray, 50, 150)
|
|
|
|
|
| lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=50, minLineLength=100, maxLineGap=10)
|
|
|
|
|
| angles = []
|
| if lines is not None:
|
| for line in lines:
|
| x1, y1, x2, y2 = line[0]
|
| angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi
|
| angles.append(angle)
|
|
|
| median_angle = np.median(angles) if angles else 0
|
|
|
|
|
| (h, w) = image.shape[:2]
|
| center = (w // 2, h // 2)
|
| rotation_matrix = cv2.getRotationMatrix2D(center, median_angle, 1.0)
|
| aligned_image = cv2.warpAffine(image, rotation_matrix, (w, h))
|
|
|
|
|
| lab_image = cv2.cvtColor(aligned_image, cv2.COLOR_BGR2LAB)
|
| l_channel = lab_image[:, :, 0]
|
|
|
|
|
| if h > w:
|
| intensity_profile = np.mean(l_channel, axis=1)
|
| axis_label = "Vertical Position"
|
| else:
|
| intensity_profile = np.mean(l_channel, axis=0)
|
| axis_label = "Horizontal Position"
|
|
|
|
|
| max_intensity_drop = np.max(intensity_profile) - np.min(intensity_profile)
|
| adaptive_prominence = 0.2 * max_intensity_drop
|
|
|
|
|
| peaks, _ = find_peaks(-intensity_profile, distance=20, prominence=adaptive_prominence)
|
|
|
|
|
| for peak in peaks:
|
| if h > w:
|
| cv2.line(aligned_image, (0, peak), (w, peak), (0, 0, 255), 2)
|
| else:
|
| cv2.line(aligned_image, (peak, 0), (peak, h), (0, 0, 255), 2)
|
|
|
|
|
| result_pil = Image.fromarray(cv2.cvtColor(aligned_image, cv2.COLOR_BGR2RGB))
|
|
|
|
|
| plt.figure(figsize=(6, 4))
|
| plt.plot(intensity_profile, label="LAB Lightness Intensity", color='blue')
|
| plt.scatter(peaks, intensity_profile[peaks], color='red', label="Detected Lines")
|
| plt.xlabel(axis_label)
|
| plt.ylabel("Intensity")
|
| plt.title("LAB L Channel Intensity Profile with Detected Lines")
|
| plt.legend()
|
|
|
| return result_pil, plt
|
|
|