Как соединить все контуры? - PullRequest
1 голос
/ 12 февраля 2020

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

enter image description here

У меня есть пробовал дилатацию и морфологию близко, но у меня это не работает. Будем благодарны за любую помощь!

Ожидаемый результат:

enter image description here

1 Ответ

1 голос
/ 12 февраля 2020

Интенсивное использование np.where Входящие:

  • Подсчет ненулевых пикселей вдоль оси X. Получить y индексы всех строк с хотя бы одним ненулевым пикселем.
    • Первый индекс - ymin верхней строки.
    • Последний индекс - ymax нижней строки.
  • Рассчитать разницу между индексами y (используя np.diff) для различения gui sh целые строки (вместо строк).
    • Первый индекс (сопоставленный с индексами y) - ymax верхней строки.
    • Последний индекс (сопоставленный с индексами y + 1) - ymin нижней строки.
  • Сосредоточиться на верхней части изображения, получить минимальное и максимальное количество ненулевых пикселей, то есть xmin и xmax верхней линии.
  • Сосредоточиться на нижней строке image, получите минимальное и максимальное число ненулевых пикселей, то есть xmin и xmax нижней строки.

Это будет код (с использованием Python API):

import cv2
import numpy as np
from skimage import io              # Only needed for web reading images

# Web read image; use cv2.imread(...) for local images
img = cv2.cvtColor(io.imread('https://i.stack.imgur.com/S8xJr.jpg'), cv2.COLOR_RGB2BGR)

# Threshold grayscale version of image to get rid of JPG artifacts
img_thr = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 128, 255, cv2.THRESH_BINARY)[1]

# Determine min/max y values for both lines
y_idx = np.where(np.count_nonzero(img_thr, axis=1))[0]
line1_ymin = y_idx[0]
line2_ymax = y_idx[-1]
thr_inter_line = 10
yy_idx = np.where(np.diff(y_idx) > thr_inter_line)[0]
line1_ymax = y_idx[yy_idx[0]]
line2_ymin = y_idx[yy_idx[-1]+1]

# Determine min/max x values for both lines
line1_xmin = np.min(np.where(img_thr[line1_ymin:line1_ymax, :] == 255)[1])
line1_xmax = np.max(np.where(img_thr[line1_ymin:line1_ymax, :] == 255)[1])
line2_xmin = np.min(np.where(img_thr[line2_ymin:line2_ymax, :] == 255)[1])
line2_xmax = np.max(np.where(img_thr[line2_ymin:line2_ymax, :] == 255)[1])

# Draw rectangles for both lines
img_thr = cv2.rectangle(img_thr, (line1_xmin, line1_ymin), (line1_xmax, line1_ymax), 255, cv2.FILLED)
img_thr = cv2.rectangle(img_thr, (line2_xmin, line2_ymin), (line2_xmax, line2_ymax), 255, cv2.FILLED)

cv2.imshow('img', img)
cv2.imshow('img_thr', img_thr)
cv2.waitKey(0)
cv2.destroyAllWindows()

Это будет вывод:

Output

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

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
NumPy:       1.18.1
OpenCV:      4.2.0
----------------------------------------
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...