Перекрывающиеся контуры - PullRequest
       30

Перекрывающиеся контуры

0 голосов
/ 12 ноября 2019

Я пытаюсь нарисовать несколько контуров на изображении, и, безусловно, мне удалось нарисовать контуры, применяя различные пороговые значения. Единственная проблема заключается в том, что большинство контурных областей перекрываются, и я застрял здесь, как с этим справиться. В идеале я хотел бы, чтобы в случае совпадения он разделял контуры на отдельные области. Например, как в Концептуальном изображении , есть 4 области (контуры) оранжевого, зеленого, синего и черного цветов. Всякий раз, когда есть пересечение, это должно разделиться на фиолетовые области. Это кажется очень сложным, и я даже не уверен, возможно ли это. Если нет, я бы хотел, чтобы все перекрывающиеся слились. Может кто-нибудь помочь с тем, как решить эту проблему? Образец изображения

import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
im = cv.imread('images/sample.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret1, thresh1 = cv.threshold(imgray, 30, 80, 0)
ret2, thresh2 = cv.threshold(imgray, 80, 110, 0)
ret3, thresh3 = cv.threshold(imgray, 110, 150, 0)
ret4, thresh4 = cv.threshold(imgray, 150, 200, 0)
ret5, thresh5 = cv.threshold(imgray, 200, 255, 0)
_,contours1, hierarchy1 = cv.findContours(thresh1, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
_,contours2, hierarchy2 = cv2.findContours(thresh2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_,contours3, hierarchy3 = cv2.findContours(thresh3,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_,contours4, hierarchy4 = cv2.findContours(thresh4,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
_,contours5, hierarchy5 = cv2.findContours(thresh5,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)



cv2.drawContours(im, contours1, -1, (0, 0, 255), 1)
cv2.drawContours(im, contours2, -1, (0, 255, 0), 1)
cv2.drawContours(im, contours3, -1, (0, 0, 255), 1)
cv2.drawContours(im, contours4, -1, (10, 200, 200), 1)
cv2.drawContours(im, contours5, -1, (255, 255, 0), 1)

cv2.imshow("im",im)
cv2.waitKey(0)

1 Ответ

0 голосов
/ 12 ноября 2019

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

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Generate some dummy images, whose (main) contours overlap
img1 = cv2.circle(np.zeros((400, 400, 3), np.uint8), (150, 150), 100, (0, 255, 0), cv2.FILLED)
img2 = cv2.rectangle(np.zeros((400, 400, 3), np.uint8), (175, 175), (325, 325), (0, 0, 255), cv2.FILLED)

# Find contours (OpenCV 4.x)
contours1, _ = cv2.findContours(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours2, _ = cv2.findContours(cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Find contours (OpenCV 3.x)
#_, contours1, _ = cv2.findContours(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
#_, contours2, _ = cv2.findContours(cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Generate masks of (main) contours; Attention: Hard-coded selection of first contour here!
mask1 = cv2.drawContours(np.zeros((400, 400), np.uint8), [contours1[0]], -1, 255, cv2.FILLED)
mask2 = cv2.drawContours(np.zeros((400, 400), np.uint8), [contours2[0]], -1, 255, cv2.FILLED)

# Find intersection of both masks
mask_combined = cv2.bitwise_and(mask1, mask2)

# Generate "exclusive" masks, i.e. masks without the intersection parts
mask1_excl = cv2.bitwise_xor(mask1, mask_combined)
mask2_excl = cv2.bitwise_xor(mask2, mask_combined)

# Visualization
plt.figure()
plt.subplot(3, 3, 1), plt.imshow(img1), plt.ylabel('img1')
plt.subplot(3, 3, 2), plt.imshow(img2), plt.ylabel('img2')
plt.subplot(3, 3, 3), plt.imshow(img1 + img2), plt.ylabel('img1 + img2')
plt.subplot(3, 3, 4), plt.imshow(mask1, cmap='gray'), plt.ylabel('mask1')
plt.subplot(3, 3, 5), plt.imshow(mask2, cmap='gray'), plt.ylabel('mask2')
plt.subplot(3, 3, 6), plt.imshow(mask_combined, cmap='gray'), plt.ylabel('mask_combined')
plt.subplot(3, 3, 7), plt.imshow(mask1_excl, cmap='gray'), plt.ylabel('mask1_excl')
plt.subplot(3, 3, 8), plt.imshow(mask2_excl, cmap='gray'), plt.ylabel('mask2_excl')
plt.subplot(3, 3, 9), plt.imshow(mask_combined, cmap='gray'), plt.ylabel('mask_combined')
plt.show()

Визуализация:

Visualization

Теперь это должно быть сделано для каждого набора контуров - не только пар, поскольку вы можете иметь пересечения трех или более контуров. Отслеживание всех этих результирующих масок и т. Д., Скорее всего, будет занимать много памяти, но не слишком дорого в вычислительном отношении. В конце концов, все подходы так или иначе должны будут сохранять результирующие области как какие-то маски.

Надеюсь, это поможет!

...