OpenCV實戰之圖像拼接的示例代碼

背景

圖像拼接可以應用到手機中的全景拍攝,也就是將多張圖片根據關聯信息拼成一張圖片;

實現步驟

1、讀文件並縮放圖片大小;

2、根據特征點和計算描述子,得到單應性矩陣;

3、根據單應性矩陣對圖像進行變換,然後平移;

4、圖像拼接並輸出拼接後結果圖;

一、讀取文件

第一步實現讀取兩張圖片並縮放到相同尺寸;

代碼如下:

img1 = cv2.imread('map1.png')
img2 = cv2.imread('map2.png')

img1 = cv2.resize(img1, (640, 480))
img2 = cv2.resize(img2, (640, 480))

input = np.hstack((img1, img2))
cv2.imshow('input', input)
cv2.waitKey(0)

上圖為我們需要拼接的兩張圖的展示,可以看出其還具有一定的旋轉變換,之後的圖像轉換必定包含旋轉的操作;

二、單應性矩陣計算

主要分為以下幾個步驟:

1、創建特征轉換對象;

2、通過特征轉換對象獲得特征點和描述子;

3、創建特征匹配器;

4、進行特征匹配;

5、過濾特征,找出有效的特征匹配點;

6、單應性矩陣計算

實現代碼:

def get_homo(img1, img2):
    # 1實現
    sift = cv2.xfeatures2d.SIFT_create()
    # 2實現
    k1, p1 = sift.detectAndCompute(img1, None)
    k2, p2 = sift.detectAndCompute(img2, None)
    # 3實現
    bf = cv2.BFMatcher()
    # 4實現
    matches = bf.knnMatch(p1, p2, k=2)
    # 5實現
    good = []
    for m1, m2 in matches:
        if m1.distance < 0.8 * m2.distance:
            good.append(m1)
    # 6實現
    if len(good) > 8:
        img1_pts = []
        img2_pts = []
        for m in good:
            img1_pts.append(k1[m.queryIdx].pt)
            img2_pts.append(k2[m.trainIdx].pt)
        img1_pts = np.float32(img1_pts).reshape(-1, 1, 2)
        img2_pts = np.float32(img2_pts).reshape(-1, 1, 2)
        H, mask = cv2.findHomography(img1_pts, img2_pts, cv2.RANSAC, 5.0)
        return H
    else:
        print('piints is not enough 8!')
        exit()

三、圖像拼接

實現步驟:

1、獲得圖像的四個角點;

2、根據單應性矩陣變換圖片;

3、創建一張大圖,拼接圖像;

4、輸出結果

實現代碼:

def stitch_img(img1, img2, H):
    # 1實現
    h1, w1 = img1.shape[:2]
    h2, w2 = img2.shape[:2]
    img1_point = np.float32([[0,0], [0,h1], [w1,h1], [w1,0]]).reshape(-1, 1, 2)
    img2_point = np.float32([[0,0], [0,h2], [w2,h2], [w2,0]]).reshape(-1, 1, 2)
    # 2實現
    img1_trans = cv2.perspectiveTransform(img1_point, H)
    # 將img1變換後的角點與img2原來的角點做拼接
    result_point = np.concatenate((img2_point, img1_trans), axis=0)
    # 獲得拼接後圖像x,y的最小值
    [x_min, y_min] = np.int32(result_point.min(axis=0).ravel()-0.5)
    # 獲得拼接後圖像x,y的最大值
    [x_max, y_max] = np.int32(result_point.max(axis=0).ravel()+0.5)
    # 平移距離
    trans_dist = [-x_min, -y_min]
    # 構建一個齊次平移矩陣
    trans_array = np.array([[1, 0, trans_dist[0]],
                            [0, 1, trans_dist[1]],
                            [0, 0, 1]])
    # 平移和單應性變換
    res_img = cv2.warpPerspective(img1, trans_array.dot(H), (x_max-x_min, y_max-y_min))
    # 3實現
    res_img[trans_dist[1]:trans_dist[1]+h2,
            trans_dist[0]:trans_dist[0]+w2] = img2
    return res_img

H = get_homo(img1, img2)
res_img = stitch_img(img1, img2, H)
# 4實現
cv2.imshow('result', res_img)
cv2.waitKey(0) 

最終結果圖如上圖所示,還有待優化點如下:

  • 邊緣部分有色差,可以根據取平均值消除;
  • 黑色區域可進行裁剪並用對應顏色填充;

優化部分難度不大,有興趣的可以實現一下;

總結

圖像拼接作為一個實用性技術經常出現在我們的生活中,特別是全景拍攝以及圖像內容拼接;當然,基於傳統算法的圖像拼接還是會有一些缺陷(速度和效果上),感興趣的可以瞭解下基於深度學習的圖像拼接算法,期待和大傢溝通!

到此這篇關於OpenCV實戰之圖像拼接的示例代碼的文章就介紹到這瞭,更多相關OpenCV圖像拼接內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: