Python OpenCV实现3种滤镜效果实例
作者:苏州程序大白 发布时间:2021-06-04 10:20:27
前言
本篇文章要使用OpenCV、Numpy 和Math这3个工具包实现一个简单的滤镜编辑器。在这个滤镜编辑器中,包含了3种滤镜效果,它们分别是浮雕滤镜、雕刻滤镜和凸透镜滤镜。本篇文章将对目标图像(如图1所示)进行处理,使得目标图像分别呈现浮雕滤镜(如图2所示)、雕刻滤镜(如图3所示)和凸透镜滤镜(如图4所示)的视觉效果。
浮雕滤镜效果
为了实现浮雕滤镜效果,首先要把实现浮雕滤镜效果的原理搞清楚、弄明白。实现浮雕滤镜效果的原理如下所示:
根据灰度图像中的某一个像素的像素值与其周围像素的像素值之间的差值,确定这个像素经过卷积处理后的像素值;
由于边缘点的像素值与其周围像素的像素值之间的差值较大,经卷积处理后,导致这些边缘点较亮,从而达到凸显边缘的目的,进而形成浮雕状;
为经卷积处理后的每一个像素加上一个灰度偏移值128,作为呈现浮雕滤镜效果的图像的底色。
明确了实现浮雕滤镜效果的原理后,再来学习一下实现浮雕滤镜效果的算法。实现浮雕滤镜效果的算法如下所示:
对灰度图像中的每一个像素进行卷积处理;
实现浮雕滤镜效果的卷积核算子需采用如下矩阵:
[[1, 0], [0, -1]]
掌握了实现浮雕滤镜效果的原理和算法后,下面开始编写用于实现浮雕滤镜效果的方法,即fuDiao()
方法。fuDiao()
方法是一个自定义的、有参且有返回值的方法,fuDiao()
方法的语法格式如下所示:
def fuDiao(img):
……# 省略方法体中的代码
return canvas
参数说明:
img:与目标图像对应的灰度图像。
返回值说明:
canvas:画布,用于呈现浮雕滤镜效果的图像。
那么,fuDiao()方法
被省略的代码各自发挥怎样的作用?此外,被省略的代码又是那些呢?
先要明确fuDiao()方法中被省略的代码各自发挥的作用是什么:
因为用于实现浮雕滤镜效果的卷积核算子是一个二维矩阵,所以需要使用Numpy工具包
中的array()方法
创建这个二维矩阵。关键代码如下所示:
kernel = np.array([[1, 0], [0, -1]])
分别获取灰度图像中像素的行数和列数。关键代码如下所示:
row = img.shape[0]
col = img.shape[1]
根据灰度图像中像素的行数和列数,创建一个等高、等宽的,纯黑色的画布。关键代码如下所示:
canvas = np.zeros([row, col], dtype=np.uint8)
根据横、纵坐标,使用嵌套的for循环得到灰度图像中的每一个像素。关键代码如下所示:
for i in range(row - 1):
for j in range(col - 1):
使用实现浮雕滤镜效果的卷积核算子,对灰度图像中的每一个像素进行卷积处理,并且为经卷积处理后的每一个像素加上一个灰度偏移值128。关键代码如下所示:
new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
对于经卷积处理且加上一个灰度偏移值后的每一个像素的像素值,如果大于255,那么等于255;如果小于0,那么等于0。关键代码如下所示:
if new_value > 255:
new_value = 255
elif new_value < 0:
new_value = 0
else:
pass
把经过比较后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:
canvas[i, j] = new_value
结合fuDiao()方法
中被省略的代码和它们各自发挥的作用,就能够迅速完成fuDiao()
方法的编写。fuDiao()
方法的代码如下所示:
def fuDiao(img):
kernel = np.array([[1, 0], [0, -1]])
row = img.shape[0]
col = img.shape[1]
canvas = np.zeros([row, col], dtype=np.uint8)
for i in range(row - 1):
for j in range(col - 1):
new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
if new_value > 255:
new_value = 255
elif new_value < 0:
new_value = 0
else:
pass
canvas[i, j] = new_value
return canvas
雕刻滤镜效果
实现雕刻滤镜效果的原理与实现浮雕滤镜效果的原理大致相同,实现雕刻滤镜效果的原理如下所示:
根据灰度图像中的某一个像素的像素值与其周围像素的像素值之间的差值,确定这个像素经过卷积处理后的像素值;
由于边缘点的像素值与其周围像素的像素值之间的差值较大,经卷积处理后,导致这些边缘点较暗,从而达到凹陷边缘的目的,进而形成雕刻状;
为经卷积处理后的每一个像素加上一个灰度偏移值128,作为呈现雕刻滤镜效果的图像的底色。
虽然实现雕刻滤镜效果的原理与实现浮雕滤镜效果的原理大致相同,但是实现雕刻滤镜效果的算法与实现浮雕滤镜效果的算法大不相同。实现雕刻滤镜效果的算法如下所示:
对灰度图像中的每一个像素进行卷积处理;
实现雕刻滤镜效果的卷积核算子需采用如下矩阵:
[[-1, 0],
[0, 1]]
掌握了实现雕刻滤镜效果的原理和算法后,下面开始编写用于实现雕刻滤镜效果的方法,即diaoKe()
方法。与fuDiao()
方法相同,diaoKe()
方法也是一个自定义的、有参且有返回值的方法,diaoKe()
方法的语法格式如下所示:
def diaoKe(img):
……# 省略方法体中的代码
return canvas
参数说明:
img:与目标图像对应的灰度图像。
返回值说明:
canvas:画布,用于呈现雕刻滤镜效果的图像。
diaoKe()方法被省略的代码与fuDiao()方法被省略的代码大同小异,首先明确下diaoKe()方法中被省略的代码各自发挥的作用是什么:
用于实现雕刻滤镜效果的卷积核算子与用于实现浮雕滤镜效果的卷积核算子虽然不同,但也是一个二维矩阵,因此需要使用Numpy工具包中的array()方法创建这个二维矩阵。关键代码如下所示:
kernel = np.array([[-1, 0], [0, 1]])
分别获取灰度图像中像素的行数和列数。关键代码如下所示:
row = img.shape[0]
col = img.shape[1]
根据灰度图像中像素的行数和列数,创建一个等高、等宽的,纯黑色的画布。关键代码如下所示:
canvas = np.zeros([row, col], dtype=np.uint8)
根据横、纵坐标,使用嵌套的for循环得到灰度图像中的每一个像素。关键代码如下所示:
for i in range(row - 1):
for j in range(col - 1):
使用实现雕刻滤镜效果的卷积核算子,对灰度图像中的每一个像素进行卷积处理,并且为经卷积处理后的每一个像素加上一个灰度偏移值128。关键代码如下所示:
new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
对于经卷积处理且加上一个灰度偏移值后的每一个像素的像素值,如果大于255,那么等于255;如果小于0,那么等于0。关键代码如下所示:
if new_value > 255:
new_value = 255
elif new_value < 0:
new_value = 0
else:
pass
把经过比较后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:
canvas[i, j] = new_value
结合diaoKe()
方法中被省略的代码和它们各自发挥的作用,就能够迅速完成diaoKe()
方法的编写。diaoKe()
方法的代码如下所示:
def diaoKe(img):
kernel = np.array([[-1, 0], [0, 1]])
row = img.shape[0]
col = img.shape[1]
canvas = np.zeros([row, col], dtype=np.uint8)
for i in range(row - 1):
for j in range(col - 1):
new_value = np.sum(img[i:i + 2, j:j + 2] * kernel) + 128
if new_value > 255:
new_value = 255
elif new_value < 0:
new_value = 0
else:
pass
canvas[i, j] = new_value
return canvas
凸透镜滤镜效果
所谓凸透镜滤镜效果,相当于用户使用凸透镜观察一幅图像而成的视觉效果。实现凸透镜滤镜效果的原理与实现浮雕滤镜效果的原理和实现雕刻滤镜效果的原理大不相同。下面将着重对实现凸透镜滤镜效果的原理进行讲解:
当使用凸透镜中心观察一幅图像时,被观察的图像区域将按照一定比例进行放大;相应地,这个区域的周围区域将被压缩;
为了让放大后的图像区域看起来和谐自然,这些被压缩的周围区域要保持连续性。
明确了实现凸透镜滤镜效果的原理后,再来学习一下实现凸透镜滤镜效果的算法。实现凸透镜滤镜效果的算法如下所示:
根据目标图像的宽、高确定凸透镜的半径;
选择一个凸函数作为映射函数;
如果目标图像中的某一个像素与目标图像中心之间的距离的平方不大于凸透镜的半径的平方(两个整数进行比较,保证比较结果的精确度),就使用映射函数对这个像素的横、纵坐标进行映射处理。
掌握了实现凸透镜滤镜效果的原理和算法后,下面开始编写用于实现凸透镜滤镜效果的方法,即tuTouJing()
方法。与fuDiao()
方法和diaoKe()
方法相同,tuTouJing()
方法也是一个自定义的、有参且有返回值的方法,tuTouJing()
方法的语法格式如下所示:
def tuTouJing(img):
……# 省略方法体中的代码
return canvas
参数说明:
img:目标图像。
返回值说明:
canvas:画布,用于呈现凸透镜滤镜效果的图像。
先要明确tuTouJing()
方法中被省略的代码各自发挥的作用是什么:
分别获取目标图像中像素的行数和列数以及目标图像的通道数。关键代码如下所示:
row = img.shape[0]
col = img.shape[1]
channel = img.shape[2]
根据目标图像中像素的行数和列数以及目标图像的通道数,创建一个等高、等宽、等通道数的,纯黑色的画布。关键代码如下所示:
canvas = np.zeros([row, col, channel], dtype=np.uint8)
根据目标图像中像素的行数和列数,分别获取目标图像中心的横、纵坐标。关键代码如下所示:
center_x = row/2
center_y = col/2
比较目标图像中心的横、纵坐标的大小,把较小的数值作为凸透镜的半径。关键代码如下所示:
radius = min(center_x, center_y)
根据横、纵坐标,使用嵌套的for循环得到目标图像中的每一个像素。关键代码如下所示:
for i in range(row):
for j in range(col):
计算目标图像中的每一个像素与目标图像中心之间的距离的平方和距离。关键代码如下所示:
distance = ((i-center_x) * (i-center_x) + (j-center_y) * (j-center_y))
new_dist = math.sqrt(distance)
把目标图像中的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:
canvas[i,j,:] = img[i, j, :]
如果目标图像中的某一个像素与目标图像中心之间的距离的平方不大于凸透镜的半径的平方,就使用映射函数对这个像素的横、纵坐标进行映射处理。关键代码如下所示:
if distance <= radius**2:
new_i = np.int(np.floor(new_dist * (i-center_x) / radius + center_x))
new_j = np.int(np.floor(new_dist * (j-center_y) / radius + center_y))
把经过映射处理后的每一个像素的像素值根据坐标赋值给画布对应位置上的像素。关键代码如下所示:
canvas[i,j,:] = img[new_i, new_j, :]
结合tuTouJing()方法中被省略的代码和它们各自发挥的作用,就能够迅速完成tuTouJing()方法的编写。tuTouJing()方法的代码如下所示:
def tuTouJing(img):
row = img.shape[0]
col = img.shape[1]
channel = img.shape[2]
canvas = np.zeros([row, col, channel], dtype=np.uint8)
center_x = row/2
center_y = col/2
radius = min(center_x, center_y)
for i in range(row):
for j in range(col):
distance = ((i-center_x) * (i-center_x) + (j-center_y) * (j-center_y))
new_dist = math.sqrt(distance)
canvas[i,j,:] = img[i, j, :]
if distance <= radius**2:
new_i = np.int(np.floor(new_dist * (i-center_x) / radius + center_x))
new_j = np.int(np.floor(new_dist * (j-center_y) / radius + center_y))
canvas[i,j,:] = img[new_i, new_j, :]
return canvas
来源:https://juejin.cn/post/7084841906064064526


猜你喜欢
- python 如何实现Excel 的Vlookup功能1、Excel 中VLOOKUP具体步骤Excel 中的VLOOKUP使用说明采用下面
- 我们可以通过高级API更简洁地实现多层感知机。import torchfrom torch import nnfrom d2l import
- 摘要PIL.Image.open读入的是RGB顺序,而opencv中cv2.imread读入的是BGR通道顺序 。cv2.imread会显示
- 性能监控一、web项目(如gin中)1.使用ginpprofimport "github.com/DeanThompson/gin
- 涉及到的函数为import matplotlib.pyplot as pltfrom skimage import measure, col
- 前言最近因为线上alwayson环境的一个数据库上使用内存表。经过大概一个星期监控程序发现了一个非常严重问题这个数据库的日志文件不会截断,已
- python 如何获取文件夹中的全部文件在神经网络准备训练集的时候,经常需要从文件夹中读取全部图片。经常遇到的有两种方式1 os.listd
- 最新版本的Python发布了!今年夏天,Python 3.8发布beta版本,在2019年10月14日,第一个正式版本已准备就绪。现在,我们
- 按照网上之前版本的操作,将my.ini中的skip-grant-tables注释去掉,然后在命令行中以mysql -u root -p可以直
- JSON Schema是一个用于验证JSON数据结构的强大工具, 我查看并学习了JSON Schema的官方文档, 做了详细的记录, 分享一
- python3 判断空列表@(python3)有个判断列表是否为空的需求,试了好多方式,比如:a = []if a is not None:
- 前言,在pytorch中,当服务器上的gpu被占用时,很多时候我们想先用cpu调试下代码,那么就需要进行gpu和cpu的切换。方法1:x.t
- 导语表妹心疼我,为了逗我开心,教我用Python制作会跳舞的美女。作为新时代的活雷锋,在这里分享给大家。开发工具Python版本:3.6.4
- Deepin安装开发环境 系统环境配置挂载分区1、挂载分区(需要先卸载分区):deepin:sudo mount -t ext4 /dev/
- 本文实例讲述了Python使用re模块实现信息筛选的方法。分享给大家供大家参考,具体如下:背景平时工作中,我们经常会处理大量的元数据(Raw
- 刚刚在学习些测试报告的时候,出现一个路径的问题,找了很久的原因,竟然是少了一个反斜杠引起的,在此顺便记录一下正反斜杠的作用。在Python中
- 线程池的理想大小取决于被提交任务的类型以及所部署系统的特性。线程池应该避免设置的过大或过小,如果线程池过大,大量的线程将在相对很少的CPU和
- 最近遇到一个现象,将做好的软件放在更高分辨率的电脑上运行,会导致字体显示不完全,出现被控件遮挡的情况。具体原因可以上网查询,在这里将记录下解
- 前言订单并发这个问题我想大家都是有一定认识的,这里我说一下我的一些浅见,我会尽可能的让大家了解如何解决这类问题。在解释如何解决订单并发问题之
- 这个登陆窗口是双登陆窗口的,对IE8及早期版本不支持,可以根据自己的开发语言更换,我这个是asp的,其中的引用文件可以在网络上自行下载,如找