【问题标题】:Image warping with scikit-image and transform.PolynomialTransform使用 scikit-image 和 transform.PolynomialTransform 进行图像变形
【发布时间】:2014-11-20 00:40:41
【问题描述】:

我附上了一个zip archive,其中包含说明和重现问题所需的所有文件。

(我还没有上传图片的权限...)

我有一张带有曲线的图片(zip 存档中的 test2.png)。

我尝试扭曲它,使线条笔直。 我想到了使用 scikit-image 变换,特别是 transform.PolynomialTransform,因为该变换涉及高阶失真。

所以首先我在 x 中定期测量每条线的精确位置,以定义输入兴趣点(在文件 source_test2.csv 中)。 然后我计算相应的所需位置,位于一条直线上(在文件destination_test2.csv 中)。

图对应.png显示它的样子。

接下来,我只需使用 3 阶多项式调用 transform.PolynomialTransform()。 它找到了解决方案,但是当我使用 transform.warp() 应用它时,结果很疯狂,如文件 Crazy_Warped.png 中所示

谁能告诉我我做错了什么? 我没有运气就尝试了2阶多项式...... 我设法为子图像(仅前 400 列)进行了良好的转换。 在像我这样的情况下,transform.PolynomialTransform() 完全不稳定吗?

这是完整的代码:

import numpy as np
import matplotlib.pyplot as plt
import asciitable
import matplotlib.pylab as pylab
from skimage import io, transform

# read image 
orig=io.imread("test2.png",as_grey=True)
# read tables with reference points and their desired transformed positions
source=asciitable.read("source_test2.csv")
destination=asciitable.read("destination_test2.csv")

# format as numpy.arrays as required by scikit-image
# (need to add 1 because I started to count positions from 0...)
source=np.column_stack((source["x"]+1,source["y"]+1))
destination=np.column_stack((destination["x"]+1,destination["y"]+1))
# Plot
plt.imshow(orig, cmap='gray', interpolation='nearest')
plt.plot(source[:,0],source[:,1],'+r')
plt.plot(destination[:,0],destination[:,1],'+b')
plt.xlim(0,orig.shape[1])
plt.ylim(0,orig.shape[0])

# Compute the transformation
t = transform.PolynomialTransform()
t.estimate(destination,source,3)

# Warping the image
img_warped = transform.warp(orig, t, order=2, mode='constant',cval=float('nan'))

# Show the result
plt.imshow(img_warped, cmap='gray', interpolation='nearest')
plt.plot(source[:,0],source[:,1],'+r')
plt.plot(destination[:,0],destination[:,1],'+b')
plt.xlim(0,img_warped.shape[1])
plt.ylim(0,img_warped.shape[0])
# Save as a file
io.imsave("warped.png",img_warped)

提前致谢!

【问题讨论】:

  • 当我运行你的代码时,我的 'warped.png' 看起来和你的大不相同。
  • 对不起!!!我使用三阶多项式 t.estimate(destination,source,3) 在 zip 存档中生成文件,而上面的代码使用二阶多项式 t.estimate(destination,source,2)。我刚刚编辑了上面的代码,使其保持一致。但无论如何,没有一个能给出好的结果......

标签: python image transformation distortion scikit-image


【解决方案1】:

这里有几处错误,主要与坐标约定有关。例如,如果我们检查您绘制原始图像的代码,然后将点击的点放在它上面:

plt.imshow(orig, cmap='gray', interpolation='nearest')
plt.plot(source[:,0],source[:,1],'+r')
plt.xlim(0,orig.shape[1])
plt.ylim(0,orig.shape[0])

(我已经把目的地点去掉了让它更干净)然后我们得到下面的图像:

如您所见,如果我们将 y 轴反转,则 y 轴被翻转:

source[:,1] = orig.shape[0] - source[:,1]

在绘图之前,我们得到以下信息:

所以这是第一个问题(不要忘记反转目标点),第二个问题与变换本身有关:

t.estimate(destination,source,3)

documentation 我们看到调用首先获取源点,然后是目标点。所以这些参数的顺序应该颠倒。

最后,点击点的形式为 (x,y),但图像存储为 (y,x),因此我们必须在应用变换之前转置图像,然后再次转置回来:

img_warped = transform.warp(orig.transpose(), t, order=2, mode='constant',cval=float('nan'))
img_warped = img_warped.transpose()

当您进行这些更改时,您会得到以下扭曲的图像:

这些线条并不完全平坦,但更有意义。

【讨论】:

  • 亲爱的迈克,非常感谢您的详细解答!恐怕它不能解决我的问题......你得到的图像仍然很疯狂。应该是连续的,没有这么大的洞……
【解决方案2】:

非常感谢您的详细解答!我不敢相信我没有看到轴反转问题...感谢您了解它! 但是恐怕您的最终解决方案并不能解决我的问题……您得到的图像仍然很疯狂。它应该是连续的,没有这么大的洞和奇怪的扭曲......(见下面的最终解决方案)

我发现我可以使用 RANSAC 获得合理的解决方案:

from skimage.measure import ransac
t, inliers = ransac((destination,source), transform.PolynomialTransform, min_samples=20,residual_threshold=1.0, max_trials=1000)
outliers = inliers == False

然后我得到following result

请注意,我认为我按顺序使用 (destination,source) 是正确的!我认为这与 transform.warp 需要 inverse_map 作为转换对象的输入这一事实有关,而不是前向映射。但也许我错了?我得到的好结果表明它是正确的。

我猜多项式变换太不稳定了,使用 RANSAC 可以获得合理的解决方案。 然后我的问题是找到一种方法来更改 RANSAC 调用中的多项式顺序...... transform.PolynomialTransform() 不接受任何参数,并且默认使用二阶多项式,但从结果中我可以看到我需要一个三阶或四阶多项式。

于是我打开了new question,并从 Stefan van der Walt 那里得到了解决方案。按照链接查看如何操作。

再次感谢您的帮助!

【讨论】:

    猜你喜欢
    • 2020-09-28
    • 2017-08-11
    • 2017-04-22
    • 2019-11-01
    • 1970-01-01
    • 2016-12-27
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多