如何检测将显微镜图像旋转对准模板的良好特征

rar*_*son 5 python opencv image-processing image-rotation feature-detection

我正在进行一个项目,以自动旋转流体实验的显微镜图像堆栈,以便它们与微流控芯片的CAD模板图像对齐。我正在使用Python中的OpenCV软件包进行图像处理。必须具有正确的旋转方向,以便可以正确遮盖图像以进行分析。我们的芯片具有在每个帧中都可见的充满荧光染料的标记。模板和示例图像如下所示(模板可以缩放到任意大小,但是图像的相关区域通常约为100x100像素左右):

样本模板标记 包含对齐标记的样本图像

我无法将图像旋转对齐到CAD模板。通常,CAD模板与图像之间的未对准小于几度,这仍然足以干扰分析,因此即使它相对较小,我也需要能够测量旋转差异。

在线以下示例我正在使用以下过程:

  1. 使用三次插值(〜800 x 800)将图像放大到与模板大约相同的大小
  2. 使用Otsu方法将两个图像阈值化
  3. 使用内置方法查找关键点并提取描述符(我尝试过ORB,AKAZE和Brief)。
  4. 使用具有汉明距离的蛮力匹配器来匹配描述符。
  5. 取得最佳匹配,并使用它们来计算部分仿射变换矩阵
  6. 使用该矩阵推断旋转位移,将一个图像变形为另一个图像作为检查。

这是我的代码示例(部分从此处借来):

import numpy as np
import cv2
import matplotlib.pyplot as plt

MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.5

def alignImages(im1, im2,returnpoints=False):
    # Detect ORB features and compute descriptors.
    size1 = int(0.1*(np.mean(np.shape(im1))))
    size2 = int(0.1*(np.mean(np.shape(im2))))
    orb1 = cv2.ORB_create(MAX_FEATURES,edgeThreshold=size1,patchSize=size1)
    orb2 = cv2.ORB_create(MAX_FEATURES,edgeThreshold=size2,patchSize=size2)
    keypoints1, descriptors1 = orb1.detectAndCompute(im1, None)
    keypoints2, descriptors2 = orb2.detectAndCompute(im2, None)

    matcher = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
    matches = matcher.match(descriptors1,descriptors2)
    # 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]

    # Draw top matches
    imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)
    cv2.imwrite("matches.jpg", imMatches)

    # Extract location of good matches
    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
    # Find homography
    M, inliers = cv2.estimateAffinePartial2D(points1,points2)
    height, width = im2.shape
    im1Reg = cv2.warpAffine(im1,M,(width,height))
    return im1Reg, M
Run Code Online (Sandbox Code Playgroud)

if __name__ == "__main__":
    test_template = cv2.cvtColor(cv2.imread("test_CAD_cropped.png"),cv2.COLOR_RGB2GRAY)
    test_image = cv2.cvtColor(cv2.imread("test_CAD_cropped.png"),cv2.COLOR_RGB2GRAY)
    fx = fy = 88/923
    test_image_big = cv2.resize(test_image,(0,0),fx=1/fx,fy=1/fy,interpolation=cv2.INTER_CUBIC)
    ret, imRef_t = cv2.threshold(test_template,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    ret, test_big_t = cv2.threshold(test_image_big,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    imReg, M = alignImages(test_big_t,imRef_t)
    fig, ax = plt.subplots(nrows=2,ncols=2,figsize=(8,8))
    ax[1,0].imshow(imReg)
    ax[1,0].set_title("Warped Image")
    ax[0,0].imshow(imRef_t)
    ax[0,0].set_title("Template")
    ax[0,1].imshow(test_big_t)
    ax[0,1].set_title("Thresholded Image")
    ax[1,1].imshow(imRef_t - imReg)
    ax[1,1].set_title("Diff")
    plt.show()

Run Code Online (Sandbox Code Playgroud)

在此示例中,我得到以下不良转换,因为只有三个匹配的关键点并且它们都不正确:

变换后的图像

我发现不管我的关键点/描述符参数如何,我倾向于获得的“好”功能太少。我可以做些什么来更好地对图像进行预处理,从而更可靠地获得良好的功能,或者有更好的方法将图像与不涉及关键点匹配的模板对齐?该实验的特定应用意味着我无法使用获得专利的关键点提取器/描述符,例如SURF和SIFT。

Cri*_*ngo 6

仅基于旋转、平移和缩放对齐两个图像的好方法是傅立叶梅林变换

这是使用DIPlib 中实现示例(披露:我是作者):

import PyDIP as dip

# load data
image = dip.ImageRead('image.png')
template = dip.ImageRead('template.png')
template = template.TensorElement(0) # this one is RGB, take any one channel

# pad the two images with zeros so they have equal sizes
sz = [max(image.Size(0), template.Size(0)), max(image.Size(1), template.Size(1))]
image = image.Pad(sz)
template = template.Pad(sz)

# match
res = dip.FourierMellinMatch2D(template, image)

# display
dip.JoinChannels((template,res,res)).Show()
Run Code Online (Sandbox Code Playgroud)

模板和转换图像的颜色叠加


但是,还有许多其他方法。这里的关键是模板和图像都非常简单,而且非常相似。这使得注册非常容易。

例如,假设您对模板进行了适当的缩放(我认为这应该不是问题),您需要做的就是找到旋转和平移。您可以强制旋转,只需将图像旋转一组小角度,并将每个结果与模板匹配(互相关)。具有最佳匹配(最大互相关值)的那个具有适当的旋转。如果您需要非常精确的旋转估计,您可以做第二组角度接近第一组中的最佳选择。

互相关便宜且易于计算,并导致高精度的平移估计(傅立叶梅林方法广泛使用它)。不要只是在互相关输出中找到具有最大值的像素,您可以将抛物线拟合到该抛物线周围的少数像素并使用拟合抛物线的最大值的位置。这导致翻译的亚像素估计。