资讯专栏INFORMATION COLUMN

Python 计算机视觉(十五)—— 图像特效处理

LeexMuller / 412人阅读

摘要:话不多说,先是本系列文章的经典操作之读取图像信息得到的图像信息如下毛玻璃特效毛玻璃特效的原理是在当前的像素点的邻域内随机取一个像素点来代替它,从而达到一个毛玻璃的模糊的效果。

参考的一些文章以及论文我都会给大家分享出来 —— 链接就贴在原文,论文我上传到资源中去,大家可以免费下载学习,如果当天资源区找不到论文,那就等等,可能正在审核,审核完后就可以下载了。大家一起学习,一起进步!加油!! 

目录

 前言

1. 毛玻璃特效

2. 浮雕特效

3. 素描特效

4. 怀旧特效

5. 流年特效

6. 水波特效

7. 卡通特效

8. 将图像都汇总到一张图中

9. 总体代码

结束语


 前言

       图像特效处理一般是对图像的像素点的通道、灰度值值等进行操作,达到想要的结果,下面将会给大家一一呈现一些简单特效的原理以及代码实现,希望能够对大家有一定的帮助。

话不多说,先是本系列文章的经典操作之读取图像信息:

"""Author:XiaoMadate:2021/11/16"""import cv2import numpy as npimport mathimport matplotlib.pyplot as pltimg0 = cv2.imread("E:/From Zhihu/For the desk/cvfifteen1.jpg")img1 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)h, w = img0.shape[:2]print(h, w)cv2.imshow("W0", img0)cv2.imshow("W1", img1)cv2.waitKey(delay = 0)

得到的图像信息如下: 

386 686 

1. 毛玻璃特效

       毛玻璃特效的原理是在当前的像素点的邻域内随机取一个像素点来代替它,从而达到一个毛玻璃的模糊的效果。代码如下,已经添加了注释,如果有看不懂的地方评论区留言大家一起讨论。

#毛玻璃特效img2 = np.zeros((h, w, 3), np.uint8)        #生成与原图像等大的全零矩阵for i in range(0, h - 6):                   #防止下面的随机数超出边缘    for j in range(0, w - 6):        index = int(np.random.random()*6)   #0~6的随机数        (b, g, r) = img0[i + index, j + index]        img2[i, j] = (b, g, r)cv2.imshow("W2", img2)cv2.waitKey(delay = 0)

得到的效果如下:

       由于取随机数的时候必须要减去边缘的那些像素点值,所以图像的右边界和下边界不可避免的出现了未填充区域。 

       在写博客的时候突然心生一计,如果我们在创建全零矩阵时就对边界进行限定不就可以了嘛,试了一下,果然可以!!如下:

#毛玻璃特效img2 = np.zeros((h - 6, w - 6, 3), np.uint8)        #生成的全零矩阵考虑到了随机数范围,变小了for i in range(0, h - 6):                   #防止下面的随机数超出边缘    for j in range(0, w - 6):        index = int(np.random.random()*6)   #0~6的随机数        (b, g, r) = img0[i + index, j + index]        img2[i, j] = (b, g, r)cv2.imshow("W2", img2)cv2.waitKey(delay = 0)

经过上述方式生成的毛玻璃特效就不会出现未填充部位,但图像的尺寸确实小了。 

2. 浮雕特效

       Python 实现浮雕特效的原理是先勾勒出图像的边界曲线,然后降低边界周围的像素值,从而得到一幅立体的浮雕形式的图像

#浮雕特效(需要对灰度图像进行操作)img3 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w - 2):                #减2的效果和上面一样        grayP0 = int(img1[i, j])        grayP1 = int(img1[i, j + 2])         #取与前一个像素点相邻的点        newP = grayP0 - grayP1 + 150         #得到差值,加一个常数可以增加浮雕立体感        if newP > 255:            newP = 255        if newP < 0:            newP = 0        img3[i, j] = newPcv2.imshow("W3", img3)cv2.waitKey(delay = 0)

得到效果如下:

3. 素描特效

该特效实现较为简单,直接在代码中给出注释:

#素描特效img4 = 255 - img1                                               #对原灰度图像的像素点进行反转blurred = cv2.GaussianBlur(img4, (21, 21), 0)                   #进行高斯模糊inverted_blurred = 255 - blurred                                #反转img4 = cv2.divide(img1, inverted_blurred, scale = 127.0)        #灰度图像除以倒置的模糊图像得到铅笔素描画cv2.imshow("W4", img4)cv2.waitKey(delay = 0)

4. 怀旧特效

怀旧特效需要专门的 R, G, B 通道的转换公式来对图像的三个通道进行处理,转换公式为:

实现代码如下:

#怀旧特效img5 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w):        B = 0.272 * img0[i, j][2] + 0.534 * img0[i, j][1] + 0.131 * img0[i, j][0]        G = 0.349 * img0[i, j][2] + 0.686 * img0[i, j][1] + 0.168 * img0[i, j][0]        R = 0.393 * img0[i, j][2] + 0.769 * img0[i, j][1] + 0.189 * img0[i, j][0]        if B > 255:            B = 255        if G > 255:            G = 255        if R > 255:            R = 255        img5[i, j] = np.uint8((B, G, R))cv2.imshow("W5", img5)cv2.waitKey(delay = 0)

 得到效果如下:

       这个特效计算量比起前面的几种还是有点大的,需要对像素点进行遍历,然后计算每一个点的三个通道的值。 

5. 流年特效

       比起前面的怀旧特效,流年特效只需要对图像的每一个像素点的蓝色通道(B)进行简单调整就可以了,首先是对其开根号,然后乘以一个参数即可,实现代码如下:

#流年特效img6 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w):        B = math.sqrt(img0[i, j][0]) *14       # B通道的数值开平方乘以参数14        G = img0[i, j][1]        R = img0[i, j][2]        if B > 255:            B = 255        img6[i, j] = np.uint8((B, G, R))cv2.imshow("W6", img6)cv2.waitKey(delay = 0)

 大家可以多修改参数进行调试,观察不同的参数下的效果。

6. 水波特效

       水波特效是使用三角函数得到波纹的传递函数,然后根据设定的中心进行特效的生成,该部分的算法有点难度,多尝试几次就可以了,以后博主有时间会专门出一片水波特效的介绍博文。实现代码如下:

#水波特效img7 = np.zeros((h, w, 3), np.uint8)wavelength = 20                                 #定义水波特效波长amplitude = 30                                  #幅度phase = math.pi / 4                             #相位centreX = 0.5                                   #水波中心点XcentreY = 0.5                                   #水波中心点Yradius = min(h, w) / 2icentreX = w*centreX                            #水波覆盖宽度icentreY = h*centreY                            #水波覆盖高度for i in range(0, h):    for j in range(0, w):        dx = j - icentreX        dy = i - icentreY        distance = dx * dx + dy * dy        if distance > radius * radius:            x = j            y = i        else:            # 计算水波区域            distance = math.sqrt(distance)            amount = amplitude * math.sin(distance / wavelength * 2 * math.pi - phase)            amount = amount * (radius - distance) / radius            amount = amount * wavelength / (distance + 0.0001)            x = j + dx * amount            y = i + dy * amount        # 边界判断        if x < 0:            x = 0        if x >= w - 1:            x = w - 2        if y < 0:            y = 0        if y >= h - 1:            y = h - 2        p = x - int(x)        q = y - int(y)        # 图像水波赋值        img7[i, j, :] = (1 - p) * (1 - q) * img0[int(y), int(x), :] + p * (1 - q) * img0[int(y), int(x), :]        + (1 - p) * q * img0[int(y), int(x), :] + p * q * img0[int(y), int(x), :]cv2.imshow("W7", img7)cv2.waitKey(delay = 0)

得到效果如下:
由于这张图片刚好波纹附近是头发,导致得到的波纹显得不太清晰,可以换几张图片尝试一下,看看该算法的效果。 

7. 卡通特效

       该特效主要原理是提取图像的边界轮廓,然后和原图像相与得到最终的卡通化效果,代码如下,已添加注释:

#卡通特效num_bilateral = 7                                      #定义双边滤波的数目for i in range(num_bilateral):                         #双边滤波处理,除去噪声,保留边界    img_color = cv2.bilateralFilter(img0, d = 9, sigmaColor = 5, sigmaSpace = 3)img_blur = cv2.medianBlur(img1, 7)                     # 中值滤波处理img_edge = cv2.adaptiveThreshold(img_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, blockSize = 5, C = 2) #边缘检测及自适应阈值化处理,提取边界img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)  #转换回彩色图像img8 = cv2.bitwise_and(img0, img_edge)          #图像的与运算cv2.imshow("W8", img8)cv2.waitKey(delay = 0)

得到效果如下:
如果对实现的效果不满意,可以不断调整双边滤波和中值滤波的参数,直到找到较为满意的效果。

8. 将图像都汇总到一张图中

基础操作,没啥可注释的,直接上代码:

#将所有图像保存到一张图中plt.rcParams["font.family"] = "SimHei"imgs = [img0, img1, img2, img3, img4, img5, img6, img7, img8]titles = ["原图", "灰度图", "毛玻璃特效", "浮雕特效", "素描特效", "怀旧特效", "流年特效", "水波特效", "卡通特效"]for i in range(9):    imgs[i] = cv2.cvtColor(imgs[i], cv2.COLOR_BGR2RGB)    plt.subplot(3, 3, i + 1)    plt.imshow(imgs[i])    plt.title(titles[i])    plt.xticks([])    plt.yticks([])plt.suptitle("图像特效处理")plt.savefig("E:/From Zhihu/For the desk/cvfifteenresult.jpg", dpi = 1080)plt.show()

得到最终的总图 :

9. 总体代码

       修改一下图像读取路径就可以使用了。还是那句话,建议从头慢慢来一遍,当然如果你只是想给女朋友生成一张素描或者浮雕的话那就无所谓了哈哈哈。

"""Author:XiaoMadate:2021/11/16"""import cv2import numpy as npimport mathimport matplotlib.pyplot as pltimg0 = cv2.imread("E:/From Zhihu/For the desk/cvfifteen1.jpg")img1 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)h, w = img0.shape[:2]print(h, w)cv2.imshow("W0", img0)cv2.imshow("W1", img1)cv2.waitKey(delay = 0)#毛玻璃特效img2 = np.zeros((h - 6, w - 6, 3), np.uint8)        #生成的全零矩阵考虑到了随机数范围,变小了for i in range(0, h - 6):                   #防止下面的随机数超出边缘    for j in range(0, w - 6):        index = int(np.random.random()*6)   #0~6的随机数        (b, g, r) = img0[i + index, j + index]        img2[i, j] = (b, g, r)cv2.imshow("W2", img2)cv2.waitKey(delay = 0)#浮雕特效(需要对灰度图像进行操作)img3 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w - 2):                #减2的效果和上面一样        grayP0 = int(img1[i, j])        grayP1 = int(img1[i, j + 2])         #取与前一个像素点相邻的点        newP = grayP0 - grayP1 + 150         #得到差值,加一个常数可以增加浮雕立体感        if newP > 255:            newP = 255        if newP < 0:            newP = 0        img3[i, j] = newPcv2.imshow("W3", img3)cv2.waitKey(delay = 0)#素描特效img4 = 255 - img1                                               #对原灰度图像的像素点进行反转blurred = cv2.GaussianBlur(img4, (21, 21), 0)                   #进行高斯模糊inverted_blurred = 255 - blurred                                #反转img4 = cv2.divide(img1, inverted_blurred, scale = 127.0)        #灰度图像除以倒置的模糊图像得到铅笔素描画cv2.imshow("W4", img4)cv2.waitKey(delay = 0)#怀旧特效img5 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w):        B = 0.272 * img0[i, j][2] + 0.534 * img0[i, j][1] + 0.131 * img0[i, j][0]        G = 0.349 * img0[i, j][2] + 0.686 * img0[i, j][1] + 0.168 * img0[i, j][0]        R = 0.393 * img0[i, j][2] + 0.769 * img0[i, j][1] + 0.189 * img0[i, j][0]        if B > 255:            B = 255        if G > 255:            G = 255        if R > 255:            R = 255        img5[i, j] = np.uint8((B, G, R))cv2.imshow("W5", img5)cv2.waitKey(delay = 0)#流年特效img6 = np.zeros((h, w, 3), np.uint8)for i in range(0, h):    for j in range(0, w):        B = math.sqrt(img0[i, j][0]) *14       # B通道的数值开平方乘以参数14        G = img0[i, j][1]        R = img0[i, j][2]        if B > 255:            B = 255        img6[i, j] = np.uint8((B, G, R))cv2.imshow("W6", img6)cv2.waitKey(delay = 0)#水波特效img7 = np.zeros((h, w, 3), np.uint8)wavelength = 20                                 #定义水波特效波长amplitude = 30                                  #幅度phase = math.pi / 4                             #相位centreX = 0.5                                   #水波中心点XcentreY = 0.5                                   #水波中心点Yradius = min(h, w) / 2icentreX = w*centreX                            #水波覆盖宽度icentreY = h*centreY                            #水波覆盖高度for i in range(0, h):    for j in range(0, w):        dx = j - icentreX        dy = i - icentreY        distance = dx * dx + dy * dy        if distance > radius * radius:            x = j            y = i        else:            # 计算水波区域            distance = math.sqrt(distance)            amount = amplitude * math.sin(distance / wavelength * 2 * math.pi - phase)            amount = amount * (radius - distance) / radius            amount = amount * wavelength / (distance + 0.0001)            x = j + dx * amount            y = i + dy * amount        # 边界判断        if x < 0:            x = 0        if x >= w - 1:            x = w - 2        if y < 0:            y = 0        if y >= h - 1:            y = h - 2        p = x - int(x)        q = y - int(y)        # 图像水波赋值        img7[i, j, :] = (1 - p) * (1 - q) * img0[int(y), int(x), :] + p * (1 - q) * img0[int(y), int(x), :]        + (1 - p) * q * img0[int(y), int(x), :] + p * q * img0[int(y), int(x), :]cv2.imshow("W7", img7)cv2.waitKey(delay = 0)#卡通特效num_bilateral = 7                                      #定义双边滤波的数目for i in range(num_bilateral):                         #双边滤波处理    img_color = cv2.bilateralFilter(img0, d = 9, sigmaColor = 5, sigmaSpace = 3)img_blur = cv2.medianBlur(img1, 7)                     # 中值滤波处理img_edge = cv2.adaptiveThreshold(img_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, blockSize = 5, C = 2) #边缘检测及自适应阈值化处理img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB)  #转换回彩色图像img8 = cv2.bitwise_and(img0, img_edge)          #图像的与运算cv2.imshow("W8", img8)cv2.waitKey(delay = 0)#将所有图像保存到一张图中plt.rcParams["font.family"] = "SimHei"imgs = [img0, img1, img2, img3, img4, img5, img6, img7, img8]titles = ["原图", "灰度图", "毛玻璃特效", "浮雕特效", "素描特效", "怀旧特效", "流年特效", "水波特效", "卡通特效"]for i in range(9):    imgs[i] = cv2.cvtColor(imgs[i], cv2.COLOR_BGR2RGB)    plt.subplot(3, 3, i + 1)    plt.imshow(imgs[i])    plt.title(titles[i])    plt.xticks([])    plt.yticks([])plt.suptitle("图像特效处理")plt.savefig("E:/From Zhihu/For the desk/cvfifteenresult.jpg", dpi = 1080)plt.show()

结束语

       本篇文章总结了图像特效处理中的毛玻璃、浮雕、素描等一些操作的原理和简单实现,对于一些比较复杂的算法后面有时间再专门写一篇博文进行介绍,还有油画特效本文也没有介绍,由于该特效算法也和水波特效一样有难度,所以后面等更新完这个系列我再慢慢补坑吧。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/124075.html

相关文章

  • 机器视觉、模式识别库汇总

    摘要:十开放模式识别项目开放模式识别项目,致力于开发出一套包含图像处理计算机视觉自然语言处理模式识别机器学习和相关领域算法的函数库。 一、开源生物特征识别库 OpenBROpenBR 是一个用来从照片中识别人脸的工具。还支持推算性别与年龄。使用方法:$ br -algorithm FaceRecognition -compare me.jpg you.jpg二、计算机视觉库 OpenCVOpenC...

    habren 评论0 收藏0
  • 叮咚~ 你有一份令人心动的offer待查收【cv君独家内推】

    摘要:准确定位问题协助研发人员解决问题从测试的角度提供优化意见。根据测试要求测试产品,并提交测试报告。   各位csdn的朋友们,同学们,大佬们大家好,好久不见,我是cv君,最近很忙,不过今天一个好朋友所在的公司,在招聘,我觉得公司和岗位特别不错,适合算法,或者嵌入式,或者前后端的朋友们,有实习...

    yanwei 评论0 收藏0
  • 你的游戏开发第0课

    摘要:我发现网上的游戏开发教程大多是从某种语言或引擎的开发细节入手,而没有一个提纲挈领式的整体介绍。碰撞检测,以及碰撞后的事件响应。网络请求数据更新同步等,判定游戏得分及胜负。这是游戏开发不可或缺的三个部分。 电子游戏是许多人喜爱甚至沉迷的事情。尤其对于程序员来说,开发游戏是不少人最初学习编程的动力。在之前,我发过一些游戏开发的教程和案例: 爆款游戏《贪吃蛇大作战》的 Python 实现 ...

    williamwen1986 评论0 收藏0
  • ApacheCN 人工智能知识树 v1.0

    摘要:贡献者飞龙版本最近总是有人问我,把这些资料看完一遍要用多长时间,如果你一本书一本书看的话,的确要用很长时间。为了方便大家,我就把每本书的章节拆开,再按照知识点合并,手动整理了这个知识树。 Special Sponsors showImg(https://segmentfault.com/img/remote/1460000018907426?w=1760&h=200); 贡献者:飞龙版...

    刘厚水 评论0 收藏0
  • Python中的十大图像处理工具

    摘要:之成为图像处理任务的最佳选择,是因为这一科学编程语言日益普及,并且其自身免费提供许多最先进的图像处理工具。该库包含基本的图像处理功能,包括点操作使用一组内置卷积内核进行过滤以及颜色空间转换。图像处理系统有时被称为图像处理的瑞士军刀。 showImg(https://segmentfault.com/img/remote/1460000019442221);编译:张秋玥、小七、蒋宝尚 本...

    yuanxin 评论0 收藏0

发表评论

0条评论

LeexMuller

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<