Monk247uk
Monk247uk

Reputation: 1320

cv2.warpPerspective produces Black dotted edges

I am trying to implement the Pikachu image on the hoarding board using warpPerspective transformation. The output doesn't have smooth edges it has dotted points instead.

import cv2
import numpy as np

image = cv2.imread("base_img.jpg")


h_base, w_base = image.shape[0], image.shape[1]

white_subject =  np.ones((480,640,3),dtype="uint8")*255
h_white, w_white = white_subject.shape[:2]

subject = cv2.imread('subject.jpg')


h_sub, w_sub = subject.shape[:2]

pts2 = np.float32([[109,186],[455,67],[480,248],[90,349]])
pts3 = np.float32([[0, 0], [w_white, 0], [w_white, h_white], [0, h_white]])

transformation_matrix_white = cv2.getPerspectiveTransform(pts3, pts2)
mask = cv2.warpPerspective(white_subject, transformation_matrix_white, (w_base, h_base)) 
image[mask==255] = 0

pts3 = np.float32([[0, 0], [w_sub, 0], [w_sub, h_sub], [0, h_sub]])
transformation_matrix = cv2.getPerspectiveTransform(pts3, pts2)
warped_image = cv2.warpPerspective(subject, transformation_matrix, (w_base, h_base)) 

Hoarding board image

enter image description here

Pikachu Image

enter image description here

Output Image

enter image description here

Pattern Image

enter image description here

Output Image enter image description here

Please help me out in getting the output without the dotted point at the edges.

Upvotes: 4

Views: 1699

Answers (1)

fmw42
fmw42

Reputation: 53071

Here is one way to do the anti-aliased composite in Python/OpenCV. Note that I use the background color of the overlay image in the borderVal constant in warpPerspective to set the background color, since it is a constant. I also blur the mask before doing the composite.

Background Image:

enter image description here

Overlay Image:

enter image description here


import cv2
import numpy as np
import skimage.exposure

image = cv2.imread("base_img.jpg")
h_base, w_base = image.shape[0], image.shape[1]

white_subject =  np.ones((480,640,3),dtype="uint8")*255
h_white, w_white = white_subject.shape[:2]

subject = cv2.imread('subject.jpg')
h_sub, w_sub = subject.shape[:2]

# get background color from first pixel at (0,0) and its BGR components
yellow = subject[0:1, 0:1][0][0]
blue = yellow[0]
green = yellow[1]
red = yellow[2]
print(yellow)
print(blue, green, red)

pts2 = np.float32([[109,186],[455,67],[480,248],[90,349]])
pts3 = np.float32([[0, 0], [w_white, 0], [w_white, h_white], [0, h_white]])

transformation_matrix_white = cv2.getPerspectiveTransform(pts3, pts2)
mask = cv2.warpPerspective(white_subject, transformation_matrix_white, (w_base, h_base)) 

pts3 = np.float32([[0, 0], [w_sub, 0], [w_sub, h_sub], [0, h_sub]])
transformation_matrix = cv2.getPerspectiveTransform(pts3, pts2)
# do warping with borderVal = background color
warped_image = cv2.warpPerspective(subject, transformation_matrix, (w_base, h_base), borderMode = cv2.BORDER_CONSTANT, borderValue=(int(blue),int(green),int(red))) 

# anti-alias mask
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=2, sigmaY=2, borderType = cv2.BORDER_DEFAULT)
mask = skimage.exposure.rescale_intensity(mask, in_range=(0,128), out_range=(0,255))

# convert mask to float in range 0 to 1
mask = mask.astype(np.float64)/255

# composite warped image over base and convert back to uint8
result =  (warped_image * mask + image * (1 - mask))
result = result.clip(0,255).astype(np.uint8)

# save results
cv2.imwrite('warped_mask.png',(255*mask).clip(0,255).astype(np.uint8))
cv2.imwrite('warped_image.png',warped_image)
cv2.imwrite('warped_image_over_background.png',result)

cv2.imshow("mask", mask)
cv2.imshow("warped_image", warped_image)
cv2.imshow("result", result)
cv2.waitKey(0)

Anti-aliased Warped Mask:

enter image description here

Warped Image:

enter image description here

Resulting Composite:

enter image description here

Upvotes: 7

Related Questions