Add padding to object in 4-channel image

2019-04-15 17:49发布

问题:

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

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) :

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).

回答1:

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

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



回答2:

The issue has been already addressed and solved here:

http://answers.opencv.org/question/90229/add-padding-to-object-in-4-channel-image/