Python 数据分析与展示笔记2 -- 图像手绘效果

Python 数据分析与展示笔记2 – 图像手绘效果


Python 数据分析与展示系列笔记是笔者学习、实践Python 数据分析与展示的相关笔记

课程链接: Python 数据分析与展示

参考文档:
Numpy 官方文档(英文)
Numpy 官方文档(中文)
PIL 官方文档


一、PIL 库


1、安装与导入

# 安装 PIL  库
pip install pillow

# 导入 PIL  库
import PIL

# 导入 PIL 库的 Image模块/类(用读取显示图像)
from PIL import Image

2、简单使用

# 打开图像
Image.open('图片的路径')

# 转为灰度图像
.convert('L')

# 保存图像
.save('保存路径')

二、图像手绘效果


1、总体思路

  • 图像中物体的边缘用黑色画出,而大片相同的区域用白色画出
  • 图像梯度可以求出物体的边缘,边缘越明显,梯度越大
  • 为了用黑色表色边缘,图片的像素值应该与梯度值成反比关系,而代码中的核心思想也是为了求得这个关系

2、几点理解

  • depth参数:设置 x,y 梯度占总的梯度的比例,使梯度值缩小,因为我们把z向的梯度设成了1,如果不压缩x,y向梯度那么这个1就起不到什么作用
  • z 方向的梯度(即梯度归一化中的1):为了表示像素值与梯度的反比关系,当像素的 x,y 向梯度值都很小时,在归一化时uni_z值就会区于1从而得到趋于255的像素值
  • 图像梯度归一化:主要为了得到 uni_z 的值
  • 光源设置:设置光源的角度只是为了得到 dx,dy,dz 三个可调系数而已,个人认为跟光源一点关系都没有,反而不好理解
  • dx,dy,dz:uni_x,uni_y,uni_z的系数,更深入的说其实目的是把 dz 设的很大,dx,dy很小,完全可以不要dx,dy 把dz设为1,效果几乎一样

3、代码

from PIL import Image
import numpy as np


def hand_draw_image(img_path, show=True, save_path=None):
    """
    把彩色图片变为手绘风格的灰度图片
    :param img_path: 原图片的路径
    :param show: 是否要显示手绘图片
    :param save_path: 是否要保存手绘图片
    :return:
    """
    # 打开图片转为灰度图,并转换为 float 类型的 ndarray
    img = np.asarray(Image.open(img_path).convert('L')).astype('float')

    # 求图像的梯度
    depth = 10
    grad_x, grad_y = np.gradient(img)
    grad_x = grad_x * depth / 100.
    grad_y = grad_y * depth / 100.
    # 归一化图像的梯度
    img_grad = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1)
    uni_x = grad_x / img_grad
    uni_y = grad_y / img_grad
    uni_z = 1 / img_grad

    # 光源对图像明暗的影响
    vec_el = np.pi / 2.2    # 光源的俯视角度,弧度值
    vec_az = np.pi / 4.     # 光源的方位角度,弧度值
    dx = np.cos(vec_el) * np.cos(vec_az)    # 光源对 x 轴的影响(投影)
    dy = np.cos(vec_el) * np.sin(vec_az)    # 光源对 y 轴的影响(投影)
    dz = np.sin(vec_el)     # 光源对 z 轴的影响(投影)
    img_res = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)    # 光源归一化
    img_res = img_res.clip(0, 255)      # 裁剪0-255外的像素值
    im = Image.fromarray(img_res.astype(np.uint8))     # 重构图像

    if show:
        im.show()

    if save_path:
        im.save(save_path)


if __name__ == '__main__':
    print('running hand_painted:')
    hand_draw_image('图片路径')

原图:
在这里插入图片描述
效果:
在这里插入图片描述


GOOD LUCK!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值