OpenCV: контуры скрыты за маской. Как определить, когда контур приближается к краю маски? - PullRequest
0 голосов
/ 14 июня 2019

Краткое изложение вопроса

Я обнаруживаю силуэты объектов перед источником света. Чтобы упростить фон и убрать шум, мне нужно маскировать все, что не является источником света. Как определить, когда объект находится на краю маскируемой области?

Предположения

Предположим, что фигуры безликие (монохромный черно-белый для обнаружения краев) и неоднозначные (квадрат на изображении 1 может быть кружком на изображении 2) в форме.

Подробное объяснение проблемы с "высококачественными" рисунками

Рассмотрите силуэт перед источником света. Он различен, и мы можем сказать, что он вложен во внешний контур. На рисунке 1 изображен упрощенный случай.

Distinct Contour

В этом случае мы можем рассматривать наш внешний круг как маску и легко игнорировать все НЕ в контуре. На рисунке 2 изображен упрощенный случай с некоторым обнаружением края.

Contours are nice and simple here.  Huzzah.

Все работает прекрасно, пока силуэт не переместится к краю источника света. Внезапно мы сталкиваемся с проблемами. Рисунок 3 - пример формы на краю.

A silhouette is indistinguishable from the mask.

Силуэт неотличим от черного фона / замаскированной области. OpenCV также предполагает, что внезапно контур нашего источника света имеет забавную форму, и нет другого обнаруживаемого объекта.

Пересмотренный вопрос

Какими инструментами я могу воспользоваться, чтобы определить наличие какого-либо прерывания формы края? Есть ли хороший / дешевый способ определить, пересекается ли наш силуэт с другим?

Кладбище того, что я знаю, не работает

  • Предполагается статическая или простая форма силуэта. Цифры представляют собой мультфильмы, представляющие более сложную реальную проблему.
  • Предполагается, что источник света идеально круглый. HoughCircles не работает.

1 Ответ

0 голосов
/ 15 июня 2019

Вы можете использовать функцию cv2.log_polar, чтобы развернуть круг / овал.

log_polar

После этого, np.argmax может использоваться, чтобы найти кривую. Попробуйте сгладить кривую, используя Scipy's signal.savgol_filter(). Когда объект блокирует источник света, между сглаженной линией и данными argmax будет большая разница: graph

Это код, который я использовал:

import numpy as np
import cv2
# Read the image
img = cv2.imread('/home/stephen/Desktop/JkgJw.png', 0)
# Find the log_polar image
log_polar = cv2.logPolar(img, (img.shape[0]/2, img.shape[1]/2), 40, cv2.WARP_FILL_OUTLIERS)
# Create a background to draw on
bg = np.zeros_like(log_polar)
# Iterate through each row in the image and get the points on the edge
h,w = img.shape
points = []
for col in range(h-1):
    col_slice = log_polar[col:col+1, :]
    curve = np.argmax(255-col_slice)
    cv2.circle(bg, (curve, col), 0, 255, 1)
    points.append((curve, col))

cv2.imshow('log_polar', log_polar)
cv2.waitKey(0)
cv2.destroyAllWindows()


import scipy
from scipy import signal

x,y = zip(*points)
x_smooth = signal.savgol_filter(x,123,2)

import matplotlib.pyplot as plt
plt.plot(x)
plt.plot(x_smooth)
plt.show()
...