0

I'm working on stitching multiple images using OpenCV. It's starting to work but I have a problem with one thing. After cv2.warpPerspective image has a "soft" borders, which means that calculated mask is one pixel too big.

My code:

    # apply a perspective warp to stitch the images
    # together
    result = cv2.warpPerspective(imageA, H,
        (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))

    # Now create a mask of logo and create its inverse mask also
    img2gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
    ret, mask = cv2.threshold(img2gray, 0, 255, cv2.THRESH_BINARY)
    mask_inv = cv2.bitwise_not(mask)

    resizedB = np.zeros((result.shape[0],result.shape[1],3), np.uint8)
    resizedB[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
    difference = cv2.bitwise_or(resizedB,result, mask=mask_inv)

    result = cv2.add(result,difference)
    cv2.imwrite('result .jpg', result)

I had to use cv2.bitwise_or because adding both images using cv2.add makes it too bright which made an almost black line at the connection. Do you have any idea how to fix this? Maybe there's a way to modify mask to make it 1 pixel smaller?

Ekci
  • 165
  • 1
  • 2
  • 12
  • You could use a gradient mask where the transition is, in other words blending both connecting sides – Pedro Jul 29 '16 at 12:55
  • Is there a way to obtain a gradient mask using color threshold? I don't think there is. Do you know any other way to obtain mask like this using given picture? – Ekci Jul 29 '16 at 14:16
  • you can compute the distance from the image border similar to http://stackoverflow.com/questions/37911062/how-to-obtain-the-right-alpha-value-to-perfectly-blend-two-images/37918596#37918596 and use that as a blending mask – Micka Jul 29 '16 at 14:50
  • Maybe I'm stupid but I can't find corresponding functions in Python's cv2... – Ekci Jul 29 '16 at 20:14

1 Answers1

0

I have finally solved this problem by using combination of few logic operations. Solution is presented below:

    h1,w1 = imageB.shape[:2]
    h2,w2 = imageA.shape[:2]
    pts1 = np.float32([[0,0],[0,h1],[w1,h1],[w1,0]]).reshape(-1,1,2)
    pts2 = np.float32([[0,0],[0,h2],[w2,h2],[w2,0]]).reshape(-1,1,2)
    pts2_ = cv2.perspectiveTransform(pts2, H)
    pts = np.concatenate((pts1, pts2_), axis=0)
    # print("pts:", pts)
    [xmin, ymin] = np.int32(pts.min(axis=0).ravel() - 0.5)
    [xmax, ymax] = np.int32(pts.max(axis=0).ravel() + 0.5)
    t = [-xmin,-ymin]
    Ht = np.array([[1,0,t[0]],[0,1,t[1]],[0,0,1]]) # translate

    result = cv2.warpPerspective(imageA, Ht.dot(H), (xmax-xmin, ymax-ymin))

    resizedB = np.zeros((result.shape[0], result.shape[1], 3), np.uint8)

    resizedB[t[1]:t[1]+h1,t[0]:w1+t[0]] = imageB
    # Now create a mask of logo and create its inverse mask also
    img2gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
    ret, mask = cv2.threshold(img2gray, 0, 255, cv2.THRESH_BINARY)

    kernel = np.ones((5,5),np.uint8)
    k1 = (kernel == 1).astype('uint8')
    mask = cv2.erode(mask, k1, borderType=cv2.BORDER_CONSTANT)

    mask_inv = cv2.bitwise_not(mask)

    difference = cv2.bitwise_or(resizedB, resizedB, mask=mask_inv)

    result2 = cv2.bitwise_and(result, result, mask=mask)

    result = cv2.add(result2, difference)
Ekci
  • 165
  • 1
  • 2
  • 12
  • I am also having issue in stitching multiple images. is your stitching result in panorama or orthomosaic? If possible could you please share your whole solution stitching code? That will be helpful for understanding. Thanks – ganesh Aug 02 '21 at 11:41