图像中土壤颗粒分水岭以外的替代分割技术

问题描述

我正在寻找一种替代方法来分割以下土壤颗粒图像中的颗粒,而不是 python 中的分水岭分割,因为它可能会误导对颗粒的正确检测此外,我正在研究边缘检测图像(使用 HED算法)如附件..我希望找到一种更好的方法来分割颗粒以进行进一步处理,因为我想在我的项目中获得图像中每个多边形的面积..提前致谢我也在询问随机游走器分割或任何其他可用方法.

解决方案

您可以尝试使用已实现为 Stats 的 Connected Components

每个对象的质心可以在centroid参数中找到,面积等其他信息可以在cv2.connectedComponentsWithStats返回的status变量中找到/代码>.这是标有每个多边形面积的图像.您可以使用最小阈值区域进行过滤以仅保留较大的多边形

代码

导入 cv2将 numpy 导入为 np# 加载图片,高斯模糊,灰度,Otsu的阈值图像 = cv2.imread('2.jpg')模糊 = cv2.GaussianBlur(图像, (3,3), 0)灰色 = cv2.cvtColor(模糊,cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(灰色, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]# 执行连通分量标注n_labels,标签,统计,质心 = cv2.connectedComponentsWithStats(阈值,连接 = 4)# 创建假彩色图像和背景颜色为黑色颜色 = np.random.randint(0, 255, size=(n_labels, 3), dtype=np.uint8)colors[0] = [0, 0, 0] # 出于美观的原因,我们希望背景为黑色false_colors = 颜色[标签]# 每个多边形的标注区域false_colors_area = false_colors.copy()对于 i,枚举中的质心(质心 [1:],开始 = 1):面积 = 统计[i, 4]cv2.putText(false_colors_area, str(area), (int(centroid[0]), int(centroid[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 1)cv2.imshow('thresh', thresh)cv2.imshow('false_colors', false_colors)cv2.imshow('false_colors_area', false_colors_area)cv2.waitKey()

I am searching for an alternative way for segmenting the grains in the following image of soil grains other than watershed segmentation in python as it may mislead the right detection for the grains furthermore , I am working on the edge detection image ( using HED algorithm ) as attached .. I hope to find a better way to segment the grains for further processing as I would like to get the area of each polygon in the image in my project .. Thanks in advance I am asking also about random walker segmentation or any other available method.

解决方案

You could try using Connected Components with Stats already implemented as cv2.connectedComponentsWithStats to perform component labeling. Using your binary image as input, here's the false-color image:

The centroid of each object can be found in centroid parameter and other information such as area can be found in the status variable returned from cv2.connectedComponentsWithStats. Here's the image labeled with the area of each polygon. You could filter using a minimum threshold area to only keep larger polygons

Code

import cv2
import numpy as np

# Load image, Gaussian blur, grayscale, Otsu's threshold
image = cv2.imread('2.jpg')
blur = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Perform connected component labeling
n_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=4)

# Create false color image and color background black
colors = np.random.randint(0, 255, size=(n_labels, 3), dtype=np.uint8)
colors[0] = [0, 0, 0]  # for cosmetic reason we want the background black
false_colors = colors[labels]

# Label area of each polygon
false_colors_area = false_colors.copy()
for i, centroid in enumerate(centroids[1:], start=1):
    area = stats[i, 4]
    cv2.putText(false_colors_area, str(area), (int(centroid[0]), int(centroid[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 1)

cv2.imshow('thresh', thresh)
cv2.imshow('false_colors', false_colors)
cv2.imshow('false_colors_area', false_colors_area)
cv2.waitKey()

相关文章