Вот мой код:
Код: Выделить всё
import cv2
import numpy as np
import matplotlib.pyplot as plt
# === Load and preprocess image ===
image = cv2.imread('GF sample/4.jpg') # ⬅️ Load input image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Convert to grayscale
blur = cv2.GaussianBlur(gray, (11, 11), 0) # Apply Gaussian blur to reduce noise
canny = cv2.Canny(blur, 10, 150, 3) # Edge detection using Canny
dilated = cv2.dilate(canny, (1, 1), iterations=0) # Slightly enhance edges
# === Image dimensions ===
height, width = gray.shape
# === Find external contours ===
cnts, hierarchy = cv2.findContours(
dilated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# === Calibration (based on your scale)
MICRONS_PER_PIXEL = 1.585 # ⬅️ Adjust based on scale bar (1000 µm = 631 px)
# === Filtering thresholds
MIN_AREA = 1 # Eliminate tiny specks
MIN_WIDTH_HEIGHT = 15 # Filter very small bounding boxes
MARGIN = 5 # Avoid counting fibers near the image border
# === Output image and result storage
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
font = cv2.FONT_HERSHEY_SIMPLEX
filtered_cnt = []
fiber_lengths_um = []
# === Loop through contours and apply filters
for c in cnts:
area = cv2.contourArea(c)
x, y, w, h = cv2.boundingRect(c)
if (area > MIN_AREA and
w > MIN_WIDTH_HEIGHT and h > MIN_WIDTH_HEIGHT and
x > MARGIN and y > MARGIN and
(x + w) < (width - MARGIN) and
(y + h) < (height - MARGIN)):
# Keep only filtered contours
filtered_cnt.append(c)
# Estimate length using minAreaRect
rect = cv2.minAreaRect(c)
(w_rect, h_rect) = rect[1]
length_px = max(w_rect, h_rect)
real_length_um = length_px * MICRONS_PER_PIXEL
fiber_lengths_um.append(real_length_um)
# === Label and draw only the accepted contours ===
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.5
thickness = 1
color = (255, 0, 0) # red
for i, c in enumerate(filtered_cnt, 1):
M = cv2.moments(c)
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
# Draw contour
cv2.drawContours(rgb, [c], -1, (0, 255, 0), 1)
# Get label text size
label = str(i)
(text_width, text_height), baseline = cv2.getTextSize(label, font, font_scale, thickness)
# Shift to center
text_x = int(cx - text_width / 2)
text_y = int(cy + text_height / 2)
# Draw label centered
cv2.putText(rgb, label, (text_x, text_y), font, font_scale, color, thickness)
# === Show results ===
plt.figure(figsize=(14, 10))
plt.imshow(rgb)
plt.title(f" Counted Glass Fibers: {len(filtered_cnt)}")
plt.axis('off')
plt.show()
# === Print lengths of fibers ===
print("\n📏 List of Detected Fibers (µm):")
for idx, length in enumerate(fiber_lengths_um, 1):
print(f"{idx}. {length:.2f} µm")
# === Summary statistics ===
print(f"\n📊 Total detected: {len(filtered_cnt)} fibers")
print(f"📉 Min: {min(fiber_lengths_um):.2f} µm")
print(f"📈 Max: {max(fiber_lengths_um):.2f} µm")
print(f"📌 Average: {np.mean(fiber_lengths_um):.2f} µm")

Подробнее здесь: https://stackoverflow.com/questions/797 ... the-images