ibrahim313's picture
Update app.py
b5ba092 verified
raw
history blame
8.76 kB
import cv2
import numpy as np
import pandas as pd
import gradio as gr
from skimage import morphology, segmentation
import matplotlib.pyplot as plt
from datetime import datetime
def enhanced_preprocessing(image):
"""Advanced image preprocessing pipeline"""
# Convert to LAB color space for better color separation
lab = cv2.cvtColor(image, cv2.COLOR_RGB2LAB)
# CLAHE on L-channel
l_channel = lab[:,:,0]
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
lab[:,:,0] = clahe.apply(l_channel)
# Convert back to RGB
enhanced = cv2.cvtColor(lab, cv2.COLOR_LAB2RGB)
# Edge-preserving smoothing
filtered = cv2.bilateralFilter(enhanced, 9, 75, 75)
return filtered
def detect_cells(image):
"""Advanced cell detection using multiple techniques"""
# Enhanced preprocessing
processed = enhanced_preprocessing(image)
# Convert to grayscale
gray = cv2.cvtColor(processed, cv2.COLOR_RGB2GRAY)
# Adaptive thresholding
binary = cv2.adaptiveThreshold(gray, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 21, 4)
# Morphological operations
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
cleaned = morphology.area_opening(binary, area_threshold=128)
cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, kernel, iterations=2)
# Watershed segmentation for overlapping cells
distance = cv2.distanceTransform(cleaned, cv2.DIST_L2, 3)
_, sure_fg = cv2.threshold(distance, 0.5*distance.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
# Marker labeling
_, markers = cv2.connectedComponents(sure_fg)
markers += 1 # Add one to all labels
markers[cleaned == 0] = 0 # Set background to 0
# Apply watershed
segmented = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
markers = segmentation.watershed(segmented, markers)
# Find contours from markers
contours = []
for label in np.unique(markers):
if label < 1: # Skip background
continue
mask = np.zeros(gray.shape, dtype="uint8")
mask[markers == label] = 255
cnts, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours.extend(cnts)
return contours, cleaned
def feature_analysis(contours, image):
"""Comprehensive feature extraction and validation"""
features = []
for i, contour in enumerate(contours, 1):
area = cv2.contourArea(contour)
perimeter = cv2.arcLength(contour, True)
# Improved circularity calculation
circularity = (4 * np.pi * area) / (perimeter**2 + 1e-6)
# Advanced shape validation
if 50 < area < 10000 and 0.4 < circularity < 1.2:
M = cv2.moments(contour)
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
# Convexity check
hull = cv2.convexHull(contour)
hull_area = cv2.contourArea(hull)
convexity = area / hull_area if hull_area > 0 else 0
features.append({
'Cell ID': i,
'Area (px²)': area,
'Perimeter (px)': perimeter,
'Circularity': round(circularity, 3),
'Convexity': round(convexity, 3),
'Centroid X': cx,
'Centroid Y': cy
})
return features
def visualize_results(image, contours, features):
"""Enhanced visualization with better annotations"""
vis_img = image.copy()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Draw refined contours
for idx, feature in enumerate(features):
contour = contours[idx]
cv2.drawContours(vis_img, [contour], -1, (0, 255, 0), 2)
# Improved annotation placement
x, y = feature['Centroid X'], feature['Centroid Y']
cv2.putText(vis_img, str(feature['Cell ID']),
(x+5, y-5), cv2.FONT_HERSHEY_SIMPLEX,
0.6, (255, 255, 255), 3)
cv2.putText(vis_img, str(feature['Cell ID']),
(x+5, y-5), cv2.FONT_HERSHEY_SIMPLEX,
0.6, (0, 0, 255), 2)
# Add enhanced overlay
cv2.putText(vis_img, f"Cells Detected: {len(features)} | {timestamp}",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0, 0, 0), 3)
cv2.putText(vis_img, f"Cells Detected: {len(features)} | {timestamp}",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (255, 255, 255), 2)
return vis_img
def process_image(image, transform_type):
"""Upgraded image processing pipeline"""
if image is None:
return None, None, None, None
try:
original = image.copy()
contours, mask = detect_cells(image)
features = feature_analysis(contours, image)
vis_img = visualize_results(image, contours, features)
# Create analysis plots
plt.style.use('seaborn-v0_8')
fig, ax = plt.subplots(2, 2, figsize=(15, 12))
fig.suptitle('Advanced Cell Analysis', fontsize=16)
df = pd.DataFrame(features)
if not df.empty:
ax[0,0].hist(df['Area (px²)'], bins=30, color='#1f77b4', ec='black')
ax[0,0].set_title('Area Distribution')
ax[0,1].scatter(df['Circularity'], df['Convexity'],
c=df['Area (px²)'], cmap='viridis', alpha=0.7)
ax[0,1].set_title('Shape Correlation')
ax[1,0].boxplot([df['Area (px²)'], df['Circularity']],
labels=['Area', 'Circularity'])
ax[1,0].set_title('Feature Distribution')
ax[1,1].hexbin(df['Centroid X'], df['Centroid Y'],
gridsize=20, cmap='plasma', bins='log')
ax[1,1].set_title('Spatial Distribution')
plt.tight_layout()
return (
vis_img,
apply_color_transformation(original, transform_type),
fig,
df
)
except Exception as e:
print(f"Error: {str(e)}")
return None, None, None, None
# Create Gradio interface
with gr.Blocks(title="Advanced Cell Analysis Tool", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🔬 Advanced Bioengineering Cell Analysis Tool
## Features
- 🔍 Automated cell detection and measurement
- 📊 Comprehensive statistical analysis
- 🎨 Multiple visualization options
- 📥 Downloadable results
## Author
- **Muhammad Ibrahim Qasmi**
- [LinkedIn](https://www.linkedin.com/in/muhammad-ibrahim-qasmi-9876a1297/)
""")
with gr.Row():
with gr.Column(scale=1):
input_image = gr.Image(
label="Upload Image",
type="numpy"
)
transform_type = gr.Dropdown(
choices=["Original", "Grayscale", "Binary", "CLAHE"],
value="Original",
label="Image Transform"
)
analyze_btn = gr.Button(
"Analyze Image",
variant="primary",
size="lg"
)
with gr.Column(scale=2):
with gr.Tabs():
with gr.Tab("Analysis Results"):
output_image = gr.Image(
label="Detected Cells"
)
gr.Markdown("*Green contours show detected cells, red numbers are cell IDs*")
with gr.Tab("Image Transformations"):
transformed_image = gr.Image(
label="Transformed Image"
)
gr.Markdown("*Select different transformations from the dropdown menu*")
with gr.Tab("Statistics"):
output_plot = gr.Plot(
label="Statistical Analysis"
)
gr.Markdown("*Hover over plots for detailed values*")
with gr.Tab("Data"):
output_table = gr.DataFrame(
label="Cell Features"
)
analyze_btn.click(
fn=process_image,
inputs=[input_image, transform_type],
outputs=[output_image, transformed_image, output_plot, output_table]
)
# Launch the demo
if __name__ == "__main__":
demo.launch()