写在最前
想必生活在2020的我们一定不得不对PS有所了解或者接触,虽然现在借助人工智能技术,ps已经变成了一代“神级”妖术,但是忆往昔,早期的PS其实也不过是一堆计算机视觉里的算法罢了。其实我们就可以使用计算机视觉里的技术来做一次人肉PS,提到计算机视觉逃不过的坎肯定是OpenCV,而又绕不过的坎肯定是深度学习,所以我们干脆点直接opencv-python来进行我们的旅程。只不过这次我不想剑指(剑指系列,之前写的一系列一般会由浅入深,最终目标是深挖)了,所以我们这次漫谈计算机视觉,从最基本的OpenCV慢慢讲起,一直讲到这几年比较好的深度学习各个领域。
正文开头
OpenCV一个出色的开源框架,其中Open指的就是OpenSource,开源。而CV则是计算机视觉(Computer Vision)。依靠OpenCV背后开源社区背书,其不仅在过去实现了绝大多数计算机视觉所需要的基础算法,同时也能跟随时代发展不断更新新的神经网络。
我们在之前曾经编写过OpenCV实现人脸识别,为了更好地进行之后技术的发展。我们自然需要对OpenCV进一步学习。今天就是从最基本的内容——去除噪点开始,同时学习OpenCV的基本操作。
计算机女神——蕾娜
lena图是计算机视觉非常经典的图像,她的优势在于图像颜色丰富,明暗明显,而且轮廓,边角等都有丰富存在对演示多种算法都有不错的效果(当然也很漂亮,所以更容易广泛传播)。我们这次包括之后都会有很多地方能够用到她。顺便一提,上面这幅图片来自OpenCV的官方,你可以在opencv的github项目中找到她。
图片的读取,展示与存储
opencv的安装非常简单,我们主要在python中使用它,因此使用“pip install opencv-python”进行安装即可。然后我们在python中引用OpenCV类库,并使用即可。
读取和保存的具体代码如下:
import cv2 as cv
# 读取图片
src=cv.imread('/lena.jpg')
# 存储图片
cv.imwrite('images/lena_write.jpg',src)
可以看到代码非常简单,那么如何进行如想处理呢?其实也非常简单,只需要对src进行操作即可,具体的操作粗略的来说有两大类:第一类,使用opencv的方法进行处理,包括类型转换,滤波,反转等等图像操作,在这一类操作中,图像依旧是opencv的存储格式。而第二大类,则是从比较数学的角度考虑,存储的图像本质不过是一个多维矩阵(或者多维数组),那么我们自然也可以使用python中的其他矩阵处理的类库对其进行处理,甚至编写自己的图像处理算法等等。
我们刚刚说到的展示图片,本质也是一种矩阵操作——以合适的像素展示于屏幕。我们也可以有多种方法解决该问题,下面就是有关代码:
# 展示图片
cv.namedWindow('input_image', cv.WINDOW_AUTOSIZE)
cv.imshow('input_image', src)
cv.waitKey(0)
# 删除建立的全部窗口,释放资源
cv.destroyAllWindows()
上面的代码非常简单,甚至在这里第一行还可以没有,也没有太大影响。至于代码的具体解释如下:第一行代码的参数namedWindow,是创建一个窗口,第一个参数是窗口名字,第二个是尺寸。inshow适用于展示图片的函数,第一个参数是输入的窗口的标题,第二个是存储的图像。第三行是等待输入以确定之后的操作,不设置的话,之前创建的窗口会直接退出。我们也可以通过设置具体的输入键,使窗口在接收输入之后自动执行后续的代码。最后一行是删除所有窗口来释放计算资源,主要是为了保障资源的释放,这样更安全合理一些。
图片加噪
许多时候图片会出现噪点,目前随着各种技术的提升,噪点已经比较少见了,但是我们仍然会很多更专业的领域遇到这类问题。opencv就自带了很多滤波方法可以用于去噪,同时也带有多种去噪。我们首先使用随机函数为图片添加随机的噪点,也就是白点,然后使用非局部平均算法进行去噪。由于opencv的原图大小为400×400,所以我们需要生成的随机噪点范围为(0,399)。
filePath = 'images/lena.jpg'
img = cv.imread(filePath)
for i in range(1000): #生成1000个噪点
a = random.randint(0,399)
b = random.randint(0,399)
img[a,b] = 255
cv.imshow("noise",img) # 显示噪点图
图像去噪
不同的去噪方法对应着不同的噪点,我们这里首先使用非局部平均算法进行图像去噪,这是一种比较通用的去噪方法。缺点在于由于采用图像的冗余数据进行去噪,对于边缘部分的处理效果往往比较不太好。
dst = cv.fastNlMeansDenoisingColored(img, None, 12, 12, 7, 21)
# 保存图片
cv.imwrite("/home/fonttian/Documents/MyBlog/OpenCV/images/lena_noise_1000_do.jpg",dst)
由上面可以看出该方法并不太适用于边缘噪点,同时由于进行了局部平均,因此也会丧失一些局部细节。那么这个时候我们就需要使用一些更直接的滤波方法进行去噪。常见的滤波器有很多种,滤波器本身就是一个小的矩阵,也本质等同与现在深度学习常用的卷积核。只不过我们这里是直接使用特定的军阵运算对图像进行处理。与局部平均算法类似的是均值滤波,但是如果只是简单的将几个相邻的数值进行均值计算的话,由于我们这里的添加是白噪点(最大像素255),那么就会不可避免的导致周围平均后全部变白。因此我们需要使用的是其他参数。这里我们选择了中值滤波进行滤波。两种滤波器的参数都是指参数范围。具体代码和效果如下:
# 均值模糊 去随机噪声有很好的去噪效果
#(1, 15)是垂直方向模糊,(15, 1)是水平方向模糊,我们这里是随机单个白噪点,选择(3,3)进行演示
dst = cv.blur(img, (3, 3))
中值滤波则比较合适,具体代码和效果如下
dst = cv.medianBlur(img, 3)
可以看到中值滤波在这里的去噪效果和细节保留都非常好。而如果假如我们面对更多的噪声类型,则也需要具体情况具体分析,选择合理的处理方法。这个我们将在之后的内容中一一教给大家。
专栏地址
CSDN
github
fongtian的github项目–漫谈计算机视觉
公众号
本文章首发于我司的公众号“小白白AI学习”,这是我们高寻真源(山东)教育科技有限公司创办的公众号,主要目标是为了促进大数据与人工智能在山东高校的发展和落地。欢迎大家关注我们的公众号,一起交流学习,共同进步。