import cv2 import numpy as np import pandas as pd import gradio as gr def detect_baseline_and_solvent_front(image): """ Detect the baseline and solvent front in the TLC plate image. """ try: gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) edges = cv2.Canny(blurred, 50, 150) row_sums = edges.sum(axis=1) baseline_y = None solvent_front_y = None for i, value in enumerate(row_sums): if value > 50: # Threshold for significant edge detection if baseline_y is None: baseline_y = i solvent_front_y = i if baseline_y is None or solvent_front_y is None: raise ValueError("Could not detect baseline or solvent front.") return baseline_y, solvent_front_y except Exception as e: print(f"Error in detecting baseline and solvent front: {e}") return None, None def detect_spots(image): """ Detect spots on the TLC plate. """ try: gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) _, threshold = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV) contours, _ = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) spots = [] for contour in contours: x, y, w, h = cv2.boundingRect(contour) if w > 5 and h > 5: # Filter small noise spots.append((x, y, w, h)) return spots except Exception as e: print(f"Error in detect_spots: {e}") return [] def calculate_rf(spots, solvent_front_y, baseline_y): """ Calculate the Rf values for detected spots. """ try: rf_values = [] for _, y, _, _ in spots: distance_compound = y - baseline_y distance_solvent = solvent_front_y - baseline_y rf = distance_compound / distance_solvent if distance_solvent > 0 else 0 rf_values.append(round(rf, 2)) return rf_values except Exception as e: print(f"Error in calculate_rf: {e}") return [] def annotate_image(image, spots, rf_values): """ Annotate the image with detected spots and their Rf values. """ try: annotated_image = image.copy() for (x, y, w, h), rf in zip(spots, rf_values): if x < 0 or y < 0 or x + w > image.shape[1] or y + h > image.shape[0]: continue # Skip invalid spots # Annotate with Rf value cv2.putText( annotated_image, f"Rf={rf:.2f}", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1 ) # Draw rectangle around the spot cv2.rectangle(annotated_image, (x, y), (x + w, y + h), (0, 255, 0), 2) # Convert to RGB for Gradio compatibility annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB) return annotated_image except Exception as e: print(f"Error in annotate_image: {e}") return None def process_tlc(image): """ Process the TLC plate image and calculate Rf values. """ try: if image is None or not isinstance(image, np.ndarray): return "Error: Invalid image uploaded. Please try again with a valid image.", None # Detect baseline and solvent front baseline_y, solvent_front_y = detect_baseline_and_solvent_front(image) if baseline_y is None or solvent_front_y is None: return "Error: Unable to detect baseline or solvent front.", None # Detect spots on the TLC plate spots = detect_spots(image) if not spots: return "Error: No spots detected on the TLC plate.", None # Calculate Rf values rf_values = calculate_rf(spots, solvent_front_y, baseline_y) # Annotate the image with detected spots and Rf values annotated_image = annotate_image(image, spots, rf_values) if annotated_image is None: return "Error: Could not annotate the TLC plate image.", None # Generate a CSV report of Rf values report_data = {"Spot": list(range(1, len(spots) + 1)), "Rf Value": rf_values} report = pd.DataFrame(report_data).to_csv(index=False) return annotated_image, report except Exception as e: print(f"Error in process_tlc: {e}") return "Error: Processing failed. Check inputs and try again.", None # Define Gradio Interface interface = gr.Interface( fn=process_tlc, inputs=gr.Image(type="numpy", label="Upload TLC Plate Image"), outputs=[ gr.Image(type="numpy", label="Annotated TLC Plate"), gr.File(label="Download Rf Report (CSV)"), ], title="TLC Analyzer", description="Upload a TLC plate image to automatically calculate Rf values. " "The application detects the solvent front and baseline automatically.", ) if __name__ == "__main__": interface.launch()