Получить границу от хитрых краев и удалить фон изображения - PullRequest
2 голосов
/ 29 октября 2019

Я пытаюсь удалить фон изображения, с которым я пытаюсь обучить нейронную сеть. Мне немного повезло, используя метод, описанный здесь ( Как убрать фон из этого вида изображения? ), но я смог использовать Canny Edge Detector, чтобы получить полу-хорошее "Граница "объекта в моем изображении. Вот мой код, который я использую

import cv2 as cv, sys, numpy as np, PIL.Image, matplotlib.pylab as plt

# read command-line arguments
filename = '/Users/colew/Desktop/Good_Cups_Frames/frame_IMG_2057.MOV_0.jpg'

img = cv.imread(filename,0)
edges = cv.Canny(img,25,200)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.savefig("pic")
plt.show()

, и получаемые изображения получаются

enter image description here

Так что яИщу именно для меня способ получить границы хитрых краев, а затем оттуда обрезать исходное изображение вокруг этих границ. Спасибо!

1 Ответ

2 голосов
/ 30 октября 2019

Если я правильно понимаю, вы хотите удалить фон и извлечь объект. Вместо использования Canny, вот альтернативный подход. Поскольку вы не предоставили исходное изображение, я сделал снимок экрана, чтобы использовать его в качестве входных данных. В общем, существует несколько способов получения бинарного изображения для выделения границ. Они включают в себя регулярное определение порога, определение порога Оцу, адаптивное определение порога и обнаружение края Канни. В этом случае Otsu, вероятно, лучший, так как есть фоновый шум

image


Сначала мы конвертируем изображение в оттенки серого, затем выполняем пороговое значение Otsu для получения двоичного изображения

image

Есть нежелательные секции, поэтому для их удаления мы выполняем морфинг, открывающий для разделения суставов

image

Теперь, когда суставыразделены, мы находим контуры и фильтруем, используя область контура. Мы извлекаем самый большой контур, представляющий желаемый объект, затем рисуем этот контур на маске

image

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

image

Далее мы побитовые - и с исходным изображением

image

Наконец, чтобы получить желаемый результат, мы окрашиваем во все черноепикселей на маске до белого цвета

image

Отсюда вы можете использовать Numpy Slicing для извлечения ROI, но я не совсем уверен, что вы пытались сделать. Я оставлю это на ваше усмотрение

import cv2
import numpy as np

image = cv2.imread("1.png")
original = image.copy()
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
    cv2.drawContours(mask, [c], -1, (255,255,255), -1)
    break

close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=4)
close = cv2.cvtColor(close, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original, original, mask=close)
result[close==0] = (255,255,255)

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