Определить вогнутую точку - PullRequest
       0

Определить вогнутую точку

0 голосов
/ 22 сентября 2018

Если я использую goodFeaturesToTrack, я могу получить все угловые точки (красный, синий).Однако я хочу сохранить только вогнутые точки (синие).Я понятия не имею, как реализовать.Как я могу это сделать?

enter image description here enter image description here

Следующее изображение является действующим рабочим образцом: enter image description here

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Как уже упоминалось в комментариях, кажется, что здесь проще всего сделать так, чтобы свертить ваше изображение с помощью блочного фильтра (или аналогичного, но с эллиптической формой), который даст вам оконные средние по всему изображению.Вы можете просто индексировать этот результат свертки в ваших угловых точках.Если результат свертки в этих точках превышает 50%, вокруг этой точки больше белого, следовательно, это вогнутая точка.В противном случае он выпуклый.Вот как это может выглядеть в коде.

import cv2
import numpy as np
from itertools import tee

def pairwise(iterable):
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

# read image as grayscale
img = cv2.imread('example.png', 0)

# get corner points, remove duplicate/nearby points
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
contour = contours[0]
pts = np.array([contour[0]] + [pt1 for pt0, pt1 in pairwise(contour) if not (abs(pt0 - pt1) <= 1).all()])
x, y = pts[:, -1, 0], pts[:, -1, 1]

# get the kernel that you will sum around your corner points
kernel = np.float64(cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13)))
kernel /= np.sum(kernel)

# convolve the image with the kernel, and pull out the sums at the corner points
conv = cv2.filter2D(img/255, cv2.CV_64F, kernel)
neighborhood_sums = conv[y, x]

# concave indices have more white than black around them, so convolution will be >= 1/2
concave_indices = neighborhood_sums >= 0.5

# draw markers
marked = cv2.merge([img, img, img])
for pt, concave in zip(pts, concave_indices):
    color = (255, 0, 255) if concave else (0, 255, 0)
    marker = cv2.MARKER_TRIANGLE_UP if concave else cv2.MARKER_TRIANGLE_DOWN
    cv2.drawMarker(marked, tuple(pt[0]), color, markerType=marker, markerSize=10, thickness=3)

После импорта я определил один из itertools рецептов для итерации в парах (например, s -> (s0, s1), (s1, s2), ...).Это не очень важно для проблемы, но просто полезно для меня, чтобы избавиться от повторяющихся точек, которые были получены из findContours().После этого все остальное продолжается, как описано ранее.Вы можете нарисовать свое собственное ядро ​​или что угодно, но я только что вытащил одно из getStructuringElement(), так как вы можете делать эллипсы произвольного размера (хотя обратите внимание, что это возвращает ядро ​​странной формы, вы, вероятно, могли бы определить круг лучше).Обратите внимание, что размер ядра здесь указывается в общей ширине, а не просто в радиусе, и он нормализуется числом 1 в нем, так что результат всегда находится между 0 и 1.

А вот результатвыше на вашем первом изображении:

Marked concave vs convex points

0 голосов
/ 22 сентября 2018

Одно из решений это использовать HIT_MISS_MORPH в разных ядрах:

Если вы выберете это ядро:

[[-1 -1  1]
 [-1 -1  1]
 [ 1  1  1]]

Тогда сделайте hitmiss для обмолоченного изображения, вы можете получить дваякоря:

mask = cv2.morphologyEx(threshed, cv2.MORPH_HITMISS, kernel, anchor=(-1,-1))

enter image description here

Рисуем на исходном изображении:

enter image description here


Найдены якоря в разных ядрах (поверните основное ядро ​​и | или переверните его):

enter image description here

Отображение в цветах на источникеизображение:

enter image description here

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