本篇文章小编给大家分享一下Python实现图像特效中油画效果代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。
一 基本原理
如下面的两幅图所示,油画用对了地方会使得图像一下子显得文艺起来了呢!
拍出的图像
转化为油画
那么将一幅图像转化为油画类型的图案是怎么实现的呢?为了将一幅普通的图像转化为油画,一般需要以下的几个步骤:
(1)将图像转化为灰度图像
(2)将图像划分为一个个小方框(4*4,6*6...),并统计其中的每一个像素点像素值
(3)对方框中的像素点的的灰度值进行量化(可以参考我之前的关于量化的文章),并对不同的等级的像素点数目进行计数
(4)找到方框中灰度等级最多的像素点,并对这些像素点的灰度值求平均
(5)用平均值代替原像素像素值
二 代码实现
首先还是经典操作,读取图像信息:
""" Author:XiaoMa date:2021/12/10 """ import cv2 import numpy as np img = cv2.imread(r'E:From ZhihuFor the deskcvyouhua.jpg') img = cv2.resize(img, dsize = None, fx = 0.2, fy = 0.2) #由于该算法计算量较大,首先对其大小进行调整 cv2.imshow('W0', img) cv2.waitKey(0) #获取图片宽高 height, width = img.shape[:2] print(height, width)
得到图像信息如下:
对图像进行油画特效处理,代码已经添加了注释,有注释的不清楚的地方可以在评论区讨论或者私信留言,看到会回复大家的:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#将图像转化为灰度图像 dst = np.zeros((height, width, 3), np.uint8)#创建一个和原图等大小的全零矩阵 #----------------------------------------------------------------------- #使用for循环嵌套来遍历图像中的每一个像素点 #----------------------------------------------------------------------- for i in range(2, height-2): for j in range(2, width-2): # ---------------------------------------------------------- # 方框为4*4,对方框内像素点进行量化并记录不同等级的像素点的个数 # ------------------------------------------------------------ array1 = np.zeros(8, np.uint8)#将像素点的值量化为8份,定义数组记录不同等级像素点的个数 for m in range(-2, 2): for n in range(-2, 2): p1 = int(gray[i+m, j+n]/32)#量化操作 array1[p1] = array1[p1] + 1#该数组用来记录不同量化级别下的像素点,比如array1[0]代表等级一下的像素点的个数,即像素值为(0~64)的像素点的个数 #----------------------------------------------------------- #在上面的数组中寻找最大值,即寻找数目最多的像素等级 #------------------------------------------------------------ currentMax = array1[0] l = 0#用来封装最大值在数组中的位置 for k in range(0, 8): if currentMax < array1[k]: currentMax = array1[k] l = k #------------------------ #求数目最多的像素等级的平均 #------------------------ for m in range(-2, 2): for n in range(-2, 2): if gray[i + m, j + n] >= (l * 32) and gray[i + m, j + n] <= ((l + 1) * 32): (b, g, r) = img[i + m, j + n] dst[i, j] = (b, g, r) cv2.imshow('youhua', dst) cv2.waitKey(0) cv2.destroyAllWindows()
得到的结果如下:
三 总体实现代码以及保存
总体的代码以及保存方式如下,大家修改一下读取和保存的路径就可以用了,如果想了解一下实现算法可以先敲一遍代码:
""" Author:XiaoMa date:2021/12/15 """ import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r'E:From ZhihuFor the deskcvyouhua.jpg') img = cv2.resize(img, dsize = None, fx = 0.2, fy = 0.2) #由于该算法计算量较大,首先对其大小进行调整 cv2.imshow('W0', img) cv2.waitKey(0) #获取图片宽高 height, width = img.shape[:2] print(height, width) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#将图像转化为灰度图像 dst = np.zeros((height, width, 3), np.uint8)#创建一个和原图等大小的全零矩阵 #----------------------------------------------------------------------- #使用for循环嵌套来遍历图像中的每一个像素点 #----------------------------------------------------------------------- for i in range(2, height-2): for j in range(2, width-2): # ---------------------------------------------------------- # 方框为4*4,对方框内像素点进行量化并记录不同等级的像素点的个数 # ------------------------------------------------------------ array1 = np.zeros(8, np.uint8)#将像素点的值量化为8份,定义数组记录不同等级像素点的个数 for m in range(-2, 2): for n in range(-2, 2): p1 = int(gray[i+m, j+n]/32)#量化操作 array1[p1] = array1[p1] + 1#该数组用来记录不同量化级别下的像素点,比如array1[0]代表等级一下的像素点的个数,即像素值为(0~64)的像素点的个数 #----------------------------------------------------------- #在上面的数组中寻找最大值,即寻找数目最多的像素等级 #------------------------------------------------------------ currentMax = array1[0] l = 0#用来封装最大值在数组中的位置 for k in range(0, 8): if currentMax < array1[k]: currentMax = array1[k] l = k #------------------------ #求数目最多的像素等级的平均 #------------------------ for m in range(-2, 2): for n in range(-2, 2): if gray[i + m, j + n] >= (l * 32) and gray[i + m, j + n] <= ((l + 1) * 32): (b, g, r) = img[i + m, j + n] dst[i, j] = (b, g, r) cv2.imshow('youhua', dst) cv2.waitKey(0) cv2.destroyAllWindows() #------------------------------------------------ #保存图像(以前的文章中介绍过,有不懂的地方可以去考古) #------------------------------------------------ plt.rcParams['font.family'] = 'SimHei' #将全局中文字体改为黑体 ImgGroup = [img, gray, dst] ImgTitle = ['原图', '灰度图', '油画'] a = plt.figure(figsize=(30, 10)) #创建画布 for i in range(0, 3): ImgGroup[i] = cv2.cvtColor(ImgGroup[i], cv2.COLOR_BGR2RGB) plt.subplot(1, 3, i + 1) plt.imshow(ImgGroup[i]) plt.title(ImgTitle[i]) plt.suptitle('图像油画特效') plt.xticks([]) plt.yticks([]) plt.savefig(r'E:From ZhihuFor the deskAcvyouhua.jpg') plt.show()
得到结果如下:
创造与魔法 安卓版v1.0.0750
创造与魔法是一款开放世界手游,在游戏中玩家可探索这个奇妙的世
创造与魔法修改版 最新版v1.0.0750
创造与魔法无限点券版是款探索冒险游戏,该款游戏的操作还是蛮自
战争与文明官方版本 安卓版v1.7.16
战争与文明是一款由上海邮通科技有限公司开发的战争策略游戏,这
迷你世界0元领皮肤无限迷你币版 最新安卓版v1.43.0
迷你世界0元购买皮肤版是这款开放沙盒冒险建造游戏的特殊破解版
创造与魔法无限经验版 安卓版v1.0.0750
创造与魔法无限经验版是款可以改造环境,整个游戏的自由度还是蛮