数字图像处理第三次作业

Fast Global Image Smoothing Based on Weighted Least Squares

在本篇论文中,主要将全局光滑问题转换为一个加权二次能量函数,最小化这个能量函数从而实现图片光滑的效果,而这个最优化问题,可以转化为一个线性方程组的求解问题,在求解效率和求解时间上都有明显的优势,同时这还是一个全局最优的线性系统。

本次作业主要对论文的基本算法Separable global smoother for 2D iamge smoothing进行了复现,使用python语言,为了加快计算速度,使用mxnet.ndarray在GPU上进行运算。

1D Fast Global Smoother

对于二维的问题,我们可以将其分解为1维的情况,所以先求解1维的线性系统。

对于1D的情况,可以定义一个WLS能量函数如下
$$
J(u) = \sum_{x} ((u_x^h - f_xh)2 + \lambda_t \sum_{i \in N_h(x)} w_{x, i}(gh)(u_xh - u_ih)2)
$$
需要极小化这个能量函数,相当于$\Delta J(u) = 0$,可以等价于求解下面的线性系统:
$$
(I_h + \lambda_t A_h) u_h = f_h
$$
使用下面的迭代方法

首先计算向前方向
$$
\tilde{c_x} = c_x / (b_x - \tilde{c_{x-1}} a_x) \
\tilde{f^h_x} = (f_x^h - \tilde{f_{x-1}^h} a_x) / (b_x - \tilde{c_{x-1}} a_x) \
(x = 1, \cdots, W-1)
$$

然后计算向后方向
$$
u_x^h = \tilde{f^h_x} - \tilde{c_x} u_{x+1}^h \quad(x = W - 2, \cdots, 0) \
u_{W-1}^h = \tilde{f_{W-1}^h}
$$

首先计算相似度权重函数$w_{p, q}(g)$如下

# 定义计算相似度权重函数
def cw_1d(p, q, g, sigma):
    '''
    计算1d上曲线g上不同位置p和q的相似性,使用sigma作为一个范围度量
    g: ndarray,W
    p: int
    q: int
    sigma: float
    '''
    norm = nd.norm(g[p] - g[q])
    return nd.exp(-norm/sigma)

为了避免streaking,每次迭代需要修改$\lambda$的值,计算公式为
$$
\lambda_t = \frac{2}{3} \frac{4^{T - t}}{4^T -1 }\lambda
$$
计算lambda的代码如下

# 每次迭代计算lambda
def compute_lamb(t, T, lamb_base):
    return 1.5 * 4**(T-t) / (4 ** T - 1) * lamb_base

求解一阶全局光滑线性系统

求解1D情况主要使用上图的(3)和(4)这两个数学公式,代码实现如下

# 求解一维的全局光滑线性系统
def compute_1d_fast_global_smoother(lamb, f, g, sigma, ctx):
    '''
    求解1d fast global smoother,给出lambda, f和g,进行前向和反向的递归求解
    '''
    w = f.shape[0]
    _c = nd.zeros(shape=w-1, ctx=ctx)
    _c[0] = -lamb * cw_1d(0, 1, g, sigma) / (1 + lamb * cw_1d(0, 1, g, sigma))
    _f = nd.zeros(shape=f.shape, ctx=ctx)
    _f[0] = f[0] / (1 + lamb * cw_1d(0, 1, g, sigma))
    # 递归前向计算
    for i in range(1, w-1):
        _c[i] = -lamb * cw_1d(i, i + 1, g, sigma) / (
            1 + lamb * (cw_1d(i, i - 1, g, sigma) + cw_1d(i, i + 1, g, sigma)) +
            lamb * _c[i - 1] * cw_1d(i, i - 1, g, sigma))
        _f[i] = (f[i] + _f[i - 1] * lamb * cw_1d(i, i - 1, g, sigma)) / (
            1 + lamb * (cw_1d(i, i - 1, g, sigma) + cw_1d(i, i + 1, g, sigma)) +
            lamb * _c[i - 1] * cw_1d(i, i - 1, g, sigma))
    _f[w-1] = (f[w-1] + _f[w-2] * lamb * cw_1d(w-1, w-2, g, sigma)) / (
            1 + lamb * (cw_1d(w-1, w-2, g, sigma)) +
            lamb * _c[w-2] * cw_1d(w-1, w-2, g, sigma))
    u = nd.zeros(shape=f.shape, ctx=ctx)
    u[w - 1] = _f[w - 1]
    # 递归向后计算
    for i in range(w - 2, -1, -1):
        u[i] = _f[i] - _c[i] * u[i + 1]
    return u.asnumpy()

完成了一维的全局光滑线性系统的求解,验证一下其是否有效

首先构造一个一维的波动输入,画出图像如下

x1 = np.random.normal(scale=0.2, size=(100))
x2 = np.random.normal(4, 0.2, size=(100))
x = np.concatenate((x1, x2))
plt.plot(np.arange(x.shape[0]), x)
output_8_1.png

通过一维全局光滑线性系统的求解,给出参数$\lambda=900, \sigma=0.07$,得到光滑之后的图像如下

u = compute_1d_fast_global_smoother(900, nd.array(x, ctx=mx.gpu(0)), nd.array(x, mx.gpu(0)), 0.07, mx.gpu(0))
plt.plot(np.arange(u.shape[0]), u)
output_10_1.png

可以明显看出能够对输入的一阶波动进行有效地光滑化,对比于论文里面的其他结果,我们认为fast global smooth具有计算时间短,优化更好的特点。

2D image separable fast global smooth

对于一张2D的图片,问题非常简单,分别在水平和竖直上应用1D的solver就能够求解,只是需要注意,在计算$w_{p, q}(g)$的时候,如果是一张RGB的图片,需要在 channel 维度的向量上计算相似度。对于这种可分的方法,虽然很直观,但是会出现streaking artifact的问题,为了解决这个问题,在每一次的迭代中,可以修改$\lambda$的值,因为这个值在每次迭代中对稀疏光滑具有显著的减少。

下面是可分离全局光滑的代码实现,只需要不断在行和列上进行计算即可,同时需要注意,如果是RGB三通道的图片,需要在每个通道上分别计算

#可分离的全局图片光滑
def Separable_global_smoother(f, T, lamb_base, sigma, ctx):
    '''
    全局图片光滑算法,输入是f和g,f是2D image, 3 channels
    '''
    print('origin lamb is {}'.format(lamb_base))
    print('sigma is {}'.format(sigma))
    H, W, C = f.shape
    u = f.copy()
    for t in range(1, T+1):
        # 计算每一步迭代的lambda_t
        lamb_t = compute_lamb(t, T, lamb_base)
        # horizontal
        for y in range(0, W):
            g = u[:, y, :]
            for c in range(C):
                f_h = u[:, y, c]
                u[:, y, c] = compute_1d_fast_global_smoother(lamb_t, f_h, g, sigma, ctx)
        # vertical
        for x in range(0, H):
            g = u[x, :, :]
            for c in range(C):
                f_v = u[x, :, c]
                u[x, :, c] = compute_1d_fast_global_smoother(lamb_t, f_v, g, sigma, ctx)
    return u

完成代码之后,我们读入一张图片,进行multi-scale manipulate测试

首先读入原图,大小是200x200

origin_img = Image.open('./jay.jpg')
plt.figure(figsize=(5, 5))
plt.title('origin image')
plt.imshow(origin_img)
output_15_1.png

对小尺度的图片做fast global smooth

接着将图片缩小尺度为100 x 100的图片,下面是缩小之后的图片,可以发现图片变得更加模糊,有很多噪点

img_100 = origin_img.resize((100, 100))
plt.figure(figsize=(5, 5))
plt.title('50 x 50 image')
plt.imshow(img_100)
output_17_1.png

接着我们进行一次迭代

lamb_base = 30**2
sigma = 255 * 0.03
ctx = mx.gpu(0)
img = np.array(img_100)
img = nd.array(img, ctx=ctx)

下面是一次迭代的结果,可以发现图片已经变得比较光滑,但是会出现条纹,具体可以看看下面红框的部分

T = 1
u1 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u1.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('1 iteration smooth result')
plt.imshow(show_u)
output_20_2.png

经过第二次迭代,下面是迭代结果,关注于两张图片的红框部分,可以发现两次迭代具有比较好的改善效果

T = 2
u2 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u2.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('2 iteration smooth result')
plt.imshow(show_u)
output_22_2.png

三面是三次迭代之后的结果,可以发现图片更加光滑了

T = 3
u3 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u3.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('3 iteration smooth result')
plt.imshow(show_u)
output_24_2.png

对原始图片做 fast global smooth

lamb_base = 30**2
sigma = 255 * 0.03
ctx = mx.gpu(0)
img = np.array(origin_img)
img = nd.array(img, ctx=ctx)

经过一次迭代之后的结果,虽然仍然存在条纹,但是比小尺度的图片效果好,这是因为小尺度的图片有更多的噪声和不光滑性

T = 1
u1 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u1.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('1 iteration smooth result')
plt.imshow(show_u)
output_28_2.png

经过第二次迭代之后的结果

T = 2
u2 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u2.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('2 iteration smooth result')
plt.imshow(show_u)
output_30_2.png

下面是三次迭代之后的结果,可以发现图片越来越光滑

T = 3
u3 = Separable_global_smoother(img, T, lamb_base, sigma, ctx)
show_u = u3.astype('uint8').asnumpy()
plt.figure(figsize=(5, 5))
plt.title('3 iteration smooth result')
plt.imshow(show_u)
output_32_2.png

与Guided Image Filter的对比

fast global image smooth是隐式求解,其将问题转移为一个优化问题,然后再转移为一个线性系统的求解,而线性系统的求解有比较成熟的解法,从而在计算效率和时间上有所提升,同时这还是一个全局最优的解法。

反观guided image filter,这篇文章我并没有非常仔细地阅读,通过大概的阅读,我发现其是一种显示的求解,通过局部的线性关系,将guided image的光滑性质转移到源图片上,通过最小化源图片与光滑图片之间的差异,将问题转移为一个岭回归问题(linear ridge regression),显示计算出双边滤波的数值,通过其进行光滑化。因为其模型的构建是在局部上进行,所以其存在解的局限性。

总结

通过本次作业,了解到光滑化图片的一些方法总结,复现了第一篇论文的算法,比较简单,没有过多的阅读论文的扩展内容。对于guided image filter,没有太过仔细的阅读,只是大体看了一下论文的核心想法,所以理解可能还不到位,有一些误解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容