如何将scikit-image轮廓按单顶点+轮廓编号存储到Pandas DataFrame
Got it, let's break down how to turn those watershed segmentation contours into a clean Pandas DataFrame with all the metadata you need—level, contour ID, and separate row/column indices for each vertex. Here's a practical, step-by-step solution tailored to scikit-image's workflow:
1. Import Required Libraries
First, make sure you have all the tools loaded:
import numpy as np import pandas as pd from skimage import data, filters, segmentation, measure from skimage.feature import peak_local_max
2. (Optional) Set Up a Sample Watershed Workflow
If you haven't already, here's a quick reproducible example of watershed segmentation to generate label data (replace this with your existing code):
# Use a sample image (swap with your own image) image = data.camera() # Denoise to clean up the image denoised = filters.rank.median(image, np.ones((3, 3))) # Generate distance transform for watershed distance = filters.distance_transform_edt(denoised) # Find local maxima to use as markers local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), labels=denoised) markers = measure.label(local_maxi) # Run watershed segmentation labels = watershed(-distance, markers, mask=denoised)
3. Convert Contours to Structured DataFrame
This is the core part—we'll iterate through each contour, split its vertex coordinates, and populate the DataFrame with all required columns:
# Initialize empty DataFrame with your desired columns contour_df = pd.DataFrame(columns=["level", "contour_id", "row_idx", "col_idx"]) # Track unique contour IDs across all levels contour_counter = 1 # Iterate through each non-background label (level) for level in np.unique(labels): if level == 0: # Skip the background label continue # Extract contours for the current level (convert to binary mask first) level_mask = labels == level contours = measure.find_contours(level_mask, level=0.5) # Process each contour in the current level for cnt in contours: # Split each vertex into row and column indices # Use np.round if you want integer indices (adjust if sub-pixel precision is needed) for row, col in cnt: contour_df.loc[len(contour_df)] = [ level, contour_counter, int(np.round(row)), int(np.round(col)) ] # Increment counter for the next contour contour_counter += 1
4. Verify the Result
Check the first few rows to make sure everything is structured correctly:
print(contour_df.head())
Sample output:
level contour_id row_idx col_idx 0 1 1 0 0 1 1 1 0 1 2 1 1 0 2 3 1 1 0 3 4 1 1 0 4
Key Notes & Customizations
- Sub-pixel Precision: If you need to keep the floating-point coordinates from
find_contours, just remove theint(np.round(...))wrapping. - Per-Level Contour Numbering: If you want contour IDs to reset to 1 for each level, move
contour_counter = 1inside thefor levelloop. - Column Names: Rename columns like
leveltohierarchy_levelorcontour_idtocontour_numberto match your naming convention. - Background Handling: We skipped label 0 (background) here—adjust if your workflow includes background contours.
内容的提问来源于stack exchange,提问作者MyCarta

