基于二进制掩码多边形Delaunay三角剖分的植物叶片表面积计算技术求助(已实现RCNN分割与深度图生成)
Great approach with Delaunay triangulation—this is actually the standard way to compute surface area from irregular 3D point clouds, which is exactly what your masked leaf pixels paired with depth data amount to. Here's a practical Python implementation tailored to your workflow:
Step-by-Step Implementation
First, let's break down the process into actionable steps with code:
Extract 3D Point Cloud from Mask & Depth Data
Pull out all pixels that belong to the leaf (from your binary mask) and pair them with their corresponding depth values to form 3D points.Run Delaunay Triangulation
Usescipy's built-in Delaunay tool to triangulate the 2D pixel coordinates of the leaf—this creates a mesh of triangles that covers the leaf shape.Calculate Surface Area for Each Triangle
For every triangle in the mesh, compute its 3D surface area using vector cross products, then sum all these areas to get the total leaf surface area.
Full Code Example
import numpy as np from scipy.spatial import Delaunay # Load your actual data here (adjust paths/loading method to match your setup) binary_mask = np.load("leaf_mask.npy") # Shape: (H, W), 1 = leaf pixels depth_map = np.load("depth_map.npy") # Shape: (H, W), depth value per pixel # Step 1: Extract leaf 3D points # Get coordinates of all leaf pixels y_coords, x_coords = np.where(binary_mask == 1) # Pull corresponding depth values depth_values = depth_map[y_coords, x_coords] # Combine into 3D points (x, y, z) — adjust axis order if your coordinate system differs leaf_points_3d = np.stack([x_coords, y_coords, depth_values], axis=1) # Step 2: Perform Delaunay triangulation (on 2D pixel plane) triangulation = Delaunay(leaf_points_3d[:, :2]) # Step 3: Calculate total surface area total_area = 0.0 for triangle_indices in triangulation.simplices: # Get the 3D coordinates of the triangle's three vertices p1 = leaf_points_3d[triangle_indices[0]] p2 = leaf_points_3d[triangle_indices[1]] p3 = leaf_points_3d[triangle_indices[2]] # Compute edge vectors vec1 = p2 - p1 vec2 = p3 - p1 # Cross product gives a vector whose magnitude is twice the triangle's area cross_vec = np.cross(vec1, vec2) triangle_area = 0.5 * np.linalg.norm(cross_vec) total_area += triangle_area print(f"Total leaf surface area: {total_area:.2f}")
Key Notes for Accuracy
- Coordinate & Unit Consistency: If you need physical area (e.g., cm²), you'll need to convert pixel coordinates to real-world units using your camera's intrinsic parameters. Right now, this code calculates area in pixel-depth units—adjust
x_coordsandy_coordsby multiplying with your pixel's physical size (e.g., 0.1mm per pixel) first. - Noise Reduction: If your depth map has noise, run a Gaussian blur on the masked region before extracting points, or use
scipy.spatial.KDTreeto downsample the point cloud to avoid tiny, noisy triangles. - Mask Cleanup: Use morphological operations (like
cv2.morphologyExwith a small kernel) to fix holes or stray pixels in your binary mask—this prevents invalid triangulation results.
Once you share the masked RGB image, we can tweak things further (like handling overlapping leaves or refining the triangulation for complex leaf shapes).
内容的提问来源于stack exchange,提问作者Kail Kuhn

