• python图像处理 —— 实现图像滤镜效果


    前言

    随着数字图像处理技术的不断发展,越来越多的人开始关注图像滤镜的应用。其中,使用Python的Opencv库实现图像滤镜效果成为了一种流行的技术手段。而图像滤镜是一种可以改变图像外观和色彩的技术,可以帮助我们创建独特的视觉效果。在本文中,我们将介绍如何使用Python和Opencv实现图像滤镜效果,为读者提供一个简单的入门指南。

    一、浮雕

    图像浮雕原理是通过对图像进行灰度变换,使得某些局部区域的像素值相对于周围像素值有一定的增加或减少,从而使得图像呈现出明显的浮雕感觉。具体来说,浮雕效果的实现可以通过以下步骤:

    (1)将彩色图像转换为灰度图像。
    (2)对灰度图像进行卷积操作,使用卷积核进行滤波,得到一组新的像素值。卷积核的大小可以根据需要进行调整,通常采用3x3或5x5的大小。
    (3)对于每个像素,将卷积操作后得到的像素值减去该像素在原始图像中的像素值,得到浮雕值。
    (4)根据浮雕值,将像素点的灰度值进行调整,使得局部区域的像素值相对于周围的像素值有一定的增加或减少。
    (5)将处理后的像素值重新映射到0-255的灰度值范围内,生成浮雕效果的图像。

    # ===============================图像浮雕处理===============================
    img_Fudiao = np.zeros((h, w, 3), np.uint8)
    for i in range(0, h):
        for j in range(0, w - 2):              # 减2的效果和上面一样
            grayP0 = int(gray[i, j])
            grayP1 = int(gray[i, j + 2])        # 取与前一个像素点相邻的点
            newP = grayP0 - grayP1 + 150       # 得到差值,加一个 150 常数可以增加浮雕立体感
            if newP > 255:  # 新的像素值,防止像素溢出
                newP = 255
            if newP < 0:    # 新的像素值,防止像素溢出
                newP = 0
            img_Fudiao[i, j] = newP
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    二、素描

    通过滤波、边缘检测、二值化可以将将一幅RGB图像转换成素描

    #  ===============================图像素描处理==================================
    gaussian = cv2.GaussianBlur(gray, (3, 3), 0)  # 通过高斯滤波过滤噪声
    # 通过canny算法提取图像轮过
    canny = cv2.Canny(gaussian, 50, 140)
    # 对轮廓图像进行反二进制阈值化处理
    ret, img_Sumiao = cv2.threshold(canny, 50, 255, cv2.THRESH_BINARY_INV)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    三、怀旧

    将一幅RGB图像转为怀旧图像的基本原理是将原始图像的颜色进行调整,使其呈现出类似老照片的色调。

    # ===============================图像怀旧处理===============================
    img_old = np.zeros((h, w, 3), dtype=img.dtype)
    # 通过对原始图像进行遍历,通过怀旧公式修改像素值,然后进行怀旧处理
    for i in range(h):
        for j in range(w):
            B = 0.272 * img[i, j][2] + 0.534 * img[i, j][1] + 0.131 * img[i, j][0]
            G = 0.349 * img[i, j][2] + 0.686 * img[i, j][1] + 0.168 * img[i, j][0]
            R = 0.393 * img[i, j][2] + 0.769 * img[i, j][1] + 0.189 * img[i, j][0]
            # 防止图像溢出
            if B > 255:
                B = 255
            if G > 255:
                G = 255
            if R > 255:
                    R = 255
            img_old[i, j] = [int(R), int(G), int(B)]  # B\G\R三通道都设置为怀旧值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    四、水彩画

    cv2.stylization是OpenCV库中的一种图像风格化函数,它可以用于将图像转换为带有不同风格的艺术作品。该函数的实现基于快速风格迁移(Fast Style Transfer)技术,可以在短时间内将一张普通照片转化为梵高,毕加索或印象派等多种不同风格的艺术作品。

    # ===============================图像水彩画效果处理===============================
    """
    src:需要进行风格化的原始图像。
    sigma_s:控制空间域滤波器的尺度,通常取值在0到200之间,数值越大则滤波器的尺度越大,图像的细节信息会被平滑处理。
    sigma_r:控制像素值域滤波器的尺度,通常取值在0到1之间,数值越小则滤波器的尺度越小,图像的细节信息会被保留。
    """
    img_color = cv2.stylization(img, sigma_s=60, sigma_r=0.6)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    五、水波

    添加水波特效的原理是通过对RGB图像进行仿射变换和图像处理,使图像呈现出波动效果。

    # ===============================水波特效===============================
    img_wave = np.zeros((h, w, 3), np.uint8)
    wavelength = 30                                 #定义水波特效波长
    amplitude = 20                                  #幅度
    phase = math.pi / 4                             #相位
    centreX = 0.5                                   #水波中心点X
    centreY = 0.5                                   #水波中心点Y
    radius = min(h, w) / 2
    icentreX = 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)
            # 图像水波赋值
            img_wave[i, j, :] = (1 - p) * (1 - q) * img[int(y), int(x), :] + p * (1 - q) * img[int(y), int(x), :]
            + (1 - p) * q * img[int(y), int(x), :] + p * q * img[int(y), int(x), :]
    img_wave = cv2.cvtColor(img_wave, cv2.COLOR_BGR2RGB)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    六、卡通

    将一幅RGB图像添加卡通特效的原理是将图像进行多次模糊、锐化、边缘检测等处理,使得图像呈现出光滑的颜色渐变和明显的边缘线条,从而使得图像具有卡通般的效果。

    # ===============================卡通特效===============================
    img_blur = cv2.medianBlur(gray, 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)  # 转换回彩色图像
    img_cartoon = cv2.bitwise_and(img, img_edge)          # 图像的与运算
    img_cartoon = cv2.cvtColor(img_cartoon, cv2.COLOR_BGR2RGB)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    七、流年

    添加流年特效是一种常见的图像处理操作,它可以使一幅RGB图像呈现出类似老照片的效果。实现流年特效的主要原理是通过对图像的色彩、亮度、对比度等进行调整,使得图像呈现出一种偏暗、偏黄、颗粒状的效果。

    # ===============================流年特效===============================
    img_nian = np.zeros((h, w, 3), np.uint8)
    for i in range(0, h):
        for j in range(0, w):
            B = math.sqrt(img[i, j][0]) *14       # B通道的数值开平方乘以参数14
            G = img[i, j][1]
            R = img[i, j][2]
            if B > 255:
                B = 255
            img_nian[i, j] = np.uint8((B, G, R))
    img_nian = cv2.cvtColor(img_nian, cv2.COLOR_BGR2RGB)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    八、美颜

    美颜本质上就是双边滤波,函数 cv2.bilateralFilter() 能在保持边界清晰的情况下有效的去除噪音,就是人脸上的痘痘,所以有美颜效果

    # ===============================美颜===============================
    img_bit = cv2.bilateralFilter(src=img, d=0, sigmaColor=30, sigmaSpace=15)
    img_bit = cv2.cvtColor(img_bit, cv2.COLOR_BGR2RGB)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    完整代码

    # -*- coding:utf-8 -*-
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    import math
    plt.rcParams['font.family'] = 'SimHei'
    img = cv2.imread('bin.png')
    img_Org = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    h, w = img.shape[:2]
    # ===============================图像浮雕处理===============================
    img_Fudiao = np.zeros((h, w, 3), np.uint8)
    for i in range(0, h):
        for j in range(0, w - 2):              # 减2的效果和上面一样
            grayP0 = int(gray[i, j])
            grayP1 = int(gray[i, j + 2])        # 取与前一个像素点相邻的点
            newP = grayP0 - grayP1 + 150       # 得到差值,加一个 150 常数可以增加浮雕立体感
            if newP > 255:  # 新的像素值,防止像素溢出
                newP = 255
            if newP < 0:    # 新的像素值,防止像素溢出
                newP = 0
            img_Fudiao[i, j] = newP
    
    #  ===============================图像素描处理==================================
    gaussian = cv2.GaussianBlur(gray, (3, 3), 0)  # 通过高斯滤波过滤噪声
    # 通过canny算法提取图像轮过
    canny = cv2.Canny(gaussian, 50, 140)
    # 对轮廓图像进行反二进制阈值化处理
    ret, img_Sumiao = cv2.threshold(canny, 50, 255, cv2.THRESH_BINARY_INV)
    
    # ===============================图像怀旧处理===============================
    img_old = np.zeros((h, w, 3), dtype=img.dtype)
    # 通过对原始图像进行遍历,通过怀旧公式修改像素值,然后进行怀旧处理
    for i in range(h):
        for j in range(w):
            # B = 0.131 * img[i, j, 0] + 0.534 * img[i, j, 1] + 0.272 * img[i, j, 2]
            # G = 0.168 * img[i, j, 0] + 0.686 * img[i, j, 1] + 0.349 * img[i, j, 2]
            # R = 0.189 * img[i, j, 0] + 0.769 * img[i, j, 1] + 0.393 * img[i, j, 2]
            B = 0.272 * img[i, j][2] + 0.534 * img[i, j][1] + 0.131 * img[i, j][0]
            G = 0.349 * img[i, j][2] + 0.686 * img[i, j][1] + 0.168 * img[i, j][0]
            R = 0.393 * img[i, j][2] + 0.769 * img[i, j][1] + 0.189 * img[i, j][0]
            # 防止图像溢出
            if B > 255:
                B = 255
            if G > 255:
                G = 255
            if R > 255:
                    R = 255
            img_old[i, j] = [int(R), int(G), int(B)]  # B\G\R三通道都设置为怀旧值
    
    # ===============================图像水彩画效果处理===============================
    """
    src:需要进行风格化的原始图像。
    sigma_s:控制空间域滤波器的尺度,通常取值在0到200之间,数值越大则滤波器的尺度越大,图像的细节信息会被平滑处理。
    sigma_r:控制像素值域滤波器的尺度,通常取值在0到1之间,数值越小则滤波器的尺度越小,图像的细节信息会被保留。
    """
    img_color = cv2.stylization(img, sigma_s=60, sigma_r=0.6)
    img_color = cv2.cvtColor(img_color, cv2.COLOR_BGR2RGB)
    
    # ===============================水波特效===============================
    img_wave = np.zeros((h, w, 3), np.uint8)
    wavelength = 30                                 #定义水波特效波长
    amplitude = 20                                  #幅度
    phase = math.pi / 4                             #相位
    centreX = 0.5                                   #水波中心点X
    centreY = 0.5                                   #水波中心点Y
    radius = min(h, w) / 2
    icentreX = 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)
            # 图像水波赋值
            img_wave[i, j, :] = (1 - p) * (1 - q) * img[int(y), int(x), :] + p * (1 - q) * img[int(y), int(x), :]
            + (1 - p) * q * img[int(y), int(x), :] + p * q * img[int(y), int(x), :]
    img_wave = cv2.cvtColor(img_wave, cv2.COLOR_BGR2RGB)
    
    # ===============================卡通特效===============================
    img_blur = cv2.medianBlur(gray, 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)  # 转换回彩色图像
    img_cartoon = cv2.bitwise_and(img, img_edge)          # 图像的与运算
    img_cartoon = cv2.cvtColor(img_cartoon, cv2.COLOR_BGR2RGB)
    
    # ===============================流年特效===============================
    img_nian = np.zeros((h, w, 3), np.uint8)
    for i in range(0, h):
        for j in range(0, w):
            B = math.sqrt(img[i, j][0]) *14       # B通道的数值开平方乘以参数14
            G = img[i, j][1]
            R = img[i, j][2]
            if B > 255:
                B = 255
            img_nian[i, j] = np.uint8((B, G, R))
    img_nian = cv2.cvtColor(img_nian, cv2.COLOR_BGR2RGB)
    # ===============================美颜===============================
    img_bit = cv2.bilateralFilter(src=img, d=0, sigmaColor=30, sigmaSpace=15)
    img_bit = cv2.cvtColor(img_bit, cv2.COLOR_BGR2RGB)
    
    plt.figure(figsize=(16,9))
    plt.subplot(331),plt.imshow(img_Org), plt.xticks([]), plt.yticks([]), plt.title('原图')
    plt.subplot(332),plt.imshow(img_Fudiao, cmap='gray'), plt.xticks([]), plt.yticks([]), plt.title('浮雕')
    plt.subplot(333),plt.imshow(img_Sumiao, cmap='gray'), plt.xticks([]), plt.yticks([]), plt.title('素描')
    plt.subplot(334),plt.imshow(img_old), plt.xticks([]), plt.yticks([]), plt.title('怀旧')
    plt.subplot(335),plt.imshow(img_color), plt.xticks([]), plt.yticks([]), plt.title('水彩')
    plt.subplot(336),plt.imshow(img_wave), plt.xticks([]), plt.yticks([]), plt.title('水波')
    plt.subplot(337),plt.imshow(img_cartoon), plt.xticks([]), plt.yticks([]), plt.title('卡通')
    plt.subplot(338),plt.imshow(img_nian), plt.xticks([]), plt.yticks([]), plt.title('流年')
    plt.subplot(339),plt.imshow(img_bit), plt.xticks([]), plt.yticks([]), plt.title('美颜')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
  • 相关阅读:
    c++视觉检测-----角点检测
    4. 堪比JMeter的.Net压测工具 - Crank 进阶篇 - 认识wrk、wrk2
    火炬之光无限-萌新记录
    第七章 设计zrlog项目的测试用例(7.1章节)
    ES6 入门教程 17 Promise 对象 17.11 Promise.reject() & 17.12 应用 & 17.13 Promise.try()
    基于Django+Vue.js+Scrapy+Sqlite3电影数据可视化(柱状图、折线图、饼图、词云图)设计
    猿创征文|MySQL基本查询语句的应用(有实例与代码)
    hbase建表时设置预分区
    德国大学新突破:实现数千原子量子纠缠
    【算法】石子合并(区间dp)
  • 原文地址:https://blog.csdn.net/weixin_42207434/article/details/134252468