У меня возникла проблема, когда я хочу идентифицировать разные кофейные зерна в смеси. Я создал нейронную сеть, которая способна идентифицировать разные бобы по отдельности. Но на практике я хочу разработать алгоритм, с помощью которого я смогу обнаруживать эти бобы в большей партии. Нет необходимости идентифицировать все бобы на картинке, но когда я могу идентифицировать 10-15 бобов в большей партии, этого будет достаточно.
Проблема теперь в том, что я могу сегментировать бобы, когда есть только один слой бобов с контрастным фоном, но когда под этим первым слоем есть несколько слоев бобов, это становится очень сложно.
Я попытался использовать преобразование расстояния и алгоритм водораздела из openCV, и, как уже упоминалось, это работало только для отдельных компонентов и для некоторого небольшого перекрытия между компонентами (как в этот пример). На рисунке ниже показаны результаты: результаты однослойной сегментации
Мой используемый код был основан на приведенном выше примере:
import cv2
import numpy as np
from matplotlib import pyplot as plt
from scipy.ndimage import label
from scipy.ndimage import morphology
# load the image as normal and grayscale
img_path = "FINAL/segmentation/IMG_6699.JPG"
img= cv.imread(img_path,0)
img0 = cv.imread(img_path)
#preprocess the image
img= cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,80,255,cv.THRESH_BINARY_INV)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(th1, cv2.MORPH_OPEN, kernel)
dilation = cv2.dilate(opening, None, iterations=2)
erosion = cv2.erode(dilation,kernel,iterations = 50)
border_nonseg = dilation - cv2.erode(dilation, None, iterations = 1)
#distance transform
#dt = morphology.distance_transform_bf(dilation, metric='chessboard')
dt = cv2.distanceTransform(dilation, 2, 5)
dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(np.uint8)
hier, dt1 = cv2.threshold(dt, 170, 255, cv2.THRESH_BINARY)
# label the centers found by the distance transform
lbl, ncc = label(dt1)
lbl = lbl * (255/ncc)
# Completing the markers now.
lbl[border_nonseg == 255] = 255
lbl = lbl.astype(np.int32)
# Watershed algorithm
cv2.watershed(img0, lbl)
lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
result = 255 - lbl
lbl_cont = result
# Draw the borders
result[result != 255] = 0
result = cv2.dilate(result, None, iterations=1)
img0[result == 255] = (255, 0, 0)
cv2.imwrite("output.png", img0)
contours, _ = cv.findContours(result, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
titles = ['Original Image', 'dilation',
'gradient morph', 'erode']
images = [ border_nonseg, dt, lbl_cont, img0]
plt.figure(figsize=(20,20))
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
Но проблема начинается, когда появляется такая картина (что является реальной ситуацией): многослойная сегментация и более жесткая многоуровневая сегментация
Я не думаю, что смогу повторно использовать код, упомянутый ранее, и мне нужен другой подход. Поскольку контраст между первым и вторым слоем слишком мал, из-за небольшого размера зерен они не создают большого оттенка, который дал бы хороший контраст, и цвет зерен также довольно темный, что не облегчает задачу.
Итак, есть ли у вас какие-либо предложения по различным подходам к решению этой проблемы или, возможно, корректировка текущего кода для решения моей проблемы?
Мне очень интересно услышать разные мнения по этому поводу!