使用Python实现图像的手绘风格效果

使用Python实现图像的手绘风格效果

  • 一、引言
  • 二、代码详细解释与示例
  • 三、完整框架流程
  • 四、运行
  • 五、结论
  • 附:完整代码

一、引言

在数字图像处理领域,模拟手绘风格是一项有趣且具有挑战性的任务。手绘风格图像通常具有独特的纹理和深浅变化,给人一种亲切和艺术感。本文旨在通过计算图像的梯度并模拟光照效果,实现一种简单而有效的手绘风格图像生成方法。

二、代码详细解释与示例

  1. 导入必要的库

    from PIL import Image
    import numpy as np
    import os
    
    • PIL(Pillow):用于图像的打开、转换和保存。
    • NumPy:用于数组和矩阵操作,以及数学计算。
    • os:用于文件和目录操作。
  2. 计算图像的阴影效果

     def calculate_shading(img, depth, vec_el, vec_az):# 计算图像在x和y方向上的梯度grad = np.gradient(img)grad_x, grad_y = grad  # grad_x是x方向的梯度,grad_y是y方向的梯度# 根据深度因子调整梯度大小grad_x *= depth / 100.grad_y *= depth / 100.# 计算梯度的模(大小),并添加一个小常数以避免除以零A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1e-7)  # 1e-7是为了数值稳定性# 计算单位梯度向量(在x, y, z方向上的分量)# 这里我们假设z方向上的分量为1/A,因为它代表图像表面的“法线”方向uni_x = grad_x / Auni_y = grad_y / Auni_z = 1. / A# 计算光源方向向量(在x, y, z方向上的分量)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方向(垂直于图像平面)的影响# 计算光源方向与单位梯度向量的点积,模拟光照效果# 点积越大,表示该点越亮;点积越小(越接近-1),表示该点越暗(但由于我们取绝对值并映射到0-255,所以实际上表现为更深的阴影)# 但由于我们是模拟手绘风格,所以直接乘以255并裁剪到0-255范围内b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)# 裁剪结果到0-255范围内,确保图像数据的有效性b = b.clip(0, 255)return b
    
    • 函数calculate_shading接收一个灰度图像数组img、深淡程度depth、光源的俯视角度vec_el和方位角度vec_az作为参数。
    • 使用np.gradient计算图像在x和y方向上的梯度,得到grad_xgrad_y
    • 根据depth因子调整梯度大小,然后计算梯度的模A,并添加一个小常数以避免除以零的错误。
    • 计算单位梯度向量uni_xuni_yuni_z(假设z方向上的分量为1/A)。
    • 计算光源方向向量dxdydz
    • 通过计算光源方向与单位梯度向量的点积,模拟光照效果,得到带有阴影效果的图像数组b
    • 使用clip函数将结果裁剪到0-255范围内,确保图像数据的有效性。

    示例
    假设我们有一个灰度图像img_array,我们可以调用这个函数来计算阴影效果:

    shaded_img = calculate_shading(img_array, depth=50.0, vec_el=np.pi / 2.2, vec_az=np.pi / 4.0)
    
  3. 将输入图片处理成手绘风格并保存

     # 将输入图片处理成手绘风格并保存为新文件def img_handpainted(input_img_path, depth=20.0, vec_el=np.pi / 2.2, vec_az=np.pi / 4.0):"""将指定路径的灰度图像转换成手绘风格的图像并保存。参数:input_img_path (str): 输入图片的路径。depth (float): 深淡程度控制因子,默认为20.0。vec_el (float): 光源的俯视角度(俯仰角),默认为np.pi/2.2。vec_az (float): 光源的方位角度(方位角),默认为np.pi/4.0。"""# 检查输入文件是否存在if not os.path.exists(input_img_path):raise FileNotFoundError(f"The file {input_img_path} does not exist.")# 打开并转换图像为灰度图,然后转换为NumPy数组img = np.array(Image.open(input_img_path).convert('L')).astype('float')# 从文件路径中提取图像名称(不包括扩展名)img_name = os.path.basename(input_img_path)[:-4]# 计算阴影效果shaded_img = calculate_shading(img, depth, vec_el, vec_az)# 将结果转换回图像格式并保存img_handwrite = Image.fromarray(shaded_img.astype('uint8'))outname = './' + img_name + '_handpainted.jpg'img_handwrite.save(outname)print(f"Saved image as {outname}")
    • 函数img_handpainted接收输入图片的路径input_img_path、深淡程度depth、光源的俯视角度vec_el和方位角度vec_az作为参数。
    • 检查输入文件是否存在,如果不存在则抛出FileNotFoundError异常。
    • 打开并转换图像为灰度图,然后转换为NumPy数组。
    • 从文件路径中提取图像名称(不包括扩展名)。
    • 调用calculate_shading函数计算阴影效果。
    • 将结果转换回图像格式,并保存为新的JPEG文件。
    • 打印保存的文件名。

    示例
    假设我们有一个灰度图像文件example.jpg,我们可以调用这个函数来生成手绘风格的图像:

    img_handpainted('./example.jpg', depth=30.0)
    

三、完整框架流程

  1. 准备阶段

    • 安装必要的Python库:Pillow(PIL)和NumPy。
    • 准备一张灰度图像作为输入。
  2. 计算阴影效果

    • 读取输入图像并转换为灰度图。
    • 将灰度图转换为NumPy数组,以便进行数学计算。
    • 调用calculate_shading函数,根据光源方向和深淡程度计算阴影效果。
  3. 生成手绘风格图像

    • 将计算得到的阴影效果应用到原始灰度图像上。
    • 将结果转换回图像格式。
    • 保存为新的JPEG文件。
  4. 运行脚本

    • 执行脚本,查看生成的手绘风格图像。

四、运行

原图片:
请添加图片描述
执行代码后生成的图片:
请添加图片描述

五、结论

通过本文介绍的方法,我们可以轻松地将普通灰度图像转换成具有手绘风格效果的图像。这种方法不仅简单易行,而且生成的图像具有独特的手绘质感,非常适合用于艺术创作和图像处理领域。希望本文能够帮助读者理解和实现这一有趣的技术。

附:完整代码

# -*- coding: utf-8 -*-
# @Time : 2021/7/4 22:30
# @Author : Leuanghing Chen
# @Blog : https://blog.csdn.net/weixin_46153372?spm=1010.2135.3001.5421
# @File : 手绘效果图.py
# @Software : PyCharmfrom PIL import Image
import numpy as np
import os# 计算图像的阴影效果,模拟手绘风格的深浅变化
def calculate_shading(img, depth, vec_el, vec_az):"""计算并返回带有阴影效果的灰度图像。参数:img (numpy.ndarray): 输入的灰度图像,应该是一个二维数组。depth (float): 深淡程度控制因子,范围0-100。值越大,阴影效果越明显。vec_el (float): 光源的俯视角度(俯仰角),以弧度为单位。控制光源相对于图像平面的垂直角度。vec_az (float): 光源的方位角度(方位角),以弧度为单位。控制光源在图像平面上的水平位置。返回:numpy.ndarray: 带有阴影效果的灰度图像,与输入图像尺寸相同。"""# 计算图像在x和y方向上的梯度grad = np.gradient(img)grad_x, grad_y = grad  # grad_x是x方向的梯度,grad_y是y方向的梯度# 根据深度因子调整梯度大小grad_x *= depth / 100.grad_y *= depth / 100.# 计算梯度的模(大小),并添加一个小常数以避免除以零A = np.sqrt(grad_x ** 2 + grad_y ** 2 + 1e-7)  # 1e-7是为了数值稳定性# 计算单位梯度向量(在x, y, z方向上的分量)# 这里我们假设z方向上的分量为1/A,因为它代表图像表面的“法线”方向uni_x = grad_x / Auni_y = grad_y / Auni_z = 1. / A# 计算光源方向向量(在x, y, z方向上的分量)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方向(垂直于图像平面)的影响# 计算光源方向与单位梯度向量的点积,模拟光照效果# 点积越大,表示该点越亮;点积越小(越接近-1),表示该点越暗(但由于我们取绝对值并映射到0-255,所以实际上表现为更深的阴影)# 但由于我们是模拟手绘风格,所以直接乘以255并裁剪到0-255范围内b = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)# 裁剪结果到0-255范围内,确保图像数据的有效性b = b.clip(0, 255)return b# 将输入图片处理成手绘风格并保存为新文件
def img_handpainted(input_img_path, depth=20.0, vec_el=np.pi / 2.2, vec_az=np.pi / 4.0):"""将指定路径的灰度图像转换成手绘风格的图像并保存。参数:input_img_path (str): 输入图片的路径。depth (float): 深淡程度控制因子,默认为20.0。vec_el (float): 光源的俯视角度(俯仰角),默认为np.pi/2.2。vec_az (float): 光源的方位角度(方位角),默认为np.pi/4.0。"""# 检查输入文件是否存在if not os.path.exists(input_img_path):raise FileNotFoundError(f"The file {input_img_path} does not exist.")# 打开并转换图像为灰度图,然后转换为NumPy数组img = np.array(Image.open(input_img_path).convert('L')).astype('float')# 从文件路径中提取图像名称(不包括扩展名)img_name = os.path.basename(input_img_path)[:-4]# 计算阴影效果shaded_img = calculate_shading(img, depth, vec_el, vec_az)# 将结果转换回图像格式并保存img_handwrite = Image.fromarray(shaded_img.astype('uint8'))outname = './' + img_name + '_handpainted.jpg'img_handwrite.save(outname)print(f"Saved image as {outname}")# 当脚本作为主程序运行时,调用img_handpainted函数
if __name__ == '__main__':img_handpainted('./1.jpg')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58843.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle Select语句

SELECT语句使用方法 在Oracle中,表是由列和行组成。 例如,示例数据库中的customers表具有以下列:customer_id,name,address,website和credit_limit。customers表中这些列中也有对应的数据。 要从表的一个或…

w~大模型~合集21

我自己的原文哦~ https://blog.51cto.com/whaosoft/12459590 #大模型~微调~用带反馈的自训练 面对当前微调大模型主要依赖人类生成数据的普遍做法,谷歌 DeepMind 探索出了一种减少这种依赖的更高效方法。大模型微调非得依赖人类数据吗?用带反馈的自训…

ctfshow(316,317,318)--XSS漏洞--反射性XSS

反射型XSS相关知识 Web316 进入界面: 审计 显示是关于反射性XSS的题目。 思路 首先想到利用XSS平台解题,看其他师傅的wp提示flag是在cookie中。 当前页面的cookie是flagyou%20are%20not%20admin%20no%20flag。 但是这里我使用XSS平台,…

【案例】Excel使用宏来批量插入图片

一、场景介绍 我有一个excel文件,需要通过一列的文件名称,按照规则给批量上传图片附件。 原始文件: 成功后文件: 二、实现方法 1. 使用【wps】工具打开Excel文件,将其保存为启用宏的文件。 2.找到编辑宏的【VB编辑器…

ENSP OSPF和BGP引入

路由协议分为:内部网关协议和外部网关协议。内部网关协议用于自治系统内部的路由,包括:RIP和OSPF。外部网关协议用于自治系统之间的路由,包括BGP。内部网关协议和外部网关协议配合来共同完成网络的路由。 BGP:边界网关路由协议(b…

Linux磁盘存储

磁盘存储 设备文件 设备文件是类Unix操作系统(包括Linux)中一种特殊的文件类型,它代表了设备接口,使得用户空间的程序可以通过标准的文件操作来访问和控制硬件设备。设备文件为周边设备提供了简单的接口,如打印机、硬…

阿里云ECS服务器使用限制及不允许做的事情

阿里云ECS(Elastic Compute Service)是一种高性能的弹性计算服务,允许用户在云端创建和管理虚拟服务器。尽管ECS提供了强大的功能,但在使用过程中,阿里云有一些限制和不允许的行为。以下是一些主要的使用限制和禁止行为…

【手撕排序4】计数排序+快速排序(非递归)

> 🍃 本系列包括常见的各种排序算法,如果感兴趣,欢迎订阅🚩 > 🎊个人主页:[小编的个人主页])小编的个人主页 > 🎀 🎉欢迎大家点赞👍收藏⭐文章 > ✌️ 🤞…

FPGA实现以太网(一)、以太网基础知识

系列文章目录 FPGA实现以太网(二)、初始化和配置PHY芯片 文章目录 系列文章目录一、以太网简介二、OSI七层模型三、TCP/IP五层模型四、MAC-PHY接口五、MAC帧格式六、IP帧格式6.1 IP首部校验和计算6.2 IP首部校验和校验 七、UDP帧格式7.1 UDP头部校验和…

Linux平台C99与C++11获取系统时间

源码: #include <iostream> #include <chrono> #include <ctime> #include <thread>using namespace std; int main() {cout << "===使用C99方式获取系统时间===" << endl;time_t now = time(nullptr);struct tm *tm_c99 = lo…

QT版发送邮件程序

简单的TCP邮箱程序 **教学与实践目的&#xff1a;**学会网络邮件发送的程序设计技术。 1.SMTP协议 邮件传输协议包括 SMTP&#xff08;简单邮件传输协议&#xff0c;RFC821&#xff09;及其扩充协议 MIME&#xff1b; 邮件接收协议包括 POP3 和功能更强大的 IMAP 协议。 服务…

【学习记录】使用CARLA录制双目摄像头SLAM数据

一、数据录制 数据录制的部分参考了网上的部分代码&#xff0c;代码本身并不复杂&#xff0c;基本都是简单的CARLA语法&#xff0c;关键的一点在于&#xff0c;CARLA内部本身并没有预设的双目摄像头&#xff0c;需要我们添加两个朝向相同的摄像头来组成双目系统&#xff0c;这…

第02章 CentOS基本操作

2.文件基本操作【文件操作&#xff08;一&#xff09;】 目标 理解Linux下路径的表示方法能够使用命令(mkdir和touch)在指定位置创建目录和文件能够使用命令(rm)删除指定的目录和文件能够使用命令(ls)列出目录里的文件能够使用命令(cat,head,tail,less,more)查看文件内容理解标…

【数字图像处理+MATLAB】解决 imshow 函数图像显示亮度异常问题:自动调整亮度范围使图像能正确显示

问题描述 在MATLAB中&#xff0c;使用imshow函数进行图像显示时&#xff0c;图片亮度显示异常。 imshow(im_avg);执行上述代码后&#xff0c;得到的图片亮度异常&#xff0c;如下图所示&#xff1a; 原因分析 在MATLAB中&#xff0c;imshow函数的亮度显示规则是基于图像数据…

探索 Python 的新边疆:sh 库的革命性功能

文章目录 **探索 Python 的新边疆&#xff1a;sh 库的革命性功能**第一部分&#xff1a;背景介绍第二部分&#xff1a;sh 库是什么&#xff1f;第三部分&#xff1a;如何安装 sh 库&#xff1f;第四部分&#xff1a;简单库函数使用方法1. 执行 ls 命令2. 使用 grep 搜索文件内容…

外贸管理利器7选,助力高效办公

推荐7款外贸管理软件&#xff0c;包括ZohoBooks、ZohoCRM、富通天下等&#xff0c;各具特色&#xff0c;满足外贸企业不同需求&#xff0c;提高管理效率&#xff0c;助力企业全球化竞争。、 一、Zoho Books Zoho Books是一款外贸财务管理软件&#xff0c;不仅为用户提供了一个…

SQL中的内连接(inner join)、外连接(left|right join、full join)以及on关键字中涉及分区筛选、null解释

一、简介 本篇幅主要介绍了&#xff1a; SQL中内连接&#xff08;inner join&#xff09;、外连接&#xff08;left join、right join、full join&#xff09;的机制;连接关键字on上涉及表分区筛选的物理执行及引擎优化&#xff1b;null在表关联时的情况与执行&#xff1b; …

机器学习(一)——基本概念、模型的评估与选择

目录 1 关于2 概念2.1 基础概念2.2 学习过程2.3 预测与评估2.4 标记与分类2.4.1 标记2.4.2 分类 2.5 回归分析2.6 聚类分析2.7 学习类型2.8 泛化能力2.9 统计学概念 3 模型评估与选择3.1 经验误差与过拟合3.2 评估方法3.2.1 留出法3.2.2 交叉验证法3.2.3 自助法3.2.4 调参与最终…

ssm060基于SSM的高校共享单车管理系统的设计与实现+vue(论文+源码)_kaic

设计题目&#xff1a;高校共享单车管理系统的设计与实现 摘 要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0…

聚观早报 | 比亚迪腾势D9登陆泰国;苹果 iOS 18.2 将发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 11月5日消息 比亚迪腾势D9登陆泰国 苹果 iOS 18.2 将发布 真我GT7 Pro防尘防水细节 小米15 Ultra最快明年登场 …