Определить ширину объектов на изображении - PullRequest
3 голосов
/ 16 мая 2019

У меня есть изображения, подобные следующим (это выходные данные UNET на исходном изображении):

example1, example2, example3

Я думал, что сегментирование исходного изображения было трудной задачей, но я боролся со следующей задачей: для каждого изображения необходимо вычислить ширину зеленой области в соответствии с красной, как показано ниже:

distance1, distance2, distance3

Что я пытался сделать:

Обнаружение краев зеленой зоны было простым. Затем я нашел линии в полярных координатах через преобразование Хафа:

image = cv2.imread("../../../../example_1.png")
image[:, :, 2] = 0
canny = cv2.Canny(image, 150, 250, 3)
lines = cv2.HoughLinesP(canny, cv2.HOUGH_PROBABILISTIC, np.pi/180, 20)
for line in lines:
    for x0, y0, x1, y1 in line:
        cv2.line(image, (x0,y0), (x1,y1), (255, 255, 255), 1)

fig = plt.figure(figsize = (15, 10))
fig.add_subplot(1, 2, 1).set_title("canny")
plt.imshow(canny, cmap = "gray")
fig.add_subplot(1, 2, 2).set_title("lines")
plt.imshow(image)

Что дает:

cannyplushough

Как видите, есть много строк кандидатов (много ложных срабатываний), и я изо всех сил стараюсь сохранить те, которые мне нужны. Кроме того: Как бы вы рассчитали ширину?

Используя грубые линии в полярных координатах, я смог получить угол, который каждая линия имеет с началом оси, поэтому для вычисления ширины я должен найти пару параллельных линий (одинаковый угол или почти одинаковый угол) с разным расстоянием от происхождение. Я не уверен, что это лучший подход.

Спасибо за помощь

1 Ответ

2 голосов
/ 19 мая 2019

Как подсказал @Micka, вы можете использовать cv2.minAreaRect для этого.Для этого вы можете применить простой порог на двух красных и зеленых плоскостях с последующей оценкой контура.Затем можно взять самые большие контуры и найти самый маленький прямоугольник по площади.Используя его координаты, можно рассчитать высоту и ширину, а затем их соотношение.Код

img = cv2.imread('red_green.png')
red = img[:, :, 2] # to segment out red area
green = img[:, :, 1] # to segment out green are
ret, thresh1 = cv2.threshold(red, 5, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(green, 5, 255, cv2.THRESH_BINARY)
_, cnts1, _ = cv2.findContours(thresh1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_, cnts2, _ = cv2.findContours(thresh2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
c1 = max(cnts1, key = cv2.contourArea)
c2 = max(cnts2, key = cv2.contourArea)
rect1 = cv2.minAreaRect(c1)
rect2 = cv2.minAreaRect(c2)
box1 = cv2.boxPoints(rect1)
box2 = cv2.boxPoints(rect2)
box1 = np.int0(box1)
box2 = np.int0(box2)
cv2.drawContours(img, [box1], 0, (0, 255, 255), 2)
cv2.drawContours(img, [box2], 0, (0, 255, 255), 2)
(p1, p2, p3, p4) = box1 # Unpacking tuple
h1 = (((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)**0.5) # calculating width by calculating distance
w1 = (((p2[0]-p3[0])**2 + (p2[1]-p3[1])**2)**0.5) # calculating height by calculating distance
(p1, p2, p3, p4) = box2 # Unpacking tuple
h2 = (((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)**0.5) # calculating width by calculating distance
w2 = (((p2[0]-p3[0])**2 + (p2[1]-p3[1])**2)**0.5) # calculating height by calculating distance
rofh = h2/h1
rofw = w2/w1
print("ratio of height = ", rofh, "and ratio by width = ", rofw)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Полученное изображение:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...