2

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

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

我有一个带有曲线的图像(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)

提前致谢!

4

2 回答 2

3

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

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 轴,则 y 轴被翻转:

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

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

这样好多了

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

t.estimate(destination,source,3)

文档中我们看到调用首先获取源点,然后是目标点。所以这些论点的顺序应该颠倒过来。

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

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

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

正确翘曲

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

于 2014-11-18T18:53:23.633 回答
0

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

我发现我可以使用 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

然后我得到以下结果

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

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

所以我提出了一个新问题,并从 Stefan van der Walt 那里得到了解决方案。按照链接查看如何操作。

再次感谢你的帮助!

于 2014-11-19T08:01:55.900 回答