简介
这是一张需要变窄的照片 使用图像伸缩的结果,城堡的形状变了 使用图像裁剪的结果,城堡的一部分被切掉了 接缝裁剪的结果接缝裁剪(Seam carving),是一个可以针对图像内容做正确缩放的算法(由Shai Avidan和Ariel Shamir所发表)。概念上,算法会找出一系列的接缝(seam)(接缝是在图像中最不重要的一连串像素),接着利用接缝对图像做缩放。如果是要缩小图像,则移除这些接缝,若是放大,则在这些接缝的位置上,插入一些像素。接缝裁剪可以人工定义一些不会被修改的像素区域,也可以从图像中移除整个物体。接缝裁剪算法的主要目的是图像重定向(image retargeting),将图像无失真的显示在各种大小的萤幕或位置上,比如说,手机、投影幕等等。
接缝(Seams)
接缝有两种形式,水平或垂直的。接缝本身是一条由像素构成的路径,水平的接缝连接图像的左侧和右侧,路径中的像素个数和图像的列数一致。垂直接缝则类似,连接图像的顶部和底部,像素个数和图像的行数一致。接缝上每个像素都有存在一个称为重要性或者能量的指标,这个指标的值是根据像素的邻接像素计算得到的。一个像素和周边像素的相似度越高,则其重要性或者说能量就越低。
算法
1. 首先,我们拿到一张需要缩小的照片(这里以缩小举例)
2. 接着我们计算照片中每一个像素的强度(energy),这一步可以由很多算法完成,这里以gradient magnitude为例。
3. 有了每一个pixel的强度后,我们可以利用一些算法,像是dynamic programming等等,找到图中数条强度较低的seams。
Seams 在gradient magnitude图中的样子:
Seams 在原始图片中的样子:
(从seams在原始图中的样子,我们可以看到所谓强度低的seam,基本上就可以表达照片中相对不重要的部分)
4. 接着我们把这些seams拿掉,就可以拿到一张缩小后的照片。
5. 若是我们需要放大图片,则我们可以在这些我们找到的seam的旁边,增加pixel,而pixel的value可以简单的取附近的pixel的平均。
计算 seams
在这个算法中,我们每次要找出一条照片中能量最小的seam,这里的能量可以想成是频率低,或者是照片中较为不重要的pixel。而找出seam的方法有很多种,我们可以利用dynamic programming或者其他算法完成。
动态规划
以下为matlab的ref code,示范的是找出水平的seam后,放大图片。
function srcImg = seam_carving(srcImg, targetH) % srcImg为原始的图片, targetH为想要放大到的高 % h, w为原始图片的长和宽 = size( srcImg ); while h 1 && dp( j - 1, i - 1 ) < minNeighbor minNeighbor = dp( j - 1, i - 1 ); from( j, i ) = j - 1; end if j < h && dp( j + 1, i - 1 ) < minNeighbor minNeighbor = dp( j + 1, i - 1 ); from( j, i ) = j + 1; end dp( j, i ) = gMag( j, i ) + minNeighbor; end end % 在最右侧的column找出最小强度的path的终点 mn = 10 ^ 18; idx = -1; for i = 1 : h if dp( i, w ) h srcImg( path( 1, i ) + 1, i, : ) = srcImg( path( 1, i ), i, : ); else srcImg( path( 1, i ) + 1, i, : ) = srcImg( path( 1, i ), i, : ) / 2 + ... srcImg( path( 1, i ) + 2, i, : ) / 2; end end % 取得新的长和宽 = size( srcImg ); endend
<!–esi –>取自“https://www.7890.net/w/index.php?title=接缝裁剪&oldid=51757181”