我附上一个zip archive,其中包含说明和重现问题所需的所有文件。
(我还没有上传图片的权限......)
我有一个带有曲线的图像(zip存档中的test2.png)。
我试着扭曲它以使线条笔直。 我想过使用scikit-image变换,特别是transform.PolynomialTransform,因为变换涉及高阶失真。
首先,我在x中以固定间隔测量每条线的精确位置,以定义输入兴趣点(在文件source_test2.csv中)。 然后我计算相应的所需位置,位于一条直线上(在文件destination_test2.csv中)。
figure correspondence.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)
提前致谢!
答案 0 :(得分: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轴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()
进行这些更改时,会出现以下扭曲图像:
这些线条并不完全平坦,但更有意义。
答案 1 :(得分: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
然后我得到following result
请注意,我认为我按顺序使用(目标,来源)!我认为这与transform.warp需要inverse_map作为转换对象的输入而不是前向映射这一事实有关。但也许我错了?我得到的好结果表明它是正确的。
我猜多项式变换太不稳定了,使用RANSAC可以得到合理的解决方案。 我的问题是找到一种方法来改变RANSAC调用中的多项式顺序...... transform.PolynomialTransform()不接受任何参数,默认情况下使用二阶多项式,但从结果我可以看出我需要一个三阶或四阶多项式。
所以我打开了new question,得到了Stefan van der Walt的解决方案。点击链接查看如何操作。
再次感谢您的帮助!