python - OpenCV remove background -
i trying remove background of images, tweaking values , using methods morphologyex
gives me aceptable result holes still remaining, in last case, holes doesn't fill iterating on every contour , drawing -1
. can see threshold image good, making whole shape lines, don't know how continue...
update i've changed code better results i'm still getting holes... if fill theese holes, script perfect.
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 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 = [] 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 # easy blending masked = (mask * img) + ((1 - mask) * (0,0,1)) # blend masked = (masked * 255).astype('uint8') imshow("maked", masked) waitkey()
0 original
1 threshold
2 holes
3 final image
iteratively perform morphological closing of holes image using kernel of increasing size. but, before doing suggest resize holes image (using nearest-neighbor interpolation) don't have use huge kernels. in following code (c++), resized holes image 25% of original dimensions.
to reduce effects on borders add constant border of zeros using copymakeborder before apply iterative closing. using 15 iterations here, make border around image larger 15.
so steps are
- resize holes image
- add 0 border
- iteratively close image kernel of increasing size
- remove border
- now have small mask. resize mask original image size
the code in c++. i'm not familiar python.
// read image , holes mat im = imread("koal2.jpg"); mat holes = imread("guicx.jpg", 0); // resize mat small, bordered; resize(holes, small, size(), .25, .25); // add 0 border int b = 20; copymakeborder(small, bordered, b, b, b, b, border_constant, scalar(0)); // close (int = 1; < 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 mask mat largemask; resize(mask, largemask, size(im.cols, im.rows)); // foreground mat fg; im.copyto(fg, largemask);
the output (not original scale) looks fine except takes background region @ bottom foreground.
Comments
Post a Comment