• Python----图像的手绘效果


    图像的数组表示

    图像是有规则的二维数据,可以用numpy 库将图像转换成数组对象 :

    1. from PIL import Image
    2. import numpy as np
    3. im=np.array(Image.open("D://np.jpg"))
    4. print(im.shape,im.dtype)

    结果:

    图像转换对应的ndarray 类型是3 维数据,如(569, 813, 3),其中,前两维表示图像的长度宽度,单位是像素,第三维表示每个像素点的RGB 值,每个RGB 值是一个单字节整数。

    像素处理
    一.convert()函数:

    PIL 库包括图像转换函数,能够改变图像单个像素的表示形式。使用convert()函数

    lmage.convert(mode) #使用不同的参数,转换图像为新的模式,返回新副本 

    1.RGB模式("RGB"):RGB模式是最常见的彩色图像模式,它使用红色、绿色和蓝色三个通道来表示图像的颜色。

    2.’L’模式表示将像素从RGB 的3 字节形式转变为单一数值形式,这个数值范围在0 到255,表示灰度色彩变化。

    3.RGBA模式("RGBA"):RGBA模式也是一种彩色图像模式,与RGB模式类似,但多了一个Alpha通道。Alpha通道表示图像的透明度,取值范围为0到255,0代表完全透明,255代表完全不透明。

    4.CMYK模式("CMYK"):CMYK模式主要用于印刷领域,使用青色、品红色、黄色和黑色四个通道来表示颜色。它与RGB模式的颜色表示方式不同。

    5.HSV模式("HSV"):HSV模式是一种基于色调(Hue)、饱和度(Saturation)和亮度(Value)的颜色表示方式。它可以更直观地表示颜色的属性。

    以"L"类型举例:

    1. from PIL import Image
    2. import numpy as np
    3. im = np.array(Image.open("D://np.jpg").convert('L'))
    4. print(im.shape, im.dtype)

    结果:

    此时,图像从彩色变为带有灰度的黑白色。转换后,图像的ndarray 类型变为二维数据,每个像素点色彩只由一个整数表示。

     

    二.numpy访问像素值

    通过对图像的数组转换,可以利用numpy 访问图像上任意像素值,例如,获取访问位于坐标(20, 300)像素的颜色值或获取图像中最大和最小的像素值。也可以采用切片方式获取指定行或列的元素值,甚至修改这些值。

    >>> im[20][300]
    28
    >>> print(int(im.min()),int(im.max()))
    0 255
    >>> print(im[10,:])
    [ 2  4  6  7  7  ... 13 12]

     

    三.图像变换

    将图像读入ndarray 数组对象后,可以通过任意数学操作来获取相应的图像变换。以灰度变换为例,分别对灰度变化后的图像进行反变换、区间变化和像素值平方处理。

    注:有些数学变换会改变图像的数据类型,如变成浮点数等,所以在重新生成PIL 图像前要先将数据类型通过numpy.uint()变换成整数

    >>>im0 = np.array(Image.open('np.jpg').convert('L'))

    >>>im1 = 255 - im0 #反变换

    >>>im2 = (100/255)*im0 + 150 #区间变换

    >>>im3 = 255*(im1/255)**2 #像素平方处理

    >>>pil_im = Image.fromarray(np.uint(im1)) #对im1,im2,im3执行

    >>>pil_im.show()

    原图:

     

    处理过后:

    四.手绘效果的实现

    - 为了实现手绘风格,即黑白轮廓描绘,首先需要读取原图像的明暗变化,即灰度值。从直观视觉感受上定义,图像灰度值显著变化的地方就是梯度,它描述了图像灰度变化的强度。

    - 通常可以使用梯度计算来提取图像轮廓,numpy 中提供了直接获取灰度图像梯度的函数gradient(),传入图像数组表示即可返回代表x 和y 各自方向上梯度变化的二维元组。

    numpy.gradient(f, *varargs, axis=None, edge_order=1)

    f,包含标量函数样本的n维数组

    varargs:标量或数组列表,可选

    edge_order:{1,2}, 可选。使用n阶精确的边界差来计算梯度。默认值:1。

    axis:沿着给定的轴计算梯度

    返回: f关于每一维的梯度

    将光源定义为三个参数:方位角vec_az、俯视角vec_el 和深度权值depth。两个角度的设定和单位向量构成了基础的柱坐标系,体现物体相对于虚拟光源的位置。

    通过np.gradient()函数计算图像梯度值作为新色彩计算的基础。为了更直观的进行计算,可以把角度对应的柱坐标转化为xyz 立体坐标系。dx、dy、dz 是像素点在施加模拟光源后在x、y、z 方向上明暗度变化的加权向量。

    A 是梯度幅值,也是梯度大小。各个方向上总梯度除以幅值得到每个像素单元的梯度值。利用每个单元的梯度值和方向加权向量合成灰度值,clip 函数用预防溢出,并归一化到0‐255 区间。最后从数组中恢复图像并保存。

    1. from PIL import Image
    2. import numpy as np
    3. im = Image.open("D://np.jpg").convert('L')
    4. a = np.asarray(im).astype('float')
    5. depth = 10.0 # 设置深度值(0-100
    6. grad = np.gradient(a) # 取图像灰度的梯度值
    7. grad_x, grad_y, *_ = grad # 分别取横纵图像梯度值
    8. grad_x = grad_x * depth / 100
    9. grad_y = grad_y * depth / 100
    10. vec_el = np.pi / 2.2 # 光源的俯视角度,弧度值
    11. vec_az = np.pi / 4 # 光源的方位角度,弧度值
    12. dx = np.cos(vec_el) * np.cos(vec_az) # 光源对x轴的影响
    13. dy = np.cos(vec_el) * np.sin(vec_az) # 光源对y轴的影响
    14. dz = np.sin(vec_el) # 光源对z轴的影响
    15. A = np.sqrt(grad_x**2 + grad_y**2 + 1.0)
    16. uni_x = grad_x / A
    17. uni_y = grad_y / A
    18. uni_z = 1.0 / A
    19. a2 = 255 * (dx * uni_x + dy * uni_y + dz * uni_z) # 光源归一化
    20. a2 = a2.clip(0, 255)
    21. im2 = Image.fromarray(a2.astype('uint8')) # 重构图像
    22. im2.save('D://npHandDraw2.jpg') # 保存图像

    原图:

    结果:

     可以进入如下链接学习:

    Python实现图像手绘效果的方法详解_python_脚本之家 (jb51.net)

    手绘图像的基本思想是利用像素之间的梯度值(而不是像素本身)重构每个像素值。为了体现光照效果,设计一个光源,建立光源对各点梯度值的影响函数,进而运算出新的像素值,从而体现边界点灰度变化,形成手绘效果。

    具体来说,为了更好体现立体感,增加一个z方向梯度值,并给x 和y 方向梯度值赋权值depth。这种坐标空间变化相当于给物体加上一个虚拟光源,根据灰度值大小模拟各部分相对于人视角的远近程度,使画面显得有“深度”。

    在利用梯度重构图像时,对应不同梯度取0‐255 之间不同的灰度值,depth 的作用就在于调节这个对应关系。depth 较小时,背景区域接近白色,画面显示轮廓描绘;depth 较大时,整体画面灰度值较深,近似于浮雕效果。

  • 相关阅读:
    WebGIS(一):高德地图API-显示地图
    [plugin:vite:css] [sass] Undefined mixin.
    E. Expenditure Reduction(用链式前向星存储下一个字符a在s中的位置)
    是真是假,AI可根据声音检测是否感染新冠 准确率达89%
    0基础,跟我一起学python--基础篇(2)
    【AI视野·今日NLP 自然语言处理论文速览 第三十九期】Fri, 22 Sep 2023
    记账不等于抠门
    MAUI Blazor 项目实战 - 从0到1轻松构建多平台应用UI
    数据结构上机1
    OkHttp原理解析(二)
  • 原文地址:https://blog.csdn.net/weixin_69884785/article/details/134446918