我正在尝试在由3x3矩阵(使用齐次坐标)转换的matplotlib中显示图像。我有以下内容:
import numpy as np
import matplotlib as mp
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
class GenericTransform(mp.transforms.Transform):
input_dims = 2
output_dims = 2
is_separable = False
# expects a 3x3 matrix as a numpy array
def __init__(self, matrix):
super().__init__()
self.matrix = matrix
self.has_inverse = (np.linalg.det(matrix) != 0)
def transform(self, values):
# append 1 to each coordinate in `values`
hvals = np.insert(values, 2, 1, axis=1)
# do the transformations
thvals = np.matmul(self.matrix, hvals.transpose()).transpose()
# TODO: perspective divison?
# get rid of extra dimension and return
return thvals[:, 0:2]
def transform_non_affine(self, values):
return self.transform(values)
def inverted(self):
return GenericTransform(np.linalg.inv(self.matrix))
# add an image to the plot with a transformation
def addImage(filename, matrix):
transform = GenericTransform(matrix)
img = mpimg.imread(filename)
imgShow = plt.imshow(img, alpha=1)
imgShow.set_transform(transform + imgShow.get_transform())
我用图像文件名和矩阵调用addImage
,然后调用plt.show()
,转换似乎正确应用。但是,绘制的图像看起来会超出其边界范围,就像填充图像角落定义的轴对齐框一样:
看似“反射”的线是我想要简单地切断图像的地方。我对matplotlib不太熟悉,所以我很困惑为什么会这样。我松散地追随this。我还尝试使用路径手动剪辑图像:
# add an image to the plot with a transformation
def addImage(filename, matrix):
transform = GenericTransform(matrix)
img = mpimg.imread(filename)
x = img.shape[1]
y = img.shape[0]
path = transform.transform_path(mp.path.Path([[0,0], [x,0], [x,y], [0,y], [0,0]]))
patch = mp.patches.PathPatch(path, facecolor="none")
imgShow = plt.imshow(img, alpha=1, clip_on=True, clip_path=patch)
imgShow.set_transform(transform + imgShow.get_transform())
但这并不是我想要的。具体来说,每当我调整窗口大小或移动绘图时,剪切区域都会保持静止,因为背景中的图像会移动。如何才能正确剪辑图像?
另外,我知道我进行转换的方式对于透视转换可能是错误的,但我想自己解决这个问题。
答案 0 :(得分:1)
几个小时后,我终于明白了。我不太明白如何将变换应用于剪辑路径。最终,这有效:
def addImage(filename, matrix):
transform = GenericTransform(matrix)
img = mpimg.imread(filename)
imgShow = plt.imshow(img, alpha=1, clip_on=True, interpolation="bilinear")
oldTransform = imgShow.get_transform()
imgShow.set_transform(transform + oldTransform)
w = img.shape[1]
h = img.shape[0]
path = transform.transform_path(mp.path.Path([[0,0], [w,0], [w,h], [0,h], [0,0]]))
patch = mp.patches.PathPatch(path, facecolor="none")
patch.set_transform(oldTransform)
imgShow.set_clip_path(patch)