OpenCV фильтр изображения, сегментация, кластеризация
Есть вот такая картинка(см. цветную)
История происхождения картинки, есть 3D камера, она предаёт массив с координатами и расстояниями до каждой точки, чем число больше тем пиксель ближе к камере (на картинке чем больше пиксель тем он краснее)
С помощью фильтров я её преобразовываю в черно берую:
@dataclass
class Root:
lower_ = 510
upper_ = 530
se1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
se2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13))
def new_data(self):
for frame in glob.glob('\*npy'):
frame = np.load(frame)
frame2 = plt.cm.jet(norm(frame))
cv2.imshow('test', frame2)
threshold1 = cv2.threshold(frame, self.lower_, 65535, cv2.THRESH_BINARY_INV)[1]
threshold2 = cv2.threshold(frame, self.upper_, 65535, cv2.THRESH_BINARY)[1]
threshold = cv2.bitwise_or(threshold1, threshold2)
mask = cv2.morphologyEx(threshold, cv2.MORPH_OPEN, self.se1)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, self.se2)
Root().new_data()
Далее с помощью opencv(connected Components With Stats) нахожу центры объектов:
out_img =np.uint8(cv2.threshold(mask, 0, 65535, cv2.THRESH_BINARY_INV)[1])
output = cv2.connectedComponentsWithStats(out_img, 4, cv2.CV_32S)
(numLabels, labels, stats, centroids) = output
for i in centroids:
cv2.circle(out_img, (int(i[0]), int(i[1])), 7, (0, 0, 255), -1)
cv2.imshow('test3', out_img)
Но некоторые объекты(обвел красным) сливаются в один, чем я могу разделить их
Может быть есть аналоги connectedComponentsWithStats, или какие ещё фильтры можно добавить чтобы разделить объекты.
Сейчас как видно из кода использую перевод изображения в бинарный вид, морфологическое открытие и закрытие
На выходе хочу получить такую картинку чтобы opencv(connected Components With Stats) смог разделить объекты.
Ответы (1 шт):
Вот, значения в целом, не плохие, можете поиграться, сделать UH меньше, получить точки для него, а потом больше и точки для этого значения тоже и отфильтфомать, если точки слишком близки, или если одни точки выходят за пределы некоторой маски.
import numpy as np
import cv2 as cv
def nothing(x):
pass
cv.namedWindow("Tracking")
cv.createTrackbar("LH", "Tracking", 0, 255, nothing)
cv.createTrackbar("LS", "Tracking", 0, 255, nothing)
cv.createTrackbar("LV", "Tracking", 0, 255, nothing)
cv.createTrackbar("UH", "Tracking", 255, 255, nothing)
cv.createTrackbar("US", "Tracking", 255, 255, nothing)
cv.createTrackbar("UV", "Tracking", 255, 255, nothing)
cv.setTrackbarPos("LH", "Tracking", 0)
cv.setTrackbarPos("LS", "Tracking", 255)
cv.setTrackbarPos("LV", "Tracking", 129)
cv.setTrackbarPos("LH", "Tracking", 15)
cv.setTrackbarPos("LS", "Tracking", 255)
cv.setTrackbarPos("LV", "Tracking", 255)
path = ...
frame = np.array(cv.imread(path))
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
while 1:
l_h = cv.getTrackbarPos("LH", "Tracking")
l_s = cv.getTrackbarPos("LS", "Tracking")
l_v = cv.getTrackbarPos("LV", "Tracking")
u_h = cv.getTrackbarPos("UH", "Tracking")
u_s = cv.getTrackbarPos("US", "Tracking")
u_v = cv.getTrackbarPos("UV", "Tracking")
l_b = np.array([l_h, l_s, l_v])
u_b = np.array([u_h, u_s, u_v])
mask = cv.inRange(hsv, l_b, u_b)
res = cv.bitwise_and(frame, frame, mask=mask)
cv.imshow("frame", frame)
cv.imshow("mask", mask)
cv.imshow("res", res)
if cv.waitKey(1) & 0xFF == ord("q"):
cv.destroyAllWindows()
break
Дополнение с точками:
...
se1 = cv.getStructuringElement(cv.MORPH_ELLIPSE, (9, 9))
se2 = cv.getStructuringElement(cv.MORPH_ELLIPSE, (13, 13))
while 1:
...
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, se1)
mask = cv.morphologyEx(mask, cv.MORPH_CLOSE, se2)
out_img = np.uint8(cv.threshold(mask, 0, 65535, 0)[1])
output = cv.connectedComponentsWithStats(out_img, 4, cv.CV_32S)
(numLabels, labels, stats, centroids) = output
for i in centroids:
cv.circle(out_img, (int(i[0]), int(i[1])), 7, (0, 0, 255), -1)
cv.imshow('dots', out_img)
Я бы ещё подумал о нормализации интенсивности пикселей на результате применении маски и вторичном применении inRange
Напмриер
...
cv.createTrackbar("alpha", "Tracking", 511, 511, nothing)
cv.createTrackbar("beta", "Tracking", 0, 511, nothing)
...
original_frame = np.array(cv.imread(path))
...
while 1:
...
frame = cv.convertScaleAbs(original_frame,
alpha=cv.getTrackbarPos("alpha", "Tracking") / 100,
beta=cv.getTrackbarPos("beta", "Tracking") / 10)
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
И если поиграться, можно получить такое, например:
или такое




