Spaces:
Sleeping
Sleeping
| 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() |