有时候我们在看知乎的时候,会突然发现一张很好看的图片,想据为己有,猥猥琐琐的准备长按图片保存,发现图片上居然带了水印,这个时候该怎么办呢?哈哈哈,直接裁剪掉不就好了吗~~~
但是,作为一个新时代的程序猿,我们不能够就这么简单处理对不对。对
于是翻起了课本,发现有一种算法叫做矩阵补全(matrix compltion)可以用来做图像修复,可以把模糊成这样的新垣结衣修复
新垣结衣原图
加了两次高斯噪声的新垣结衣
修复后的新垣结衣
虽然比原图模糊了一点,但新垣结衣还是美丽好看的(甚至别有一番韵味)。那么其实我们可以想一想噪声其实就是相当于数据缺失,那么水印也是相当于数据缺失,那么矩阵补全可以把图像修复,是不是也可以把水印去掉呢?
首先,我们来了解一下什么是矩阵补全
矩阵补全(matrix completion)
根据字面意思就是有一个矩阵,里面有一些元素是缺失的,我们要想办法把缺失的元素补全,这就是矩阵补全了。
矩阵补全一开始是从Netflix 的一个比赛中流行开来的,悬赏100万美金给能够提高公司现行的matrix completion 算法10%以上的优胜队伍。
以豆瓣为例,就是根据电影的评分系统做推断。但是我们知道,豆瓣的用户千千万,电影的数量千千万,但是每个用户对只会对极少的电影进行评分,那么这个矩阵中大部分的数据是缺失的,我们要根据这个非常稀疏的矩阵,来推断整个用户群对不同电影的评分,这就是矩阵补全的实际应用。
Netflix比赛
我们这里图像也可以看做是一个矩阵(彩色图像可以看成是三个图像),残缺的图像就相当于缺失的数据,那么通过算法把缺失的数据补上也就是修复图像了。
水印去除
我的思路就是,在有水印的地方,加一块黑色遮罩,模拟数据缺失,然后运用矩阵补全的方式复原,同样用新垣结衣来试验,先用黑色 颜色块遮罩,然后就会惊人的发现
加了色块就好了,因为背景就是黑色。。。。
加了黑色色块就好了。。。。根本不用修复,但是我还是不死心的进行了一番操作
修复后的新垣结衣2
发现修复后的图片还不如原来的,因为这次矩阵补全把黑色块附近的裙子给学习过去了。看来有点风险,还是先不用新垣结衣的照片,先用别的测试测试
好吧,我们换一张风景图片,有一块小水印
有水印的图
加了遮罩的图
复原图
可以看出,复原图虽然有一点瑕疵,但是已经算是比较成功的把水印去掉了,那么说明这个算法还是比较靠谱的,那么我们还是换上新垣结衣的照片,找了一张好看的,但是没有水印,但是不影响我们的实验,我们假设她有水印,然后我们加上黑色遮罩
原图
打了码的新垣结衣
修复后的新垣结衣
不得不说,修复效果很一般,新垣结衣都毁容了!!!!!!
很愤怒,于是乱画一通发泄
乱画之后的新垣结衣
一时气愤不由得把新垣结衣乱涂乱画起来,现在后悔不已,那么能不能够复原呢?我们来看一看
再次修复的新垣结衣
结论
综上来看,用矩阵分解的办法来进行图像修复效果还是很不错的,不论是高噪声照片还是被乱涂乱画之后的照片, 可以用于家里照片被熊孩子乱涂乱画之后的修复。
但是对于水印去除呢,部分图片还是可以的,但是部分图片效果还是差强人意。
其实内在含义就是,当数据连续缺失区域不大时,如上图风景照片或者细小的涂鸦笔记,矩阵补全的效果就比较好,但是当数据连续缺失区域较大时,矩阵补全的效果可能就没有那么好,特使是用在如此美丽动人的新垣结衣身上,小小瑕疵就会被放大得更厉害。
下面是具体实现源码:
主要用的算法是LRMC
import numpy as np
def svt(mat, tau):
u, s, v = np.linalg.svd(mat, full_matrices = 0)
vec = s – tau
vec[vec < 0] = 0
return np.matmul(np.matmul(u, np.diag(vec)), v)
def LRMC(sparse_mat, dense_mat, rho, maxiter):
pos_train = np.where(sparse_mat != 0)
pos_test = np.where((sparse_mat == 0) & (dense_mat != 0))
binary_mat = sparse_mat.copy()
binary_mat[pos_train] = 1
X = sparse_mat.copy()
Z = sparse_mat.copy()
T = sparse_mat.copy()
rse = np.zeros(maxiter)
for it in range(maxiter):
Z = svt(X + T / rho, 1 / rho)
X = Z – T / rho
X[pos_train] = sparse_mat[pos_train]
T = T – rho * (Z – X)
rse[it] = (np.linalg.norm(X[pos_test] – dense_mat[pos_test], 2)
/ np.linalg.norm(dense_mat[pos_test], 2))
return X, rse
准备两张图
import imageio
import matplotlib.pyplot as plt
lena = imageio.imread(‘z6.bmp’)/255.0
sparse_lena=imageio.imread(‘z6ss.bmp’)/255.0
print(‘The shape of the image is {}.’.format(lena.shape))
dim1, dim2,dim3 = lena.shape
mask = np.round(np.random.rand(dim1, dim2,dim3)) # Generate a binary mask.
mask1 = np.round(np.random.rand(dim1, dim2,dim3))
# mask2 = np.round(np.random.rand(dim1, dim2))
plt.figure(figsize=(15,12))
plt.imshow(lena)
plt.title(‘The original Lena’)
plt.axis(‘off’)
plt.figure(figsize=(15,12))
plt.imshow(sparse_lena)
plt.title(‘The incomplete Lena’)
plt.axis(“off”)
plt.show()
因为是彩色图片,所以需要将图片分成三原色再分别进行修复
import time
start = time.time()
rho = 0.005
maxiter = 50
mat_hat, rse_svt = LRMC(sparse_lena[:,:,0], lena[:,:,0], rho, maxiter)
print(‘Running time:%dseconds.’%(end – start))
start = time.time()
mat_hat1, rse_svt1 = LRMC(sparse_lena[:,:,1], lena[:,:,1], rho, maxiter)
print(‘Running time:%dseconds.’%(end – start))
start = time.time()
mat_hat2, rse_svt2 = LRMC(sparse_lena[:,:,2], lena[:,:,2], rho, maxiter)
print(‘Running time:%dseconds.’%(end – start))
#修复完把三张图拼接在一起
c=[]
for i in range(dim1):
c.append([])
for j in range(dim2):
c[i].append([mat_hat[i][j],mat_hat1[i][j],mat_hat2[i][j]])
显示修复后的图片
plt.figure(figsize=(20,15))
# plt.imshow(mat_hat)
plt.imshow(c)
# plt.imshow(mat_hat2)
plt.savefig(“lbk.png”)
plt.axis(‘off’)
plt.show()
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222440.html原文链接:https://javaforall.net
