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

图像的数组表示

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

from PIL import Image
import numpy as np
im=np.array(Image.open("D://np.jpg"))
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"类型举例:

from PIL import Image
import numpy as np
im = np.array(Image.open("D://np.jpg").convert('L'))
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 区间。最后从数组中恢复图像并保存。

from PIL import Image
import numpy as npim = Image.open("D://np.jpg").convert('L')
a = np.asarray(im).astype('float')depth = 10.0  # 设置深度值(0-100)
grad = np.gradient(a)  # 取图像灰度的梯度值
grad_x, grad_y, *_ = grad  # 分别取横纵图像梯度值
grad_x = grad_x * depth / 100
grad_y = grad_y * depth / 100vec_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轴的影响A = np.sqrt(grad_x**2 + grad_y**2 + 1.0)
uni_x = grad_x / A
uni_y = grad_y / A
uni_z = 1.0 / Aa2 = 255 * (dx * uni_x + dy * uni_y + dz * uni_z)  # 光源归一化
a2 = a2.clip(0, 255)im2 = Image.fromarray(a2.astype('uint8'))  # 重构图像
im2.save('D://npHandDraw2.jpg')  # 保存图像

原图:

结果:

 可以进入如下链接学习:

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

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

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

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

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

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

相关文章

什么是CDN?什么是安全加速CDN?有什么优势?

安全加速CDN(Content Delivery Network)是一种网络架构,它通过在全球范围内部署服务器并缓存静态和动态内容来提供更快的Web页面加载和更好的用户体验。安全加速CDN可以保护网站免受DDoS攻击、恶意软件和其他安全威胁,从而提高网站的可用性和稳定性。它通…

IDEA 快捷键汇总

目录 1、altinsert 2、ctrl/ 3、altenter 4、alt回车 5、ctrlD 6、ctrlaltL 7、ctrl点击 8、alt左键向下拉 9、ctrlaltv 10、ctrlaltwint 1、altinsert 快速创建代码,可以快速创建类中get set tostring等方法 2、ctrl/ 单行注释 3、altenter…

CTF-PWN-堆- 【off-by-one】

文章目录 堆的off-by-one利用思路Asis CTF 2016 b00ks libc 2.31IDA源码main输入名字creat函数dele函数edit函数print函数reeditor name函数 思路exp思路 堆的off-by-one off-by-one指的是单字节缓冲区溢出(off-by-one 是可以基于各种缓冲区的,比如栈、…

二分查找和二分答案

【深基13.例1】查找 题目描述 输入 n n n 个不超过 1 0 9 10^9 109 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a 1 , a 2 , … , a n a_1,a_2,\dots,a_{n} a1​,a2​,…,an​,然后进行 m m m 次询问。对于每次询问&#x…

【FPGA】Verilog:升降计数器 | 波纹计数器 | 约翰逊计数器 | 实现 4-bit 升降计数器的 UP/DOWN

目录 Ⅰ. 理论部分 0x00 升降计数器(UP DOWN Counter) 0x01 波纹计数器(Ripple Counter) 0x02 约翰逊计数器(Johnson Counter) Ⅱ. 实践部分 0x00 实现:升降计数器(4-bit&…

CTFhub-RCE-过滤目录分隔符 /

根据源代码信息可知&#xff0c;过滤掉了/ <?php $res FALSE; if (isset($_GET[ip]) && $_GET[ip]) { $ip $_GET[ip]; $m []; if (!preg_match_all("/\//", $ip, $m)) { $cmd "ping -c 4 {$ip}"; exec($cmd,…

HTTPS加密为什么能保证网络安全?

随着互联网的普及和发展&#xff0c;网络安全问题日益严重。为了保护用户的隐私和数据安全&#xff0c;许多网站都采用了HTTPS加密技术。那么&#xff0c;HTTPS加密为什么可以保证网络安全呢&#xff1f; 原因是HTTP协议采用的是数据明文传输方式。用户从客户端浏览器提交数据…

The import xxx.xxx.xxxx is never used

CTRL SHIFT O 就完成了&#xff0c;懒人&#xff0c;代码没洁癖啊&#xff0c;几千上万的代码没用的。

Theory behind GAN

假如要生成一些人脸图&#xff0c;实际上就是想要找到一个分布&#xff0c;从这个分布内sample出来的图片像是人脸&#xff0c;分布之外生成的就不像人脸。而GAN要做的就是找到这个distribution。 在GAN之前用的是Maximum Likelihood Estimation。 Maximum Likelihood Estimat…

List is a raw type. References to generic type List<E> should be parameterized

List is a raw type. References to generic type List<E> should be parameterized 都是代码习惯问题懒

如何用继承和多态来打印个人信息

1 问题 在python中的数据类型中&#xff0c;我们常常运用继承和多态。合理地使用继承和多态可以增强程序的可扩展性使代码更简洁。那么如何使用继承和多态来打印个人信息&#xff1f; 2 方法 打印基本信息添加子类&#xff0c;再定义一个class&#xff0c;可以直接从Person类继…