我想使用 Python 找到显微图像中类似火山口的特征的中心和半径。
我需要中心在稍后的处理中创建径向轮廓。
到目前为止,我尝试简单地应用高度阈值,对图像进行二值化并仅保留最高特征,然后将圆形或椭圆形拟合到这些点。
我的问题是,有些图像不能很好地阈值化。较低和较高的阈值都会使圆形检测变得更糟。
我尝试使用 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()
以下代码应该可以帮助您进行分割
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()
电流输出: