linrl3 / Image-Stitching-OpenCV

Simple image stitching algorithm based on SIFT, homography, KNN and Ransac in Python and OpenCV
MIT License
187 stars 43 forks source link

How to three pictures #5

Open monkeycc opened 2 years ago

monkeycc commented 2 years ago
import cv2
import numpy as np
import sys

class Image_Stitching():
    def __init__(self) :
        self.ratio=0.85
        self.min_match=10
        self.sift=cv2.SIFT_create()
        self.smoothing_window_size=800

    def registration(self,img1,img2,img3):
        kp1, des1 = self.sift.detectAndCompute(img1, None)
        kp2, des2 = self.sift.detectAndCompute(img2, None)
        kp3, des3 = self.sift.detectAndCompute(img3, None)

        matcher = cv2.BFMatcher()
        raw_matches = matcher.knnMatch(des1, des2, des3, k=3)
        good_points = []
        good_matches=[]
        for m1, m2 in raw_matches:
            if m1.distance < self.ratio * m2.distance:
                good_points.append((m1.trainIdx, m1.queryIdx))
                good_matches.append([m1])
        img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, img3, kp3, good_matches, None, flags=3)
        cv2.imwrite('matching.jpg', img3)
        if len(good_points) > self.min_match:
            image1_kp = np.float32(
                [kp1[i].pt for (_, i) in good_points])
            image2_kp = np.float32(
                [kp2[i].pt for (i, _) in good_points])
            image3_kp = np.float32(
                [kp3[i].pt for (i, _) in good_points])
            H, status = cv2.findHomography(image2_kp, image1_kp,image3_kp, cv2.RANSAC,5.0)
        return H

    def create_mask(self,img1,img2,img3,version):
        height_img1 = img1.shape[0]
        width_img1 = img1.shape[1]
        width_img2 = img2.shape[1]
        width_img3 = img3.shape[1]
        height_panorama = height_img1
        width_panorama = width_img1 +width_img2 +width_img3
        offset = int(self.smoothing_window_size / 2)
        barrier = img1.shape[1] - int(self.smoothing_window_size / 2)
        mask = np.zeros((height_panorama, width_panorama))
        if version== 'left_image':
            mask[:, barrier - offset:barrier + offset ] = np.tile(np.linspace(1, 0, 2 * offset ).T, (height_panorama, 1))
            mask[:, :barrier - offset] = 1
        else:
            mask[:, barrier - offset :barrier + offset ] = np.tile(np.linspace(0, 1, 2 * offset ).T, (height_panorama, 1))
            mask[:, barrier + offset:] = 1
        return cv2.merge([mask, mask, mask])

    def blending(self,img1,img2,img3):
        H = self.registration(img1,img2,img3)
        height_img1 = img1.shape[0]
        width_img1 = img1.shape[1]
        width_img2 = img2.shape[1]
        width_img3 = img3.shape[1]
        height_panorama = height_img1
        width_panorama = width_img1 +width_img2 +width_img3

        panorama1 = np.zeros((height_panorama, width_panorama, 3))
        mask1 = self.create_mask(img1,img2,img3,version='left_image')
        panorama1[0:img1.shape[0], 0:img1.shape[1], :] = img1
        panorama1 *= mask1
        mask2 = self.create_mask(img1,img2,img3,version='right_image')
        panorama2 = cv2.warpPerspective(img2, H, (width_panorama, height_panorama))*mask2

        panorama1 *= mask2
        mask3 = self.create_mask(img1,img2,img3,version='right_image')
        panorama3 = cv2.warpPerspective(img3, H, (width_panorama, height_panorama))*mask3

        result=panorama1+panorama2+panorama3

        rows, cols = np.where(result[:, :, 0] != 0)
        min_row, max_row = min(rows), max(rows) + 1
        min_col, max_col = min(cols), max(cols) + 1
        final_result = result[min_row:max_row, min_col:max_col, :]
        return final_result
def main(argv1,argv2,argv3):
    img1 = cv2.imread(argv1)
    img2 = cv2.imread(argv2)
    img3 = cv2.imread(argv3)

    final=Image_Stitching().blending(img1,img2,img3)
    cv2.imwrite('panorama.jpg', final)
if __name__ == '__main__':
    try: 
        main(sys.argv[1],sys.argv[2],sys.argv[3])
    except IndexError:
        print ("Please input two source images: ")
        print ("For example: python Image_Stitching.py '/Users/linrl3/Desktop/picture/p1.jpg' '/Users/linrl3/Desktop/picture/p2.jpg'")

My method is wrong