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()