SpotSmartRf / app.py
SatyamSinghal's picture
Update app.py
74ed344 verified
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()