Download app.py from ibrahim313/Bioengineering_Query_Tool_image_based: direct link, hf CLI and curl.
- Browser
- Download file 3.66 kB
-
https://huggingface.co/spaces/ibrahim313/Bioengineering_Query_Tool_image_based/resolve/77020600df0b29ff780d9dc92ec31ebeb5cc05ea/app.py
- Command line
-
hf download hf://spaces/ibrahim313/Bioengineering_Query_Tool_image_based@77020600df0b29ff780d9dc92ec31ebeb5cc05ea/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ibrahim313/Bioengineering_Query_Tool_image_based/resolve/77020600df0b29ff780d9dc92ec31ebeb5cc05ea/app.py
3.66 kB
| import cv2 | |
| import numpy as np | |
| import pandas as pd | |
| import gradio as gr | |
| import matplotlib.pyplot as plt | |
| from datetime import datetime | |
| def preprocess_image(image): | |
| """Enhance image contrast, apply thresholding, and clean noise.""" | |
| if len(image.shape) == 2: | |
| image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) | |
| gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) | |
| # Apply Gaussian blur to remove noise | |
| blurred = cv2.GaussianBlur(gray, (5, 5), 0) | |
| # Otsu's Thresholding (more robust than adaptive for blood cells) | |
| _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) | |
| # Morphological operations to improve segmentation | |
| kernel = np.ones((3, 3), np.uint8) | |
| clean_mask = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2) | |
| clean_mask = cv2.morphologyEx(clean_mask, cv2.MORPH_OPEN, kernel, iterations=1) | |
| return clean_mask | |
| def detect_blood_cells(image): | |
| """Detect blood cells and extract features.""" | |
| mask = preprocess_image(image) | |
| contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| features = [] | |
| total_area = 0 | |
| for i, contour in enumerate(contours, 1): | |
| area = cv2.contourArea(contour) | |
| perimeter = cv2.arcLength(contour, True) | |
| circularity = (4 * np.pi * area / (perimeter * perimeter)) if perimeter > 0 else 0 | |
| # Filtering: Only count reasonable-sized circular objects | |
| if 100 < area < 5000 and circularity > 0.7: | |
| M = cv2.moments(contour) | |
| if M["m00"] != 0: | |
| cx = int(M["m10"] / M["m00"]) | |
| cy = int(M["m01"] / M["m00"]) | |
| features.append({ | |
| 'ID': i, 'Area': area, 'Perimeter': perimeter, | |
| 'Circularity': circularity, 'Centroid_X': cx, 'Centroid_Y': cy | |
| }) | |
| total_area += area | |
| # Summary Statistics | |
| avg_cell_size = total_area / len(features) if features else 0 | |
| cell_density = len(features) / (image.shape[0] * image.shape[1]) # Density per pixel | |
| summary = { | |
| 'Total Cells': len(features), | |
| 'Avg Cell Size': avg_cell_size, | |
| 'Cell Density': cell_density | |
| } | |
| return contours, features, mask, summary | |
| def process_image(image): | |
| if image is None: | |
| return None, None, None, None, None | |
| contours, features, mask, summary = detect_blood_cells(image) | |
| vis_img = image.copy() | |
| for feature in features: | |
| contour = contours[feature['ID'] - 1] | |
| cv2.drawContours(vis_img, [contour], -1, (0, 255, 0), 2) | |
| cv2.putText(vis_img, str(feature['ID']), (feature['Centroid_X'], feature['Centroid_Y']), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1) | |
| df = pd.DataFrame(features) | |
| return vis_img, mask, df, summary | |
| def analyze(image): | |
| vis_img, mask, df, summary = process_image(image) | |
| plt.style.use('dark_background') | |
| fig, axes = plt.subplots(1, 2, figsize=(12, 5)) | |
| if not df.empty: | |
| axes[0].hist(df['Area'], bins=20, color='cyan', edgecolor='black') | |
| axes[0].set_title('Cell Size Distribution') | |
| axes[1].scatter(df['Area'], df['Circularity'], alpha=0.6, c='magenta') | |
| axes[1].set_title('Area vs Circularity') | |
| return vis_img, mask, fig, df, summary | |
| # Gradio Interface | |
| demo = gr.Interface( | |
| fn=analyze, | |
| inputs=gr.Image(type="numpy"), | |
| outputs=[ | |
| gr.Image(label="Processed Image"), | |
| gr.Image(label="Binary Mask"), | |
| gr.Plot(label="Analysis Plots"), | |
| gr.Dataframe(label="Detected Cells Data"), | |
| gr.JSON(label="Summary Statistics") | |
| ] | |
| ) | |
| demo.launch() | |