介绍
在本文中,我们将深入研究一种有趣的算法,称为“seam-carving”,它可以调整图像的大小而不裁剪或扭曲其内容。本文我们将逐步构建,从头开始实现接缝雕刻算法,同时查看其背后的一些有趣的数学原理。
理解该算法需要一些微积分方面的知识,但也不是必需的。
(本文的灵感来自麻省理工学院的格兰特·桑德森的演讲。)
问题
让我们看一下这张图片。
萨尔瓦多·达利(Salvador Dali)的这幅画被命名为“记忆的永恒”。我们要通过减小图片的宽度来调整图片的大小。我们可以想到的两个有效调整方法是裁剪图片和压缩宽度。
但是,正如我们所看到的,裁剪会删除许多对象,挤压又会扭曲图片。我们希望两者兼有,即在不裁剪任何对象和不扭曲对象的情况下减小宽度。
我们可以看到,除了对象之外,图片中还有很多空白的区域。我们要在此处完成的任务是以某种方式删除对象之间的空白区域,以便保留图像中有信息的部分,同时丢弃不必要的空间。
这是一个棘手的问题,因此,我们将问题分解为更小,更易于管理的小问题。我们可以将这个问题分为两个部分。
识别图片中有用的部分(即对象)。
标识可以去除而不会扭曲图片的像素路径。
识别对象
首先我们需要将图片转换为灰度图像,这将对我们稍后进行的操作很有帮助。这是一个将RGB像素转换为灰度值的简单公式
def rgbToGrey(arr):
greyVal = np.dot(arr[...,:3], [0.2989, 0.5870, 0.1140])
return np.round(greyVal).astype(np.int32)
为了识别对象,我们可以制定以下策略:首先我们能以某种方式识别图片中的所有边缘,然后使用seam-carving算法采用不通过边缘的像素路径,通过扩展,可以不碰触任何由边缘封闭的区域来实现调整图像大小的过程。
但是,我们如何识别边缘呢?我们可以观察到,每当两个相邻像素之间的颜色发生急剧变化时,最有可能就是物体的边缘,所以我们可以将这种立即的颜色变化合理化,作为从该像素开始的新对象。
我们必须解决的下一个问题是如何识别像素值的急剧变化。现在,让我们考虑一个简单的情况