科 / 研 / 图 / 像 / 处 / 理
StackReg 是 ImageJ 的一个图像配准的插件,StackReg 支持不同类型的配准,配准效果非常 Robust。
之前的文章有介绍利用 StackReg 进行图像配准:
点击跳转《ImageJ | 图像自动配准》
但 ImageJ 中的 StackReg 只支持线性配准,不支持非线性配准。且不好进行批量处理。
pyStackReg 将 StackReg 移植到了 Python,并提供了一些额外的功能:
https://pystackreg.readthedocs.io/en/latest/readme.html
pyStackReg 提供五种类型的配准:
translation
rigid body (translation + rotation)
scaled rotation (translation + rotation + scaling)
affine (translation + rotation + scaling + shearing)
bilinear (non-linear transformation)
这篇文章会介绍怎样安装 pyStackReg,并利用 pyStackReg 进行图像配准。
一、安装 pyStackReg
首先你需要在电脑上安装 Anaconda,生成一个新的环境,方便不同 Python 包的版本管理:
conda create --name stackReg
激活该环境:
conda activate stackReg
安装 pyStackReg 包:
pip install pystackreg
二、实例代码
1、单张图像配准
from pystackreg import StackReg
from skimage import io
#load reference and "moved" image
ref = io.imread('reference_image.tif')
mov = io.imread('changed_image.tif')
#Translational transformation
sr = StackReg(StackReg.TRANSLATION)
out_tra = sr.register_transform(ref, mov)
这里配准用的是 Translation,StackReg 有5种配准类型:
StackReg.TRANSLATION
StackReg.RIGID_BODY
StackReg.SCALED_ROTATION
StackReg.AFFINE
StackReg.BILINEAR
如果想要提取变换矩阵 (Transformation Matrix),用于其他图像的配准:
import numpy as np
#Get transformation matrix
tmat = sr.transform(mov)
np.save('transformation_matrices.npy', tmat)
tmat_loaded = np.load('transformation_matrices.npy')
# make sure you use the correct transformation here!
sr = StackReg(StackReg.TRANSLATION)
# transform stack using the tmat loaded from file
out_tra = sr.transform(mov, tmat=tmat_loaded)
这里提供一个自动化测试5种配准类型的脚本:
import os
import sys
import numpy as np
from matplotlib import pyplot as plt
from skimage import transform, io, exposure
from pystackreg import StackReg
#load reference and "moved" image
ref = io.imread('reference_image.tif')
mov = io.imread('changed_image.tif')
# define transformations
transformations = {
'TRANSLATION': StackReg.TRANSLATION,
'RIGID_BODY': StackReg.RIGID_BODY,
'SCALED_ROTATION': StackReg.SCALED_ROTATION,
'AFFINE': StackReg.AFFINE,
'BILINEAR': StackReg.BILINEAR
}
def composite_images(imgs, equalize=False, aggregator=np.mean):
if equalize:
imgs = [exposure.equalize_hist(img) for img in imgs]
imgs = [img / img.max() for img in imgs]
if len(imgs) < 3:
imgs += [np.zeros(shape=imgs[0].shape)] * (3-len(imgs))
imgs = np.dstack(imgs)
return imgs
def show_transformation(tmat, ax=None):
if ax is None:
_, ax = plt.subplots()
p = np.array([[1,120,1], [1,1,1], [250, 1, 1], [250,120,1], [1,120,1]])
ax.plot(p[:, 0], p[:,1])
q=np.dot(p, tmat.T)
ax.plot(q[:, 0], q[:,1])
ax.invert_xaxis()
ax.invert_yaxis()
ax.legend(['Original image', 'transformed image'])
f, ax = plt.subplots(5, 2, figsize=(16, 18))
for i, (name, tf) in enumerate(transformations.items()):
sr = StackReg(tf)
reg = sr.register_transform(ref, mov)
reg = reg.clip(min=0)
after_reg = composite_images([ref, reg])
ax[i][0].imshow(after_reg, cmap='gray', vmin=0, vmax=1)
ax[i][0].set_title(name + ' (overlay on reference)')
ax[i][0].axis('off')
if name != 'BILINEAR':
show_transformation(sr.get_matrix(), ax[i][1])
ax[i][1].set_title(name + ' (applied on a rectangle)')
else:
ax[i][1].axis('off')
可以根据 5 种配准的方法得出的结果,决定选用哪种方法进行后续配准:
2、整个Stack配准
from pystackreg import StackReg
from skimage import io
# load image stack
data_path = os.getcwd()
unreg = io.imread(os.path.join(data_path, 'ratBrain.tif'))
# define transformation
sr = StackReg(StackReg.RIGID_BODY)
# register each frame to the previous (already registered) one
out_previous = sr.register_transform_stack(unreg, reference='previous')
# register to first image
out_first = sr.register_transform_stack(unreg, reference='first')
# register to mean image
out_mean = sr.register_transform_stack(unreg, reference='mean')
pyStackReg 提供了register_transform_stack 函数,可以直接对一个 Image Stack 进行配准。
reference 的选择主要有 3 种方式:
'previous': 每一张图跟前一张图进行配准;
'first': 所有图跟第一张图进行配准;
'mean': 所有图跟整个Stack的Mean进行配准;
往期回顾
1
2
3
4