У меня есть изображение, похожее на это, с некоторыми более крупными примесями/переэкспонированными пятнами. Как правило, не имеет значения, обнаружены ли они, поскольку измерения разрешены по времени, поэтому они будут удалены позже.
Тем не менее, меня интересуют как можно больше мелких точек - как можно быстрее. skimage.feature.peak_local_max
делает действительно хорошую работу и очень прост в использовании на разных данных, потому что нет необходимости много играть с масштабированием интенсивности.
Проблема в том, что большие пятна почему-то дают очень сильные положительные результаты.
import skimage.io
import skimage.feature
import skimage.morphology
from matplotlib.collections import PatchCollection
import matplotlib.pyplot as plt
def plotRoi(spots, img_ax, color, radius):
patches = []
for spot in spots:
y, x = spot
c = plt.Circle((x, y), radius)
patches.append(c)
img_ax.add_collection(PatchCollection(patches, facecolors = "None", edgecolors = color, alpha = 0.3, linewidths = 1))
img = skimage.io.imread("/Path/to/img.png")
img = img[:,:,0]
fig, ax = plt.subplots()
ax.imshow(img, cmap = "Greys")
spots = skimage.feature.peak_local_max(img, min_distance = 0, exclude_border = True, num_peaks = 2000)
plotRoi(spots, ax, "red", radius = 10)
plt.show()
И поиск тысяч пятен на некоторых изображениях приводит к большому количеству локальных максимумов, которые в значительной степени находятся на вершине друг друга. Есть ли способ избежать этого, например, путем применения фильтра при загрузке изображения, поскольку я бы предпочел не переходить к более медленному типу установки пика?
Проблема в том, что в областях пикселей с одинаковым значением есть пики. Один из способов решить это - объединить пики в центр масс этих регионов.
Ниже я воссоздаю проблему и решая ее, как указано.
import numpy as np
import matplotlib.pyplot as plt
from skimage.feature import peak_local_max
from scipy.ndimage.measurements import center_of_mass, label
# Generate test data with two peaks, one of which consists of two pixels of equal value
image = np.zeros((11,11),dtype=np.uint8)
image[5,3] = 128
image[5,2] = 255
image[5,7:9] = 255
image[6,8] = 128
# Finding peaks normally; results in three peaks
peaks = peak_local_max(image)
# Find peaks and merge equal regions; results in two peaks
is_peak = peak_local_max(image, indices=False) # outputs bool image
labels = label(is_peak)[0]
merged_peaks = center_of_mass(is_peak, labels, range(1, np.max(labels)+1))
merged_peaks = np.array(merged_peaks)
# Visualize the results
fig,(ax1,ax2)=plt.subplots(1,2)
ax1.imshow(image.T,cmap='gray')
ax1.plot(peaks[:,0],peaks[:,1],'ro')
ax2.imshow(image.T,cmap='gray')
ax2.plot(merged_peaks[:,0],merged_peaks[:,1],'ro')
Результат: