2015-06-30 11 views
9

Próbuję usunąć tło niektórych obrazów, poprawiając niektóre wartości i używając niektórych metod, takich jak morphologyEx daje mi możliwy do zaakceptowania wynik, ale wciąż pozostają dziury, w tym ostatnim przypadku otwory nie wypełniają nawet iteracji na każdym konturze i rysując go za pomocą -1. Widzę, że próg obrazu jest bardzo dobra, co czyni cały kształt linii, ale nie wiem jak kontynuować ...OpenCV usuń tło

Aktualizacja zmieniłem mój kod więc uzyskać lepsze wyniki, ale ja Wciąż robię dziury ... Gdybym mógł wypełnić te dziury, scenariusz byłby idealny.

def get_contrasted(image, type="dark", level=3): 
    maxIntensity = 255.0 # depends on dtype of image data 
    phi = 1 
    theta = 1 

    if type == "light": 
     newImage0 = (maxIntensity/phi)*(image/(maxIntensity/theta))**0.5 
     newImage0 = array(newImage0,dtype=uint8) 
     return newImage0 
    elif type == "dark": 
     newImage1 = (maxIntensity/phi)*(image/(maxIntensity/theta))**level 
     newImage1 = array(newImage1,dtype=uint8) 

     return newImage1 

def sharp(image, level=3): 
    f = cv2.GaussianBlur(image, (level,level), level) 
    f = cv2.addWeighted(image, 1.5, f, -0.5, 0) 
    return f 

original_image = imread('imagen.jpg') 
# 1 Convert to gray & Normalize 
gray_img = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY) 
gray_img = sharp(get_contrasted(gray_img)) 
gray_img = normalize(gray_img, None, 0, 255, NORM_MINMAX, CV_8UC1) 
imshow("Gray", gray_img) 

# 2 Find Threshold 
gray_blur = cv2.GaussianBlur(gray_img, (7, 7), 0) 
adapt_thresh_im = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 1) 
max_thresh, thresh_im = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) 
thresh = cv2.bitwise_or(adapt_thresh_im, thresh_im) 

# 3 Dilate 
gray = cv2.Canny(thresh, 88, 400, apertureSize=3) 
gray = cv2.dilate(gray, None, iterations=8) 
gray = cv2.erode(gray, None, iterations=8) 
imshow("Trheshold", gray) 

# 4 Flood 
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 
contour_info = [] 
for c in contours: 
    contour_info.append((
     c, 
     cv2.isContourConvex(c), 
     cv2.contourArea(c), 
    )) 
contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True) 
max_contour = contour_info[0] 
holes = np.zeros(gray_img.shape, np.uint8) 
drawContours(holes, max_contour, 0, 255, -1) 
imshow("Holes", holes) 

mask = cv2.GaussianBlur(holes, (15, 15), 0) 
mask = np.dstack([mask] * 3) # Create 3-channel alpha mask 

mask = mask.astype('float32')/255.0 # Use float matrices, 
img = original_image.astype('float32')/255.0 # for easy blending 
masked = (mask * img) + ((1 - mask) * (0,0,1)) # Blend 
masked = (masked * 255).astype('uint8') 

imshow("Maked", masked) 
waitKey() 

0 oryginalny

enter image description here

1 Próg

enter image description here

2 otwory

enter image description here

3 Ostateczny obraz

enter image description here

+0

Twój kod nie jest prawidłowy kod Python. Proszę napisać kod bez błędów składniowych (a mianowicie kodu, który może być uruchamiany). – boardrider

+0

Brak nawiasu, zaktualizowany teraz. –

+0

Powinieneś najpierw zapoznać się z samouczkami opencv dotyczącymi maskowania. Ponadto, spójrz na to: http://stackoverflow.com/questions/18710428/how-to-remove-background-image-with-opencv –

Odpowiedz

8

Iteracyjnie wykonać morfologiczną zamykanie otworów swoim obrazie przy użyciu jądra wzrostem wielkości. Zanim jednak to zrobię, sugeruję zmianę rozmiaru obrazu otworów (z użyciem interpolacji najbliższego sąsiada), aby nie trzeba było używać ogromnych ziaren. W poniższym kodzie (C++) zmieniłem rozmiar obrazu otworów na 25% jego oryginalnych wymiarów.

Aby zmniejszyć wpływ na obramowanie, należy dodać stałą granicę zer przy użyciu copyMakeBorder przed zastosowaniem iteracyjnego zamykania. Jak używamy 15 iteracji tu zrobić ramkę wokół obrazu większy niż 15.

Więc kroki są

  • Zmiana rozmiaru obrazu otwory
  • dodać obramowanie zero
  • Iteracyjnie zamknąć zdjęcie z jądrem o rosnącym rozmiarze
  • Usuń granicę
  • Teraz mamy małą maskę. Zmień rozmiar tej maski na oryginalny rozmiar obrazu

Kod jest w C++. Nie bardzo wiem o Pythonie.

// read the image and the holes 
    Mat im = imread("koAl2.jpg"); 
    Mat holes = imread("GuICX.jpg", 0); 
    // resize 
    Mat small, bordered; 
    resize(holes, small, Size(), .25, .25); 
    // add a zero border 
    int b = 20; 
    copyMakeBorder(small, bordered, b, b, b, b, BORDER_CONSTANT, Scalar(0)); 
    // close 
    for (int i = 1; i < 15; i++) 
    { 
     Mat kernel = getStructuringElement(MORPH_ELLIPSE, cv::Size(2*i+1, 2*i+1)); 
     morphologyEx(bordered, bordered, MORPH_CLOSE, kernel, Point(-1, -1), 1); 
    } 
    // remove border 
    Mat mask = bordered(Rect(b, b, small.cols, small.rows)); 
    // resize the mask 
    Mat largeMask; 
    resize(mask, largeMask, Size(im.cols, im.rows)); 
    // the foreground 
    Mat fg; 
    im.copyTo(fg, largeMask); 

Dane wyjściowe (nie dotyczy skali oryginalnej) wyglądają dobrze, z tym, że dotyczą obszaru tła na dole jako pierwszego planu.

enter image description here

+1

Nie mogę uruchomić go w Pythonie, są dwie rzeczy, których nie mogę przekonwertować do Pythona: 1: "graniczy" stało się tylko metodą? Gdy? 'border (Rect (b, b, small.cols, small.rows))' i czym jest 'Rect'? 2: 'resize (otwory, małe, Size(), .25, .25)' Nie mam obiektu 'Size()', wyobrażam sobie, że to jest Tuple ??, ale nie mogę używać pusta krotka '()' 3: 'morfologiaEx (granicząca, granicząca, MORPH_CLOSE, jądro, punkt (-1, -1), 1)' staje się 'granicząca = cv2.morphologyEx (graniczy, cv2.MORPH_CLOSE, jądro, (-1, -1), 1) 'w python ale błąd:' nowy styl getargs format ale argument nie jest krotką ' –

+0

' Maska maty = obramowana (Rect (b, b, small.cols, small.rows)) ; 'wyodrębnia określony ROI do maski. To operator klasy Mat. Będziesz mógł to zrobić działając, jeśli skupisz się na podanym przeze mnie opisie, zamiast próbować mapowania kodu C++ do Pythona w trybie jeden-do-jednego. Dodałem kod z nadzieją, że sprawi to, że opis będzie wyraźniejszy. – dhanushka

4

@ metody dhanushka za działa dobrze.Oto mój pythonic wersja:

def get_holes(image, thresh): 
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) 

    im_bw = cv.threshold(gray, thresh, 255, cv.THRESH_BINARY)[1] 
    im_bw_inv = cv.bitwise_not(im_bw) 

    contour, _ = cv.findContours(im_bw_inv, cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE) 
    for cnt in contour: 
     cv.drawContours(im_bw_inv, [cnt], 0, 255, -1) 

    nt = cv.bitwise_not(im_bw) 
    im_bw_inv = cv.bitwise_or(im_bw_inv, nt) 
    return im_bw_inv 


def remove_background(image, thresh, scale_factor=.25, kernel_range=range(1, 15), border=None): 
    border = border or kernel_range[-1] 

    holes = get_holes(image, thresh) 
    small = cv.resize(holes, None, fx=scale_factor, fy=scale_factor) 
    bordered = cv.copyMakeBorder(small, border, border, border, border, cv.BORDER_CONSTANT) 

    for i in kernel_range: 
     kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (2*i+1, 2*i+1)) 
     bordered = cv.morphologyEx(bordered, cv.MORPH_CLOSE, kernel) 

    unbordered = bordered[border: -border, border: -border] 
    mask = cv.resize(unbordered, (image.shape[1], image.shape[0])) 
    fg = cv.bitwise_and(image, image, mask=mask) 
    return fg 


img = cv.imread('koAl2.jpg') 
nb_img = remove_background(img, 230) 

enter image description here

+0

wersja python? jak zaimportować CV? – grep

+0

", wiersz 11, w get_holes kontur, _ = cv2.findContours (im_bw_inv, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) ValueError: zbyt wiele wartości do rozpakowania – grep

4

Jak już przeciwdziałanie ten sam problem i znalazł rozwiązanie w Pythonie (z opencv2), myśl tylko dzieląc to również tutaj. Mam nadzieję, że to pomoże.

import numpy as np 
import cv2 

cv2.namedWindow('image', cv2.WINDOW_NORMAL) 

#Load the Image 
imgo = cv2.imread('koAl2.jpg') 
height, width = imgo.shape[:2] 

#Create a mask holder 
mask = np.zeros(imgo.shape[:2],np.uint8) 

#Grab Cut the object 
bgdModel = np.zeros((1,65),np.float64) 
fgdModel = np.zeros((1,65),np.float64) 

#Hard Coding the Rect The object must lie within this rect. 
rect = (10,10,width-30,height-30) 
cv2.grabCut(imgo,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT) 
mask = np.where((mask==2)|(mask==0),0,1).astype('uint8') 
img1 = imgo*mask[:,:,np.newaxis] 

#Get the background 
background = imgo - img1 

#Change all pixels in the background that are not black to white 
background[np.where((background > [0,0,0]).all(axis = 2))] = [255,255,255] 

#Add the background and the image 
final = background + img1 

#To be done - Smoothening the edges 

cv2.imshow('image', final) 

k = cv2.waitKey(0) 

if k==27: 
    cv2.destroyAllWindows() 
0

spróbować tej operacji morfologicznej dla dylatacja i erozja usuwanie dziur w C++

Mat erodeElement = getStructuringElement(MORPH_RECT, Size(4, 4)); 
morphologyEx(thresh, thresh, MORPH_CLOSE ,erodeElement); 
morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement); 
morphologyEx(thresh, thresh, MORPH_CLOSE, erodeElement); 
morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement); 
morphologyEx(thresh, thresh, MORPH_OPEN, erodeElement);