簡體   English   中英

Python OpenCV ORB 圖像對齊的掩碼問題

[英]Mask Issue With Python OpenCV ORB Image Alignment

我正在嘗試實現 Python (3.7) OpenCV (3.4.3) ORB 圖像對齊。 我通常使用 ImageMagick 進行大部分處理。 但是我需要做一些圖像對齊並嘗試使用 Python OpenCV ORB。 我的腳本基於 Satya Mallick 在https://www.learnopencv.com/image-alignment-feature-based-using-opencv-c-python/ 上的 Learn OpenCV 教程中的一個。

但是,我試圖修改它以使用剛性對齊而不是透視同源性,並使用掩碼過濾點以限制 y 值的差異,因為圖像已經幾乎對齊了。

掩碼方法取自https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_feature2d/py_matcher/py_matcher.html上最后一個示例中的 FLANN 對齊代碼。

我的腳本工作正常,如果我刪除了matchesMask,它應該提供點過濾。 (我還有另外兩個工作腳本。一個是類似的,但只是過濾點並忽略掩碼。另一個基於 ECC 算法。)

但是,我想了解為什么我下面的代碼不起作用。

也許我的掩碼結構在當前版本的 Python Opencv 中不正確?

我得到的錯誤是:

Traceback (most recent call last):
  File "warp_orb_rigid2_filter.py", line 92, in <module>
    imReg, m = alignImages(im, imReference)
  File "warp_orb_rigid2_filter.py", line 62, in alignImages
    imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None, **draw_params)
SystemError: <built-in function drawMatches> returned NULL without setting an error


這是我的代碼。 第一個箭頭顯示創建遮罩的位置。 第二個箭頭顯示了我必須刪除才能使腳本工作的行。 但隨后它忽略了我對點的過濾。

#!/bin/python3.7

import cv2
import numpy as np


MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15


def alignImages(im1, im2):

  # Convert images to grayscale
  im1Gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
  im2Gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)

  # Detect ORB features and compute descriptors.
  orb = cv2.ORB_create(MAX_FEATURES)
  keypoints1, descriptors1 = orb.detectAndCompute(im1Gray, None)
  keypoints2, descriptors2 = orb.detectAndCompute(im2Gray, None)

  # Match features.
  matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
  matches = matcher.match(descriptors1, descriptors2, None)

  # Sort matches by score
  matches.sort(key=lambda x: x.distance, reverse=False)

  # Remove not so good matches
  numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
  matches = matches[:numGoodMatches]

  # Extract location of good matches and filter by diffy
  points1 = np.zeros((len(matches), 2), dtype=np.float32)
  points2 = np.zeros((len(matches), 2), dtype=np.float32)

  for i, match in enumerate(matches):
    points1[i, :] = keypoints1[match.queryIdx].pt
    points2[i, :] = keypoints2[match.trainIdx].pt

  # initialize empty arrays for newpoints1 and newpoints2 and mask
  newpoints1 = np.empty(shape=[0, 2])
  newpoints2 = np.empty(shape=[0, 2])
  matches_Mask = [0] * len(matches)

  # filter points by using mask    
  for i in range(len(matches)):
      pt1 = points1[i]
      pt2 = points2[i]
      pt1x, pt1y = zip(*[pt1])
      pt2x, pt2y = zip(*[pt2])
      diffy = np.float32( np.float32(pt2y) - np.float32(pt1y) )
      print(diffy)
      if abs(diffy) < 10.0:
        newpoints1 = np.append(newpoints1, [pt1], axis=0)
        newpoints2 = np.append(newpoints2, [pt2], axis=0)
        matches_Mask[i]=[1,0]  #<--- mask created
  print(matches_Mask)

  draw_params = dict(matchColor = (255,0,),
    singlePointColor = (255,255,0),
    matchesMask = matches_Mask, #<---- remove mask here
    flags = 0)

  # Draw top matches
  imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None, **draw_params)
  cv2.imwrite("/Users/fred/desktop/lena_matches.png", imMatches)


  # Find Affine Transformation
  # true means full affine, false means rigid (SRT)
  m = cv2.estimateRigidTransform(newpoints1,newpoints2,False)

  # Use affine transform to warp im1 to match im2
  height, width, channels = im2.shape
  im1Reg = cv2.warpAffine(im1, m, (width, height))

  return im1Reg, m


if __name__ == '__main__':

  # Read reference image
  refFilename = "/Users/fred/desktop/lena.png"
  print("Reading reference image : ", refFilename)
  imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR)

  # Read image to be aligned
  imFilename = "/Users/fred/desktop/lena_r1.png"
  print("Reading image to align : ", imFilename);  
  im = cv2.imread(imFilename, cv2.IMREAD_COLOR)

  print("Aligning images ...")
  # Registered image will be stored in imReg. 
  # The estimated transform will be stored in m. 
  imReg, m = alignImages(im, imReference)

  # Write aligned image to disk. 
  outFilename = "/Users/fred/desktop/lena_r1_aligned.jpg"
  print("Saving aligned image : ", outFilename); 
  cv2.imwrite(outFilename, imReg)

  # Print estimated homography
  print("Estimated Affine Transform : \n",  m)


這是我的兩個圖像:lena 和 lena 旋轉了 1 度。 請注意,這些不是我的實際圖像。 這些圖像沒有 diffy 值 > 10,但我的實際圖像有。

在此處輸入圖片說明

在此處輸入圖片說明

我正在嘗試對齊和扭曲旋轉后的圖像以匹配原始的 lena 圖像。

您創建遮罩的方式不正確。 它只需要是一個帶有單個數字的列表,每個數字都會告訴您是否要使用該特定功能匹配。

因此,替換此行:

matches_Mask = [[0,0] for i in range(len(matches))]

有了這個:

matches_Mask = [0] * len(matches)

... 所以:

# matches_Mask = [[0,0] for i in range(len(matches))]
matches_Mask = [0] * len(matches)

這將創建一個與匹配數一樣長的 0 列表。 最后,您需要使用單個值更改對掩碼的寫入:

  if abs(diffy) < 10.0:
    #matches_Mask[i]=[1,0]  #<--- mask created
    matches_Mask[i] = 1

我終於明白了:

Estimated Affine Transform :
 [[ 1.00001187  0.01598318 -5.05963793]
  [-0.01598318  1.00001187 -0.86121051]]

請注意,掩碼的格式因您使用的匹配器而異。 在這種情況下,您使用強力匹配,因此掩碼需要采用我剛剛描述的格式。

例如,如果您使用 FLANN 的knnMatch ,那么它將是一個嵌套的列表列表,每個元素都是一個長度為k的列表。 例如,如果您有k=3和五個關鍵點,它將是一個包含五個元素的列表,每個元素都是一個三元素列表。 子列表中的每個元素都描述了您要用於繪圖的匹配項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM