检测显微图像中陨石坑的中心和半径

问题描述 投票:0回答:1

我想使用 Python 找到显微图像中类似火山口的特征的中心和半径。

我有这样的图像,它们是代表表面高度图的 numpy 数组。

我需要中心在稍后的处理中创建径向轮廓。

到目前为止,我尝试简单地应用高度阈值,对图像进行二值化并仅保留最高特征,然后将圆形或椭圆形拟合到这些点。

我的问题是,有些图像不能很好地阈值化。较低和较高的阈值都会使圆形检测变得更糟。

我尝试使用 Canny,但没有取得太大成功。

如何正确检测这些圆圈?

这是到目前为止的代码:

from skimage.measure import EllipseModel, CircleModel
from skimage.draw import ellipse_perimeter, circle_perimeter
import numpy as np
import diplib as dip
import matplotlib.pyplot as plt
from pathlib import Path

base_path = Path("folder including multiple images")

glob = base_path.rglob("*_f.npz")

for file in glob:
    image_grey: np.ndarray = np.load(file)["arr_0"]

    max_peak = image_grey.max()
    min_peak = image_grey.min()

    # i adjust the value at the end here to set a certain threshold
    threshold = max_peak - (max_peak-min_peak)*0.3

    rim_binarized = image_grey>=threshold
    points = np.argwhere(rim_binarized)

    ell = EllipseModel()
    succ = ell.estimate(points)
    print(succ)
    ye, xe, a, b = (int(round(x)) for x in ell.params[:-1])
    ey, ex = ellipse_perimeter(ye,xe,a,b,ell.params[-1])

    circ = CircleModel()
    circ.estimate(points)
    yc, xc, r = (int(round(x)) for x in circ.params)
    cy, cx = circle_perimeter(yc,xc,r)

    fig2, (ax1, ax2, ax3) = plt.subplots(ncols=3, nrows=1, figsize=(12, 4),
                                    sharex=False, sharey=False)

    ax1.set_title('Original picture')
    ax1.imshow(image_grey)
    ax1.plot(cx,cy, "r,")
    ax1.plot(ex,ey, "m,")

    ax2.set_title('Rim')
    ax2.imshow(rim_binarized, cmap="Greys")

    dipimg = dip.Image(image_grey)

    ax3.set_title("Ridge")
    rad = dip.RadialMean(dipimg, binSize=1, center=(ye,xe), maxRadius="inner radius")
    ax3.plot(rad, label="ellipse")
    rad = dip.RadialMean(dipimg, binSize=1, center=(yc,xc), maxRadius="inner radius")
    ax3.plot(rad, label="circle")

    plt.show()
python image-processing feature-detection
1个回答
0
投票

以下代码应该可以帮助您进行分割

import numpy as np
import matplotlib.pyplot as plt
import cv2
 

 
# Read in the image
image = cv2.imread(r"C:\Users\shorokhovi\Downloads\deGSv.png")
 
# Change color to RGB (from BGR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
 
# Reshaping the image into a 2D array of pixels and 3 color values (RGB)
pixel_vals = image.reshape((-1,3))
 
# Convert to float type
pixel_vals = np.float32(pixel_vals)

#the below line of code defines the criteria for the algorithm to stop running, 
#which will happen is 100 iterations are run or the epsilon (which is the required accuracy) 
#becomes 85%
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.85)
 
# then perform k-means clustering with number of clusters defined as 3
#also random centres are initially choosed for k-means clustering
k = 2
retval, labels, centers = cv2.kmeans(pixel_vals, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
 
# convert data into 8-bit values
centers = np.uint8(centers)
segmented_data = centers[labels.flatten()]
 
# reshape data into the original image dimensions
segmented_image = segmented_data.reshape((image.shape))
 

gray = cv2.cvtColor(segmented_image, cv2.COLOR_BGR2GRAY) # convert to grayscale
blur = cv2.GaussianBlur(gray, (3, 3), 0)
# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)
kernel = np.ones((5, 5), np.uint8) 
  
# The first parameter is the original image, 
# kernel is the matrix with which image is 
# convolved and third parameter is the number 
# of iterations, which will determine how much 
# you want to erode/dilate a given image. 
img_erosion = cv2.erode(blur, kernel, iterations=1) 


plt.imshow(img_erosion)
plt.show()

电流输出:

© www.soinside.com 2019 - 2024. All rights reserved.