File size: 2,499 Bytes
e6748e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import cv2
import numpy as np
import pandas as pd
import streamlit as st

def calculate_parameters(annotations, scale_factor):
    """Calculates parameters for each segmented object, including Feret diameter."""
    df = pd.DataFrame(columns=['Object', 'Area', 'Perimeter', 'Roundness', 
                                'Aspect Ratio (Elongation)', 'Longest Feret Diameter'])
    if len(annotations) > 0:
        for i, mask in enumerate(annotations):
            binary_mask = mask.cpu().numpy().astype(np.uint8)
            area_pixel = np.sum(binary_mask)
            area_micron = area_pixel * (scale_factor ** 2)

            # Find contours with all points (no approximation)
            contours, _ = cv2.findContours(binary_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

            if contours:  # Check if any contours were found
                perimeter_pixel = cv2.arcLength(contours[0], True)
                perimeter_micron = perimeter_pixel * scale_factor

                # Fit ellipse for roundness and aspect ratio (check for sufficient points)
                if len(contours[0]) >= 5:
                    ellipse = cv2.fitEllipse(contours[0])
                    major_axis, minor_axis = ellipse[1]
                else:
                    major_axis = minor_axis = 0

                major_axis_micron = major_axis * scale_factor
                minor_axis_micron = minor_axis * scale_factor
                roundness = (4 * np.pi * area_micron) / (perimeter_micron ** 2)
                aspect_ratio = major_axis_micron / minor_axis_micron if minor_axis_micron != 0 else "Undefined"

                # Calculate Feret diameter and Elongation
                hull = cv2.convexHull(contours[0])
                distances = np.linalg.norm(hull - hull[:, 0, :], axis=2)
                max_feret_diameter_micron = np.max(distances) * scale_factor

                new_row = pd.DataFrame({
                    'Object': [f"Object {i}"],
                    'Area': [area_micron],
                    'Perimeter': [perimeter_micron],
                    'Roundness': [roundness],
                    'Aspect Ratio (Elongation)': [aspect_ratio],
                    'Longest Feret Diameter': [max_feret_diameter_micron],
                })
                df = pd.concat([df, new_row], ignore_index=True)

        # Eliminate artifacts with undefined parameters
        df = df[(df['Longest Feret Diameter'] != 0) & (df['Roundness'] >= 0) & (df['Roundness'] <= 1)]

    return df