二、下面就是考虑是什么样的顺序来处理待修复区域中的所有像素。作者采用的是快速行进方法Fast Marching Method。
行进算法伪代码:- δΩi = boundary of region to inpaint//修复区域的边缘
- δΩ = δΩi
- while (δΩ not empty)
- {
- p = pixel of δΩ closest to δΩi//修复距离边缘最近的像素
- inpaint p using Eqn.2//利用公式2修复p点
- advance δΩ into Ω//把边缘向里行进
- }
复制代码 看到这里,就会有疑惑了,怎么确定像素与边缘的距离呢。
算法中为待修复区域边缘构建了一个窄边(narrowBand),就是上面所说的δΩ。在opencv里是利用先将mask膨胀得到mask2(结构元素是长为2*ε+1的十字形,以中心点为原点),再用mask2减去mask得到band图,则band中非0元素即narrowBand)。从这里可以看出最初的narrowBand(即δΩ1)是不需要修复的。确定窄边的目的就是为了找到下面要修复的像素。
首先将像素分为三类,用flag标识记录:BAND:其实就是δΩ上的像素; KNOWN:就是δΩ外部不需要修复的像素;INSIDE:就是δΩ内部的等待修复的像素。
另外,每个像素还需要存储两个值:T(该像素离到边缘 δΩ的距离);I(灰度值)。
下面先说一下处理像素是按怎样的行进方式的:
1. 初始化。首先按上面说的方法找到narrowBand,flag记为BAND;窄边内部的待修复区域记为INSIDE,已知像素flag设为KNOWN。BAND和KNOWN类型的像素T值初始化为0(这里看opencv代码里好像把KNOWN也设为106),INSIDE类型像素T值设为无限大(实际中设为106)。
2. 定义一个数据结构NarrowBand(opencv中采用双向链表实现),将窄边中的像素按T值升序排列,依次加入到NarrowBand中,先处理T最小的像素。假设为p点,将p点类型改为KNOWN,然后依次处理p点的四邻域点Pi。如果Pi类型为INSIDE,若是则重新计算I,修复该点,并更新其T值,修改该点类型为BAND,加入NarrowBand(这里仍按顺序,即始终保持NarrowBand是按升序排列的)。依次进行,每次处理的都是NarrowBand中T最小的像素,直到NarrowBand中没有像素。
代码如下:- while (NarrowBand not empty)
- {
- extract P(i,j) = head(NarrowBand); /* STEP 1 *//*提取T值最小像素*/
- for (k,l) in (i-1,j),(i,j-1),(i+1,j),(i,j+1)/*依次处理该像素的四邻域像素*/
- {
- if (f(k,l)!=KNOWN)
- {
- if (f(k,l)==INSIDE)
- {
- f(k,l)=BAND; /* STEP 2修改(k,l)像素点的lag*/
- inpaint(k,l); /* STEP 3修复(k,l)像素点*/
- }
- T (k,l) = min(solve(k-1,l,k,l-1), /* STEP 4 更新(k,l)像素点的值*/
- solve(k+1,l,k,l-1),
- solve(k-1,l,k,l+1),
- solve(k+1,l,k,l+1));
- insert(k,l) in NarrowBand; /* STEP 5 将(k,l)像素点加入NarrowBand*/
- }
- }
- }
复制代码 下面是具体计算T的代码个地方,原文中的代码有错误,下面是参考opencv代码修改好的)- T(k,l)=min(solve(k-1,l,k,l-1),solve(k+1,l,k,l-1),solve(k-1,l,k,l+1),solve(k+1,l,k,l+1));
- float solve(int i1,int j1,int i2,int j2)
- {
- float sol = 1.0e6;
- if (f(i1,j1)==KNOWN)
- if (f(i2,j2)==KNOWN)
- {
- float r = sqrt(2-(T(i1,j1)-T(i2,j2))*(T(i1,j1)-T(i2,j2)));
- float s = (T(i1,j1)+T(i2,j2)-r)/2;
- if (s>=T(i1,j1) && s>=T(i2,j2)) sol = s;
- else
- { s += r; if (s>=T(i1,j1) && s>=T(i2,j2)) sol = s; }
- }
- else sol = 1+T(i1,j1));
- else if (f(i2,j2)==KNOWN) sol = 1+T(i2,j2));
- return sol;
- }
复制代码 |