Add padding to object in 4-channel image

2019-04-15 17:52发布

I have a 4-channel image (.png, .tif) like this one:

enter image description here

I am using OpenCV, and I would like to add padding of type BORDER_REFLECT around the flower. copyMakeBorder is not useful, since it adds padding to the edges of the image.

I can add certain padding if I split the image in bgr + alpha and apply dilate with BORDER_REFLECT option on the bgr image, but that solution spoils all the pixels of the flower.

Is there any way to perform a selective BORDER_REFLECT padding addition on a ROI defined by a binary mask?

EDIT:

The result I expect is something like (sorry I painted it very quickly with GIMP) :

enter image description here

I painted two black lines to delimit the old & new contour of the flower after the padding, but of course those lines should not appear in the final result. The padding region (inside the two black lines) must be composed by mirrored pixels from the flower (I painted it yellow to make it understandable).

2条回答
可以哭但决不认输i
2楼-- · 2019-04-15 18:13
戒情不戒烟
3楼-- · 2019-04-15 18:15

A simple python script to resize the image and copy the original over the enlarged one will do the trick.

import cv2

img = cv2.imread('border_reflect.png', cv2.IMREAD_UNCHANGED)

pad = 20
sh = img.shape
sh_pad = (sh[0]+pad, sh[1]+pad)
imgpad = cv2.resize(img, sh_pad)

imgpad[20:20+sh[0], 20:20+sh[1], :][img[:,:,3]==255] = img[img[:,:,3]==255]
cv2.imwrite("padded_image.png", imgpad)

Here is the result

enter image description here

But that doesn't look very 'centered'. So I modified the code to detect and account for the offsets while copying.

import cv2

img = cv2.imread('border_reflect.png', cv2.IMREAD_UNCHANGED)

pad = 20
sh = img.shape
sh_pad = (sh[0]+pad, sh[1]+pad)
imgpad = cv2.resize(img, sh_pad)

def get_roi(img):
    cimg = img[:,:,3].copy()

    contours,hierarchy = cv2.findContours(cimg,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

    #Remove the tiny pixel noises that get detected as contours
    contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 10]

    x,y,w,h = cv2.boundingRect(cnt)
    roi=img[y:y+h,x:x+w]
    return roi

roi = get_roi(img)
roi2 = get_roi(imgpad)

sh = roi.shape
sh2 = roi2.shape

o = ((sh2[0]-sh[0])/2, (sh2[1]-sh[1])/2)

roi2[o[0]:o[0]+sh[0], o[1]:o[1]+sh[1], :][roi[:,:,3]==255] = roi[roi[:,:,3]==255]
cv2.imwrite("padded_image.png", imgpad)

Looks much better now

enter image description here

查看更多
登录 后发表回答