Удалить фоновое изображение и извлечь объект в изображение - PullRequest
2 голосов
/ 03 февраля 2020

Я знаю, что здесь много тем об этой проблеме, но я не могу решить мою проблему с помощью этих ответов. Я много раз пытался с разными кодами удалить фон изображения, подобного этому: With Background

до этого:

Without Background

со следующим кодом:

img2 = Image.open("foo.jpg")
c_red, c_green, c_blue = cv2.split(img2)
img2 = cv2.merge((c_red, c_green, c_blue, mask.astype('float32') / 255.0))
img.paste(img2,(0,0))

или с этим кодом:

img2 = Image.open("foo.jpg")
img2 = img2.convert("RGBA")
datas = img2.getdata()

newData = []
for item in datas:
    if item[0] == 255 and item[1] == 255 and item[2] == 255:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)
img2.putdata(newData)

или:

threshold=100
dist=5
img2 = Image.open("foo.jpg")
img2 = img2.convert("RGBA")

arr=np.array(np.asarray(img2))
r,g,b,a=np.rollaxis(arr,axis=-1)    
mask=((r>threshold)
      & (g>threshold)
      & (b>threshold)
      & (np.abs(r-g)<dist)
      & (np.abs(r-b)<dist)
      & (np.abs(g-b)<dist)
      )
arr[mask,3]=0
img2=Image.fromarray(arr,mode='RGBA')

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

1 Ответ

2 голосов
/ 04 февраля 2020

Вот один из способов сделать это с помощью OpenCV. Идея состоит в том, чтобы получить двоичное изображение, а затем использовать cv2.boundingRect для получения координат ограничивающего прямоугольника. Мы можем обрезать изображение, используя Numpy, затем добавить альфа-канал. Вот результаты:

Входное изображение

enter image description here

Двоичное изображение и область для извлечения

enter image description here

Извлеченный ROI

enter image description here

Код

import cv2
import numpy as np

# Load image, convert to grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Obtain bounding rectangle and extract ROI
x,y,w,h = cv2.boundingRect(thresh)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
ROI = original[y:y+h, x:x+w]

# Add alpha channel
b,g,r = cv2.split(ROI)
alpha = np.ones(b.shape, dtype=b.dtype) * 50
ROI = cv2.merge([b,g,r,alpha])

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.imshow('ROI', ROI)
cv2.waitKey()
...