Pillow图像处理(PIL.Image类的详细使用)
文章目录
- Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序
- Python图像处理库(PIL、Pillow、Scikit-image、Opencv)
- Pillow 官方文档(超详细,超推荐)
- 一、PIL库与Pillow库的区别
- 二、Pillow库
- (1)Pillow库特点
- (2)Pillow库安装
- 三、Pillow的Image对象(PIL.Image)
- (1)打开图像:Image.open() —— 可以加载任意图像格式
- (2)自建图像:Image.new()
- (3)查看Image对象的属性 —— width + height + size + format + randonly + info + mode
- (4)保存图像:Image.save() —— 保存的同时可以改变格式
- (5)图像模式转换:im.convert() —— 不同格式之间的转换
- (6)图像缩放:im.resize() —— 整体缩放 + 局部放大(指定区域)
- (7)图像的缩略图:im.thumbnail() —— 只能在原图上修改,返回None
- (8)图像通道分离:im.split() —— r/g/b三通道
- (9)图像通道合并:Image.merge() —— 颜色通道合并 + 图像融合(权重值五五开)
- (10)混合图像:Image.blend() —— 将两张图像叠加在一起,并可以选择其中一张图像的透明度,取值范围[0, 1]。
- <11> 图像裁剪:im.crop() —— 获取指定区域
- <12> 图像拷贝:im.copy() —— 深拷贝
- <13> 图像粘贴:im.paste() —— 可以将两张图叠加在一起
- <14> 图像几何变换(翻转):im.transpose()
- <15> 图像几何变换(旋转):im.rotate()
- <16> 图像几何变换(形状变换):im.transform()
- <17> 图像降噪处理:ImageFilter —— 集成多种滤波器(17种)
- <18> 图像像素增强:ImageEnhance —— 对选择的属性增强N倍(颜色平衡、对比度、亮度、锐度)
- <19> 绘制图形:ImageDraw.Draw() —— 添加文字 + 绘制点、直线、矩形、多边形、椭圆、圆弧、弦、饼图
- (20)获取 RGB 值:ImageColor.getrgb()
- (21)获取颜色值:ImageColor.getcolor()
- (22)ndarray数组与图像之间的相互转换:np.array + Image.fromarray
- (23)读取序列图像: seek() + tell() 、ImageSequence()
- 应用一:批量修改图像尺寸
- 应用二:图像添加水印:ImageDraw + ImageFont
- 应用三:生成GIF动态图
Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序
需注意:Pillow加载图像后的尺寸是二维,图形化是三维,但无法打印三维尺寸。
详细区别:
Opencv
:uint8的ndarray数据,通道顺序[h, w, c]
,颜色通道BGR
。
- 导入模块:
import cv2
(1)cv2.imread()
(2)cv2.imshow()
(3)cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
Matplotlib(plt)
:uint8的ndarray数据,通道顺序[h, w, c]
,颜色通道RGB
。
- 导入模块:
import matplotlib.pyplot as plt
(1)plt.imread()
(2)plt.imshow()
Pillow(PIL)
:uint8的ndarray数据,通道顺序[h, w, c]
,颜色通道RGB
。
- 导入模块:
import PIL
(1)PIL.Image.open()
(2)PIL.Image.show()
Pythorch
:tensor数据,通道顺序[n, c, h, w]
,颜色通道RGB
。
- 导入模块:
import torchvision
(1)torchvision.transforms.ToTensor()
(2)torchvision.transforms.ToPILImage()
Python图像处理库(PIL、Pillow、Scikit-image、Opencv)
图像(指数字图像)由许多像素点组成,像素是组成图像的基本单位,而每一个像素点又可以使用不同的颜色,最终呈现出了绚丽多彩的图像。
(1)PIL是一个免费开源的Python图像处理库。而Pillow是基于PIL库的一个派生分支,它在 PIL 库的基础上增加了许多新的特性。
- 特点:PIL、Pillow只提供最基础的数字图像处理**,功能有限。
(2)Scikit-image:基于 scipy 科学计算的python图像处理软件包,由 scipy 社区开发和维护,以数组的形式对图像进行处理。
- 特点:轻量,易安装,易使用,轻量级
(3)Opencv:由 C/C++ 语言编写的图像处理库,同时提供Python、Ruby、MATLAB等语言的接口。图像处理界中的绝对大佬
- 特点:环境难搭建,重量型,集成功能较多
Pillow 官方文档(超详细,超推荐)
Pillow 官方文档:https://pillow.readthedocs.io/en/stable/index.html
一、PIL库与Pillow库的区别
PIL(Python Imaging Library)是一个免费开源的Python图像处理库,其功能丰富,API 简洁易用,一度深受好评。
发展历程
- 2011年,PIL官网宣布不再更新PIL,其最新版本仅支持 Python 2.7,而不支持 Python3。
- 于是,一群 Python 社区的志愿者(主要贡献者:Alex Clark 和 Contributors)在 PIL 库的基础上,开发了一个支持 Python3 版本的图像处理库,它就是 Pillow。目前,已成为Linux发行版中原始PIL的替代品。
二、Pillow库
Pillow是基于PIL库的一个派生分支,它在 PIL 库的基础上增加了许多新的特性。发展至今,已经成为比PIL本身更具活力的图像处理库。
- Pillow 安装后,导入库的使用方式仍是
import PIL
,但实际上使用的是 Pillow 库,这里的 PIL 可以看做是 Pillow 库的简称。 - Pillow 支持跨平台运行,比如 Windows、Linux、MacOS 等。
- Pillow支持python3,Pillow官网最新版:Pillow 8.4.0。
(1)Pillow库特点
- (1) 支持图像的多种输入格式:jpeg、png、bmp、gif、ppm、tiff 等。且支持图像格式之间的相互转换。
- (2)支持多种图像操作:
- 11、创建缩略图、生成预览图像、图像批量处理等;
- 22、图像裁剪、图像缩放、像素点处理、添加滤镜、图像颜色处理等。
- 33、添加水印、合成 GIF 动态效果图等等。
- (3)可以配合 Python GUI(图形用户界面)工具 Tkinter 一起使用。
(2)Pillow库安装
备注:Pillow 和 PIL 不能共存于同一个环境中,在安装 Pillow 前,需要先卸载 PIL。
-
(1)pip安装:该方法是最简单、轻量级的一种安装方式,并且适用于任何平台。只需执行:
pip install Pillow
。 -
(2)whl轮子安装:
通过Python PyPi第三方库官网下载与平台系统相对应的版本。下载完成后,进入下载文件的所在位置,然后执行:pip install + whl文件名
。 -
(3)Anaconda安装:
Anaconda 是一款开源的 Python 发行版(官网下载地址),是当下较为流行的科学计算平台,支持 Windows、Linux、MacOS 系统。Anaconda 自带许多已经安装完成软件包,其中就包含 Pillow,因此无须重新安装。但默认安装的 Pillow 版本可能会比较低或不是你需要的版本。
验证是否安装成功:
(0)WIN键+R键打开运行,输入cmd,回车进入命令提示符。
(1)输入:python
(打开 Python 解释器交互环境)
(2)输入:import PIL
(如果解释器没有报错,则安装成功)
三、Pillow的Image对象(PIL.Image)
Image 类是 Pillow 库中最为重要的类,该类被定义在和与其同名的 Image 模块中。
- 导入 Image 模块:
from PIL import Image
。 - 使用 Image 类可以实例化 Image 对象,通过调用该对象的属性和方法对图像进行处理。
- Pillow 提供了两种创建 Image 实例对象的方法:open()、new()。
(1)打开图像:Image.open() —— 可以加载任意图像格式
"""
函数说明: im = Image.open(fp, mode = "r")
参数说明:(1)fp(file_path):文件路径, 字符串格式;(2)mode:(可选参数)。若使用,则必须设置mode="r",否则显示ValueError异常。
"""from PIL import Image
im_open = Image.open("C:/Users/pc/Desktop/1.png") # 打开图像
im_open.show() # 显示图像
(2)自建图像:Image.new()
"""
函数说明: im = Image.new(mode, size, color)
参数说明:(1)mode:指定图像模式,字符串格式。如: RGB真彩图像、L灰度图像、CMYK色彩图打印模式等;(2)size:指定图像大小(width, height)。(3)color:图像颜色,默认0表示黑色。参数值支持 [R,G,B] 三元组数字格式、颜色的十六进制值以及颜色英文单词。
"""from PIL import Image
im_new = Image.new(mode='RGB', size=(260, 100), color="#ff0000") # 使用颜色的十六进制格式
im_new.show() # 显示图像
(3)查看Image对象的属性 —— width + height + size + format + randonly + info + mode
from PIL import Image
im = Image.open("C:/Users/pc/Desktop/1.png")
print('打印image对象:', im)
print("图像的宽=%s, 高=%s" %(im.width, im.height)) # width/height:查看图像的宽/高
print("图像的尺寸:", im.size) # size:查看图像的尺寸
print("图像的格式:", im.format) # format:查看图片的格式
print("图像是否为只读:", im.readonly) # readonly:图片是否为只读
print("图像信息:", im.info) # info:查看图片相关信息。包括每英寸像素点大小和截图软件信息
print("图像模式:", im.mode) # mode:图像模式"""
打印image对象:<PIL.PngImagePlugin.PngImageFile image mode=RGB size=1810x228 at 0x17426DA3610>
图像的宽=1810, 高=228
图像的尺寸:(1810, 228)
图像的格式:PNG
图像是否为可读:1
图像信息:{}
图像模式:PGB
"""
(4)保存图像:Image.save() —— 保存的同时可以改变格式
"""
函数说明: Image.save(fp, format=None)
参数说明:(1)fp:图像的存储路径,包含图像的名称+后缀,字符串格式;(2)format:(可选参数),指定图像保存的格式。若不指定文件格式,则以默认的图片格式来存储。
"""from PIL import Image
im = Image.open("C:/Users/pc/Desktop/1.png") # 打开图像
im.save('C:/Users/pc/Desktop/2.bmp') # 保存图像
- 并非所有的图片格式都可以用 save() 方法转换完成,比如将 PNG 格式的图片(四通道 RGBA 模式)保存为 JPG 格式(三通道 RGB 模式)。保存之前,需要进行图像模型转换。
(5)图像模式转换:im.convert() —— 不同格式之间的转换
常用的图像模式如下:
"""
函数说明: im.convert(mode, parms**)
参数说明:(1)mode:指的是要转换成的图像模式;(2)parms:其他可选参数。如:matrix、dither 等。其中,最关键的参数是 mode,其余参数无须关心。
"""
from PIL import Image
import matplotlib.pyplot as pltim = Image.open("大黄蜂.jpg")
print(im.mode) # RGB
im1 = im.convert('1')
im2 = im.convert('L')
im3 = im.convert('P')
im4 = im.convert('RGB')
im5 = im.convert('RGBA')
im6 = im.convert('CMYK')
im7 = im.convert('YCbCr')
# im8 = im.convert('LAB') # ValueError: conversion from RGB to LAB not supported
im9 = im.convert('HSV')
im10 = im.convert('I')
im11 = im.convert('F')
######################################################################
# 绘图
im_list = [im, im1, im2, im3, im4, im5, im6, im7, im9, im10, im11]
for i, j in enumerate(im_list):plt.subplot(3, 4, i+1)plt.title(['raw', '1', 'L', 'P', 'RGB', 'RGBA', 'CMYK', 'YCbCr', 'HSV', 'I', 'F'][i])plt.axis('off')plt.imshow(j)
plt.show()"""
plt.subplot(3,4,1), plt.imshow(im), plt.title('raw'), plt.axis('off')
plt.subplot(3,4,2), plt.imshow(im1), plt.title('1'), plt.axis('off')
plt.subplot(3,4,3), plt.imshow(im2), plt.title('L'), plt.axis('off')
plt.subplot(3,4,4), plt.imshow(im3), plt.title('P'), plt.axis('off')
plt.subplot(3,4,5), plt.imshow(im4), plt.title('RGB'), plt.axis('off')
plt.subplot(3,4,6), plt.imshow(im5), plt.title('RGBA'), plt.axis('off')
plt.subplot(3,4,7), plt.imshow(im6), plt.title('CMYK'), plt.axis('off')
plt.subplot(3,4,8), plt.imshow(im7), plt.title('YCbCr'), plt.axis('off')
# plt.subplot(3,4,9), plt.imshow(im8), plt.title('LAB'), plt.axis('off')
plt.subplot(3,4,10), plt.imshow(im9), plt.title('HSV'), plt.axis('off')
plt.subplot(3,4,11), plt.imshow(im10), plt.title('I'), plt.axis('off')
plt.subplot(3,4,12), plt.imshow(im11), plt.title('F'), plt.axis('off')
plt.show()
"""
(6)图像缩放:im.resize() —— 整体缩放 + 局部放大(指定区域)
- 整体缩放操作
"""
函数说明: resize(size, resample=image.BICUBIC, box=None, reducing_gap=None)
参数说明:(1)size:元组参数 (width,height),图片缩放后的尺寸;(2)resample:(可选参数),指图像重采样滤波器,与 thumbnail() 的 resample 参数类似,默认为 Image.BICUBIC;(3)box:(可选参数),对指定区域进行缩放,默认对整个原图进行缩放。备注1:指定区域必须在原图范围内,若超出范围则报错。每个像素点代表一个单位。备注2:box 的参数值是长度为 4 的像素坐标元组,即 (x_左上, y_左下, x1_右上, y1_右下),分别表示被裁剪矩形区域的左上角(x, y)和右下角(x, y)。例如:(0,0,120,180)表示以原图的左上角为原点,选择宽和高分别是(120,180)的图像区域。(4)reducing_gap:(可选参数),浮点参数值,用于优化图片的缩放效果,常用参数值有 3.0 和 5.0。
"""from PIL import Image
import matplotlib.pyplot as pltim = Image.new(mode='RGB', size=(260, 100), color="#ff0000") # 使用颜色的十六进制格式
im1 = im.resize((550, 260)) # 放大图像
im2 = im.resize((80, 50)) # 缩小图像
######################################################################
# 绘图
im_list = [im, im1, im2]
for i, j in enumerate(im_list):plt.subplot(1, 3, i+1)plt.title(['raw', 'Enlarge image', 'Reduced image'][i])plt.imshow(j)
plt.show()
- 局部放大操作
from PIL import Image
im = Image.open("大黄蜂.jpg")
try:image = im.resize((550, 260), resample=Image.LANCZOS, box=(0, 0, 120, 180))print("查看新图像的尺寸", image.size)image.show()
except IOError:print("操作有误")
(7)图像的缩略图:im.thumbnail() —— 只能在原图上修改,返回None
"""
函数说明: thumbnail(size, resample)
参数说明:(1)size:元组参数,指的是缩小后的图像大小;(2)resample:(可选参数),默认为 Image.BICUBIC。备注:有四种图像重采样滤波器,分别是 Image.BICUBIC(双立方插值法)、PIL.Image.NEAREST(最近邻插值法)、PIL.Image.BILINEAR(双线性插值法)、PIL.Image.LANCZOS(下采样过滤插值法)。
"""from PIL import Image
im = Image.open("C:/Users/pc/Desktop/1.png")
im.thumbnail((150, 50))
注意:缩略图的尺寸与您指定的尺寸可能会出现不一致的情况。
- 因为 Pillow 会对原图像的长、宽进行等比例缩小,当指定的尺寸不符合图像的尺寸规格时,缩略图就会创建失败。比如:指定的尺寸超出了原图像的尺寸规格。
(8)图像通道分离:im.split() —— r/g/b三通道
from PIL import Image
import matplotlib.pyplot as pltim = Image.open("C:/Users/pc/Desktop/1.jpg")
r, g, b = im.split() # 分离颜色通道,产生三个Image对象plt.subplot(131), plt.imshow(im), plt.title('im'), plt.axis('off')
plt.subplot(132), plt.imshow(r), plt.title('r'), plt.axis('off')
plt.subplot(133), plt.imshow(g), plt.title('g'), plt.axis('off')
plt.subplot(133), plt.imshow(b), plt.title('b'), plt.axis('off')
plt.show()# r.show()
# g.show()
# b.show()
(9)图像通道合并:Image.merge() —— 颜色通道合并 + 图像融合(权重值五五开)
- 颜色通道合并
"""
函数说明: Image.merge(mode, bands)
参数说明:(1)mode:指定输出图像的模式(2)bands:参数类型为元组或者列表序列,其元素值是组成图像的颜色通道,比如 RGB 分别代表三种颜色通道(r,g,b)。备注:要求两张图片的模式、大小必须一致,否则不能合并。
"""
from PIL import Image
import matplotlib.pyplot as pltim = Image.open("starry_night.jpg")
r, g, b = im.split() # 分离颜色通道,产生三个 Image 对象
im1 = Image.merge('RGB', (r, g, b)) # 重新组合颜色通道,返回 Image 对象
im2 = Image.merge('RGB', (r, b, g))
im3 = Image.merge('RGB', (g, r, b))
im4 = Image.merge('RGB', (g, b, r))
im5 = Image.merge('RGB', (b, r, g))
im6 = Image.merge('RGB', (b, g, r))plt.subplot(231), plt.imshow(im1), plt.title('rgb'), plt.axis('off')
plt.subplot(232), plt.imshow(im2), plt.title('rbg'), plt.axis('off')
plt.subplot(233), plt.imshow(im3), plt.title('grb'), plt.axis('off')
plt.subplot(234), plt.imshow(im4), plt.title('gbr'), plt.axis('off')
plt.subplot(235), plt.imshow(im5), plt.title('brg'), plt.axis('off')
plt.subplot(236), plt.imshow(im6), plt.title('bgr'), plt.axis('off')
plt.show()
- 图像融合:每张图像的权重值都是50%
from PIL import Image
im_1 = Image.open("starry_night.jpg")
im_2 = Image.open("大黄蜂.jpg")# 因为两种图片的图片格式一致,所以仅需要处理图片的大小,让它们保持一致
im_2 = im_2.resize(im_1.size)
r1, g1, b1 = im_1.split()
r2, g2, b2 = im_2.split()
im_3 = Image.merge('RGB', [r2, g2, b1])
im_3.show()
(10)混合图像:Image.blend() —— 将两张图像叠加在一起,并可以选择其中一张图像的透明度,取值范围[0, 1]。
"""
函数说明: Image.blend(image1, image2, alpha)
参数说明:(1)image1,image2:表示两个 Image 对象。(2)alpha:表示透明度,取值范围为 0 到 1。11:当取值为 0 时,等同于 image1 的拷贝。22:而取值为 1 时,等同于 image2 的拷贝。33:当取值为 0.5 时,与Image.merge()效果等同。备注:要求两张图片的模式、大小必须一致,否则不能合并。
"""from PIL import Imageim_1 = Image.open("starry_night.jpg")
im_2 = Image.open("大黄蜂.jpg")
im_2 = im_2.resize(im_1.size)
im3 = Image.blend(im_1, im_2, 0.7)
im3.show()
<11> 图像裁剪:im.crop() —— 获取指定区域
"""
函数说明: crop(box=None)
参数说明: box:表示裁剪区域,默认为 None,表示拷贝原图像。备注:box 是一个有四个数字的元组参数 (x_左上, y_左下, x1_右上, y1_右下),分别表示被裁剪矩形区域的左上角(x, y)和右下角(x, y)。默认(0, 0)表示坐标原点,宽度的方向为 x 轴,高度的方向为 y 轴,每个像素点代表一个单位。
"""from PIL import Imageim = Image.open("大黄蜂.jpg")
im2 = im.crop((0, 0, 50, 50))
im2.show()
<12> 图像拷贝:im.copy() —— 深拷贝
"""
函数说明: copy(image)
参数说明: image:拷贝图像;
"""from PIL import Imageim = Image.open("大黄蜂.jpg")
im_copy = im.copy()
im_copy.show()
<13> 图像粘贴:im.paste() —— 可以将两张图叠加在一起
"""
函数说明: im.paste(image, box=None, mask=None)
参数说明: (1)image:指被粘贴的图像;(2)box:指定图像被粘贴的位置或者区域,其参数值是长度为 2 或者 4 的元组序列。备注1:长度为 2 时,表示具体的某一点 (x, y)。备注2:长度为 4 时,表示具体的粘贴的区域,此时区域的大小必须要和被粘贴的图像大小保持一致。(3)mask:(可选参数),为图片添加蒙版效果。
"""from PIL import Imageim = Image.open("starry_night.jpg")
im1 = Image.open("大黄蜂.jpg")
im_copy = im1.copy() # 图像拷贝
im_crop = im_copy.crop((0, 0, 200, 100)) # 图像裁剪# 创建一个新的图像作为蒙版,L模式,单颜色值
image_new = Image.new('L', (200, 100), 200)
# 将裁剪后的副本粘贴至副本图像上,并添加蒙版
im.paste(im_crop, (100, 100, 300, 200), mask=image_new) # 图像粘贴
im.show()
<14> 图像几何变换(翻转):im.transpose()
"""
函数说明: im.transpose(method)
常见方法: (1)Image.FLIP_LEFT_RIGHT:左右水平翻转;(2)Image.FLIP_TOP_BOTTOM:上下垂直翻转;(3)Image.ROTATE_90:图像旋转 90 度;(4)Image.ROTATE_180:图像旋转 180 度;(5)Image.ROTATE_270:图像旋转 270 度;(6)Image.TRANSPOSE:图像转置;(7)Image.TRANSVERSE:图像横向翻转。
"""from PIL import Image
import matplotlib.pyplot as pltim = Image.open("starry_night.jpg")
im1 = im.transpose(Image.FLIP_LEFT_RIGHT)
im2 = im.transpose(Image.FLIP_TOP_BOTTOM)
im3 = im.transpose(Image.ROTATE_90)
im4 = im.transpose(Image.ROTATE_180)
im5 = im.transpose(Image.ROTATE_270)
im6 = im.transpose(Image.TRANSPOSE)
im7 = im.transpose(Image.TRANSVERSE)
############################################################
# 绘图
im_list = [im, im1, im2, im3, im4, im5, im6, im7]
for i, j in enumerate(im_list):plt.subplot(2, 4, i+1)plt.title(['raw', 'Image.FLIP_LEFT_RIGHT', 'Image.FLIP_TOP_BOTTOM', 'Image.ROTATE_90', 'Image.ROTATE_180', 'Image.ROTATE_270', 'Image.TRANSPOSE', 'Image.TRANSVERSE'][i])plt.axis('off')plt.imshow(j)
plt.show()"""
plt.subplot(421), plt.imshow(im), plt.title('raw_image'), plt.axis('off')
plt.subplot(422), plt.imshow(im1), plt.title('Image.FLIP_LEFT_RIGHT'), plt.axis('off')
plt.subplot(423), plt.imshow(im2), plt.title('Image.FLIP_TOP_BOTTOM'), plt.axis('off')
plt.subplot(424), plt.imshow(im3), plt.title('Image.ROTATE_90'), plt.axis('off')
plt.subplot(425), plt.imshow(im4), plt.title('Image.ROTATE_180'), plt.axis('off')
plt.subplot(426), plt.imshow(im5), plt.title('Image.ROTATE_270'), plt.axis('off')
plt.subplot(427), plt.imshow(im6), plt.title('Image.TRANSPOSE'), plt.axis('off')
plt.subplot(428), plt.imshow(im7), plt.title('Image.TRANSVERSE'), plt.axis('off')
plt.show()
"""
<15> 图像几何变换(旋转):im.rotate()
"""
函数说明: im.rotate(angle, resample=PIL.Image.NEAREST, expand=None, center=None, translate=None, fillcolor=None)
参数说明: (1)angle:表示任意旋转的角度;(2)resample:重采样滤波器,默认为 PIL.Image.NEAREST 最近邻插值方法;(3)expand:可选参数,表示是否对图像进行扩展,如果参数值为 True 则扩大输出图像,如果为 False 或者省略,则表示按原图像大小输出;(4)center:可选参数,指定旋转中心,参数值是长度为 2 的元组,默认以图像中心进行旋转;(5)translate:表示对旋转后的图像进行平移。参数值为二元组,以左上角为原点;可以为负数(6)fillcolor:可选参数,填充颜色,图像旋转后,对图像之外的区域进行填充。
"""from PIL import Imageim = Image.open("starry_night.jpg")
im_out = im.rotate(angle=30, translate=(0, -25), fillcolor="green")
im_out.show()
<16> 图像几何变换(形状变换):im.transform()
"""
函数说明: im.transform(size, method, data=None, resample=0)
参数说明: (1)size:指定变换后的图像尺寸;(2)method:指定图像的变化方式。比如:Image.EXTENT 表示矩形变换;(3)data:截取原图像的区域(4)resample:图像重采样滤波器,默认参数值为 PIL.Image.NEAREST。
"""from PIL import Imageim = Image.open("starry_night.jpg")
im_out = im.transform((500, 500), Image.EXTENT, data=[0, 0, 100 + im.width//2, im.height//3])
im_out.show()
<17> 图像降噪处理:ImageFilter —— 集成多种滤波器(17种)
常见的降噪滤波器如下表:官网Fillow:对每个滤波器的详细定义
函数 | 说明 |
---|---|
from PIL import ImageFilter | \ |
– | – |
ImageFilter.BLUR | 模糊滤波(均值滤波) |
ImageFilter.CONTOUR | 轮廓滤波(寻找图像轮廓信息) |
ImageFilter.DETAIL | 细节滤波(使得图像细节更加明显) |
ImageFilter.FIND_EDGES | 寻找边界滤波(找寻图像的边界信息) |
ImageFilter.EMBOSS | 浮雕滤波(以浮雕图的形式显示图像) |
ImageFilter.EDGE_ENHANCE | 边界增强滤波(突出、加强和改善图像中不同灰度区域之间的边界和轮廓的图像增强方法。) |
ImageFilter.EDGE_ENHANCE_MORE | 深度边缘增强滤波(使得图像中边缘部分更加明显) |
ImageFilter.SMOOTH | 平滑滤波(突出图像的宽大区域、低频成分、主干部分或抑制图像噪声和干扰高频成分,使图像亮度平缓渐变,减小突变梯度,改善图像质量。) |
ImageFilter.SMOOTH_MORE | 深度平滑滤波(使得图像变得更加平滑) |
ImageFilter.SHARPEN | 锐化滤波(补偿图像的轮廓,增强图像的边缘及灰度跳变的部分) |
ImageFilter.GaussianBlur() | 高斯模糊 |
ImageFilter.UnsharpMask() | 反锐化掩码滤波 |
ImageFilter.Kernel() | 卷积核滤波:Kernel(size,kernel, scale=None, offset=0) 。(1)当前版本,size必须为(3,3)或者(5,5)。kernel必须对应为9个或者25个整数或者浮点数的序列。如:Kernel((3,3),(1,1,1,0,0,0,2,0,2) 。(2)scale:将卷积核作用于每个像素值之后的数据,都需要除以这个变量。默认值为卷积核的权重之和。(3)offset:将该值加到卷积核作用的结果上,然后再除以变量scale。 |
ImageFilter.MinFilter(num) | 最小值滤波器,从 size=num x num 参数指定的区域中选择最小像素值,然后将其存储至输出图像中。 |
ImageFilter.MedianFilter(num) | 中值滤波器,从 size=num x num参数指定的区域中选择中值像素值,然后将其存储至输出图像中。(特别是消除椒盐噪声,中值滤波的效果要比均值滤波更好) |
ImageFilter.MaxFilter(num) | 最大值滤波器,从 size=num x num参数指定的区域中选择最大值像素值,然后将其存储至输出图像中。 |
ImageFilter.ModeFilter(num) | 模式滤波,从 size=num x num参数指定的区域中拷贝出现次数最多的像素值存储到输出图像中。如果没有一个像素值出现过两次极其以上,则使用原始像素值。 |
from PIL import Image, ImageFilter
import matplotlib.pyplot as pltim = Image.open("大黄蜂.jpg")
im1 = im.filter(ImageFilter.BLUR)
im2 = im.filter(ImageFilter.CONTOUR)
im3 = im.filter(ImageFilter.DETAIL)
im4 = im.filter(ImageFilter.FIND_EDGES)
im5 = im.filter(ImageFilter.EMBOSS)
im6 = im.filter(ImageFilter.EDGE_ENHANCE)
im7 = im.filter(ImageFilter.EDGE_ENHANCE_MORE)
im8 = im.filter(ImageFilter.SMOOTH)
im9 = im.filter(ImageFilter.SMOOTH_MORE)
im10 = im.filter(ImageFilter.SHARPEN)
im11 = im.filter(ImageFilter.GaussianBlur())
im12 = im.filter(ImageFilter.UnsharpMask())
im13 = im.filter(ImageFilter.Kernel((3,3),(1,1,1,0,0,0,2,0,2)))
im14 = im.filter(ImageFilter.MinFilter(3))
im15 = im.filter(ImageFilter.MedianFilter(3))
im16 = im.filter(ImageFilter.MaxFilter(3))
im17 = im.filter(ImageFilter.ModeFilter())
############################################################
# 绘图
im_list = [im, im1, im2, im3, im4, im5, im6, im7, im8, im9, im10, im11, im12, im13, im14, im15, im16, im17]
for i, j in enumerate(im_list):plt.subplot(4, 5, i+1)plt.title(['raw', 'ImageFilter.BLUR', 'ImageFilter.CONTOUR', 'ImageFilter.DETAIL', 'ImageFilter.FIND_EDGES', 'ImageFilter.EMBOSS', 'ImageFilter.EDGE_ENHANCE', 'ImageFilter.EDGE_ENHANCE_MORE', 'ImageFilter.SMOOTH', 'ImageFilter.SMOOTH_MORE', 'ImageFilter.SHARPEN', 'ImageFilter.GaussianBlur', 'ImageFilter.UnsharpMask', 'ImageFilter.Kernel', 'ImageFilter.MinFilter', 'ImageFilter.MedianFilter', 'ImageFilter.MaxFilter', 'ImageFilter.ModeFilter'][i])plt.axis('off')plt.imshow(j)
plt.show()"""
plt.subplot(4,5,1), plt.imshow(im), plt.title('raw_image'), plt.axis('off')
plt.subplot(4,5,2), plt.imshow(im1), plt.title('ImageFilter.BLUR'), plt.axis('off')
plt.subplot(4,5,3), plt.imshow(im2), plt.title('ImageFilter.CONTOUR'), plt.axis('off')
plt.subplot(4,5,4), plt.imshow(im3), plt.title('ImageFilter.DETAIL'), plt.axis('off')
plt.subplot(4,5,5), plt.imshow(im4), plt.title('ImageFilter.FIND_EDGES'), plt.axis('off')
plt.subplot(4,5,6), plt.imshow(im5), plt.title('ImageFilter.EMBOSS'), plt.axis('off')
plt.subplot(4,5,7), plt.imshow(im6), plt.title('ImageFilter.EDGE_ENHANCE'), plt.axis('off')
plt.subplot(4,5,8), plt.imshow(im7), plt.title('ImageFilter.EDGE_ENHANCE_MORE'), plt.axis('off')
plt.subplot(4,5,9), plt.imshow(im8), plt.title('ImageFilter.SMOOTH'), plt.axis('off')
plt.subplot(4,5,10), plt.imshow(im9), plt.title('ImageFilter.SMOOTH_MORE'), plt.axis('off')
plt.subplot(4,5,11), plt.imshow(im10), plt.title('ImageFilter.SHARPEN'), plt.axis('off')
plt.subplot(4,5,12), plt.imshow(im11), plt.title('ImageFilter.GaussianBlur'), plt.axis('off')
plt.subplot(4,5,13), plt.imshow(im12), plt.title('ImageFilter.UnsharpMask'), plt.axis('off')
plt.subplot(4,5,14), plt.imshow(im13), plt.title('ImageFilter.Kernel'), plt.axis('off')
plt.subplot(4,5,15), plt.imshow(im14), plt.title('ImageFilter.MinFilter'), plt.axis('off')
plt.subplot(4,5,16), plt.imshow(im15), plt.title('ImageFilter.MedianFilter'), plt.axis('off')
plt.subplot(4,5,17), plt.imshow(im16), plt.title('ImageFilter.MaxFilter'), plt.axis('off')
plt.subplot(4,5,18), plt.imshow(im17), plt.title('ImageFilter.ModeFilter'), plt.axis('off')
plt.show()
"""
<18> 图像像素增强:ImageEnhance —— 对选择的属性增强N倍(颜色平衡、对比度、亮度、锐度)
常见的降噪滤波器如下表:
函数 | 说明 |
---|---|
from PIL import ImagEnhance | \ |
– | – |
ImageEnhance.Color(im).enhance(N) | 调整图像的颜色平衡 |
ImageEnhance.Contrast(im).enhance(N) | 调整图像的对比度 |
ImageEnhance.Brightness(im).enhance(N) | 调整图像的亮度 |
ImageEnhance.Sharpness(im).enhance(N) | 调整图像的锐度 |
from PIL import Image, ImageEnhance
import matplotlib.pyplot as pltim = Image.open("大黄蜂.jpg")
im1 = ImageEnhance.Color(im).enhance(2)
im2 = ImageEnhance.Contrast(im).enhance(2)
im3 = ImageEnhance.Brightness(im).enhance(2)
im4 = ImageEnhance.Sharpness(im).enhance(8)
############################################################
# 绘图
im_list = [im, im1, im2, im3, im4]
for i, j in enumerate(im_list):plt.subplot(2, 3, i+1)plt.title(['raw', 'ImageEnhance.Color', 'ImageEnhance.Contrast', 'ImageEnhance.Brightness', 'ImageEnhance.Sharpness'][i])plt.axis('off')plt.imshow(j)
plt.show()"""
plt.subplot(2,3,1), plt.imshow(im), plt.title('raw_image'), plt.axis('off')
plt.subplot(2,3,2), plt.imshow(im1), plt.title('ImageEnhance.Color'), plt.axis('off')
plt.subplot(2,3,3), plt.imshow(im2), plt.title('ImageEnhance.Contrast'), plt.axis('off')
plt.subplot(2,3,4), plt.imshow(im3), plt.title('ImageEnhance.Brightness'), plt.axis('off')
plt.subplot(2,3,5), plt.imshow(im4), plt.title('ImageEnhance.Sharpness'), plt.axis('off')
plt.show()
"""
<19> 绘制图形:ImageDraw.Draw() —— 添加文字 + 绘制点、直线、矩形、多边形、椭圆、圆弧、弦、饼图
方法 | 说明 |
---|---|
draw = ImageDraw.Draw(im) | 新建 ImageDraw 绘图对象,参数 im 表示 Image 对象 |
– | – |
draw.text(xy=(x,y), "text", font, fill=None) | 绘制文字。(1)(x,y):起始坐标位置,以图像左上角为坐标原点;(2)text:字符串格式,要添加的文本内容;(3)font:ImageFont 对象;(4)fill:填充色。 |
draw.point(xy=(x,y), fill=None) | 绘制点。(1)(x,y):起始坐标位置,以图像左上角为坐标原点;(2)fill:填充色。 |
draw.line(xy=(x1, y1, x2, y2), fill=None, width=None) | 绘制直线。(1)(x,y):左上角和右下角位置,以图像左上角为坐标原点;(2)fill:填充色。(3)边框宽度 |
draw.rectangle(xy=(x1, y1, x2, y2), fill=None, outline=None, width=None) | 绘制矩形。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)fill:填充色;(3)outline:边框颜色。(4)边框宽度 |
draw.polygon(xy=(x1, y1, x2, y2), fill=None, outline=None, width=None) | 绘制多边形。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)fill:填充色;(3)outline:边框颜色;(4)边框宽度 |
draw.eclipse(xy=(x1, y1, x2, y2), fill=None, outline=None, width=None) | 绘制椭圆形。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)fill:填充色;(3)outline:边框颜色;(4)边框宽度 |
draw.arc(xy=(x1, y1, x2, y2), start, end, fill=None, width=None) | 绘制圆弧。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)start:开始点;(3)end:结束点;(4)fill:填充色;(5)边框宽度 |
draw.chord(xy=(x1, y1, x2, y2), start, end, fill=None, outline=None, width=None) | 绘制弦。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)start:开始点;(3)end:结束点;(4)fill:填充色;(5)outline:边框颜色;(6)边框宽度 |
draw.pieslice(xy=(x1, y1, x2, y2), start, end, fill=None, outline=None, width=None) | 绘制饼图。(1)xy:左上角和右下角位置,以图像的左上角为坐标原点;(2)start:开始点;(3)end:结束点;(4)fill:填充色;(5)outline:边框颜色;(6)边框宽度 |
"""
函数说明: ImageColor.getrgb(color)
参数说明: 一个颜色名称,字符串格式,可以是颜色的英文单词,或者十六进制颜色名。如果是不支持的颜色,会报 ValueError 错误;备注:该模块支持不同格式的颜色,比如 RGB 格式的颜色三元组、十六进制的颜色名称(#ff0000)以及颜色英文单词("red")。
"""from PIL import Image, ImageDraw, ImageFontim = Image.new('RGB', (600, 600), color='gray') # 创建 Image 对象,当做背景图
draw = ImageDraw.Draw(im) # 创建 ImageDraw 对象######################################################################
# 绘制文字
font = ImageFont.truetype('C:/Windows/Fonts/msyh.ttc', size=25) # 加载计算机本地字体文件
draw.text(xy=(200, 200), text='胖墩会武术', fill=(255, 0, 0), font=font) # 在原图像上添加文本
"""
函数说明: font = ImageFont.truetype(font, size)
参数说明: (1)font:指定的字体格式文件路径,字符串格式。如:TrueType 和 OpenType 类型的字体(2)size:字体大小
"""
######################################################################
# 绘制点 —— 点的pixel为1,若觉得太小可以使用绘制圆来替代
draw.point(((400, 250), (400, 200), (400, 220)), fill=(255, 255, 0))
###################################
# 绘制直线
draw.line(((5,5), (5,100)), fill=(255,0,0), width=5)
###################################
# 绘制矩形
draw.rectangle(((10,10), (50,50)), fill=(0,255,0), outline=(255,0,0))
# 绘制正方形
draw.rectangle(((50,50), (100,100)), fill=None, outline=(0,0,255), width=5)
# 绘制多边形
draw.polygon(((400, 400), (350, 380), (420, 350)), fill=(255, 255, 0), outline=(0, 0, 0))
###################################
# 绘制椭圆形
draw.ellipse(((100, 100), (120, 150)), fill=(0, 255, 0), outline=(255, 0, 0))
# 绘制圆形
draw.ellipse(((250, 250), (300, 300)), fill=None, outline=(0, 0, 255), width=5)
# 绘制圆弧
draw.arc((25, 50, 175, 200), start=30, end=270, fill=(255, 255, 0))
# 绘制弦
draw.chord((225, 50, 375, 200), start=30, end=270, fill=(255, 255, 0), outline=(0, 0, 0))
# 绘制饼图
draw.pieslice((425, 50, 575, 200), start=30, end=270, fill=(255, 255, 0), outline=(0, 0, 0))im.show()
(20)获取 RGB 值:ImageColor.getrgb()
RGB 色彩模式、HSL (色调-饱和度-明度)、HSB (又称 HSV,色调-饱和度-亮度)。
下面对 HSL 做简单介绍:
- H:即 Hue 色调,取值范围 0 -360,其中 0 表示红色(red),120 表示绿色(green),240 表示蓝色(blue);
- S:即 Saturation 饱和度,代表色彩的纯度,取值 0~100%,其中 0 代表灰色(gry),100% 表示色光最饱和;
- L:即 Lightness 明度,取值为 0~100%,其中 0 表示黑色(black),50% 表示正常颜色,100% 则表示白色。
"""
函数说明: ImageColor.getrgb(color)
参数说明: 一个颜色名称,字符串格式,可以是颜色的英文单词,或者十六进制颜色名。如果是不支持的颜色,会报 ValueError 错误;备注:该模块支持不同格式的颜色,比如 RGB 格式的颜色三元组、十六进制的颜色名称(#ff0000)以及颜色英文单词("red")。
"""from PIL import Image, ImageColorcolor1 = ImageColor.getrgb("blue")
color2 = ImageColor.getrgb('#DCDCDC')
color3 = ImageColor.getrgb('HSL(0, 100%, 50%)') # 使用HSL模式红色print(color1) # (0, 0, 255)
print(color2) # (220, 220, 220)
print(color3) # (255, 0, 0)
(21)获取颜色值:ImageColor.getcolor()
"""
函数说明: ImageColor.getcolor(color, mode)
参数说明: (1)color:一个颜色名称,字符串格式,可以是颜色的英文单词,或者十六进制颜色名。如果是不支持的颜色,会报 ValueError 错误;(2)mode:指定色彩模式,如果是不支持的模式,会报 KeyError 错误。备注:该模块支持不同格式的颜色,比如 RGB 格式的颜色三元组、十六进制的颜色名称(#ff0000)以及颜色英文单词("red")。
"""from PIL import Image, ImageColorcolor4 = ImageColor.getcolor('#EEA9B8','L')
color5 = ImageColor.getcolor('yellow','RGBA')print(color4) # 191
print(color5) # (255, 255, 0, 255)
(22)ndarray数组与图像之间的相互转换:np.array + Image.fromarray
ndarray 是 NumPy 中的数组类型,也称为 ndarray 数组,该数组可以与 Pillow 的 PIL.Image 对象实现相互转化。
from PIL import Image
import numpy as npimg = Image.open("C:/Users/pc/Desktop/1.png")
img_2 = np.array(img) # Image图像转换为ndarray数组
arr_img = Image.fromarray(img_2) # ndarray转换为Image图像
arr_img.show()
(23)读取序列图像: seek() + tell() 、ImageSequence()
Pillow 库也包含对图像序列(动画格式)的一些基本支持。支持的序列格式文件包括:GIF、TIFF 和 FLI 等等。当加载序列图像时,默认加载的是第一帧。
- 方法一:除使用 seek() 方法读取图像序列外,ImageSequence 模块还提供了 for 循环迭代遍历图像序列的方法。你可以使用 seek() 和 tell() 方法访问不同的帧。
from PIL import Image
import matplotlib.pyplot as pltfname = r'C:\Users\my\Desktop\image\my.gif'
im = Image.open(fname)
im_list = [im.copy()]
try:while True:im.seek(im.tell()+1)im_list.append(im.copy())
except EOFError:pass
#################################################
# 绘图
for i, j in enumerate(im_list):plt.subplot(1, 4, i+1)plt.title(str(i+1))plt.axis('off')plt.imshow(j)
plt.show()
- 方法二:除使用 seek() 方法读取图像序列外,ImageSequence 模块还提供了 for 循环迭代遍历图像序列的方法。
from PIL import Image, ImageSequence
import matplotlib.pyplot as pltfname = r'C:\Users\my\Desktop\image\my.gif'
im = Image.open(fname)
im_list = []
for frame in ImageSequence.Iterator(im):im_list.append(frame.copy())
##############################################
# 绘图
for i, j in enumerate(im_list):plt.subplot(1, 4, i+1)plt.title(str(i+1))plt.axis('off')plt.imshow(j)
plt.show()
应用一:批量修改图像尺寸
import os
from PIL import Image# 若文件夹不存在,则新建:NewImage
if not os.path.exists('C:/Users/pc/Desktop/NewImage/'):os.mkdir('C:/Users/pc/Desktop/NewImage/') fileName = os.listdir('C:/Users/pc/Desktop/image01/') # 指定图像的文件夹:image01
for img in fileName:raw_image = Image.open('C:/Users/pc/Desktop/image01/' + img)new_image = raw_image.resize((350, 350), Image.BILINEAR)new_image.save('C:/Users/pc/Desktop/NewImage/'+img)
应用二:图像添加水印:ImageDraw + ImageFont
即在原图上添加自定义的字体
from PIL import Image, ImageFont, ImageDrawdef creating_watermark(im, text, font):# 给水印添加透明度,因此需要转换图片的格式im_rgba = im.convert('RGBA')im_text_canvas = Image.new('RGBA', im_rgba.size, (255, 255, 255, 0))draw = ImageDraw.Draw(im_text_canvas)text_x_width, text_y_height = draw.textsize(text, font=font) # 设置文本文字大小text_xy = (im_rgba.size[0] - text_x_width, im_rgba.size[1] - text_y_height)draw.text(text_xy, text, font=font, fill=(0, 125, 125)) # 设置文本im_text = Image.alpha_composite(im_rgba, im_text_canvas) # 将原图片与文字复合return im_textimage = Image.open("大黄蜂.jpg")
font1 = ImageFont.truetype('C:/Windows/Fonts/msyh.ttc', size=100)
image_water = creating_watermark(image, '胖墩会武术', font=font1)
image_water.show()
应用三:生成GIF动态图
以第一张图片作为开始,将多张连续图像合并成 gif 动态图
import os
import random
from PIL import Imagedef png_to_gif(png_path, gif_name):"""png合成gif图像:保存图像的文件夹路径, gif保存路径"""frames = []png_files = os.listdir(png_path)print(png_files)# 读取文件内的静态图for frame_id in range(1, len(png_files)+1):frame = Image.open(os.path.join(png_path, 'image%d.jpg'%frame_id))frames.append(frame)frames[0].save(gif_name, save_all=True, append_images=frames[1:], transparency=0, duration=2000, loop=0, disposal=2)
# 函数作用:以第一张图片作为开始,将后续5张图片合并成 gif 动态图
# 参数说明:
# save_all 保存图像;
# transparency 设置透明背景色;
# duration 单位毫秒,动画持续时间。
# loop=0 无限循环;
# disposal=2 恢复原背景颜色。
# 注意:Pillow 总是以灰度模式(L)或调色板模式(P)来读取 GIF 文件。
png_to_gif("C:/Users/pc/Desktop/image", 'C:/Users/pc/Desktop/t.gif')
相关文章:
Pillow图像处理(PIL.Image类的详细使用)
文章目录 Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序Python图像处理库(PIL、Pillow、Scikit-image、Opencv)Pillow 官方文档(超详细,超推荐)一、PIL库与Pillow库的区别二、Pillow库(…...
嵌入式开发——ADC开发
学习目标 了解ADC开发流程掌握采样方式能够使用ADC进行芯片内部通道进行采样能够使用ADC对外部电路进行采样学习内容 GD32F4的ADC 特点: 16个外部模拟输入通道;1个内部温度传感通道(VSENSE);1个内部参考电压输入通道(VREFINT);1个外部监测电池VBAT供电引脚输入通道。ADC开…...
FreeSWITCH t38测试
主叫 192.168.100.205 被叫 192.168.100.121 主叫侧发送multipage.tif 被叫侧接收传真,保存为recv.tif 主叫侧: originate [fax_enable_t381][fax_verbose1][fax_disable_v170][fax_ident77777777][fax_enable_t38_request1]sofia/internal/1234192.168.100.121:…...
跑腿配送系统技术探析
概述 跑腿配送系统是一种基于现代科技的服务平台,通过智能化的技术手段,实现用户需求的快速响应和高效配送。本文将探讨该系统的核心技术原理,以及在实际开发中的一些代码示例。 技术原理 1. 用户请求与任务分配 跑腿配送系统的第一步是…...
【数据不完整?用EM算法填补缺失】期望值最大化 EM 算法:睹始知终
期望值最大化算法 EM:睹始知终 算法思想算法推导算法流程E步骤:期望M步骤:最大化陷入局部最优的原因 算法应用高斯混合模型(Gaussian Mixture Model, GMM)问题描述输入输出Python代码实现 算法思想 期望值最大化方法&a…...
PMP证书可以挂靠吗?
PMP证书不是国内的证书,挂靠不了呀,想挂靠,可以考软考/一建等,里面也有项目管理相关的证书。 PMP证书虽然不能挂靠,但是用处还是很大的,例如提升个人能力、薪资待遇,还有持证可享一些城市的福利…...
HTML语义化的理解
HTML语义化是指在编写HTML代码时,合理地选择适当的标签和属性来描述页面的结构和内容,使得代码更具有可读性、可维护性和可访问性。 可读性:通过使用语义化的标签,可以清晰地表达页面的结构和内容,使得代码更易于阅读和…...
(Java企业 / 公司项目)注册,配置中心Nacos的怎么使用?(含相关面试题)(一)
在企业项目中使用Nacos实现的功能操作,以及如何在自己的环境中搭建Nacos环境,包含demo 一. 官网介绍:home (nacos.io) 文档地址:Nacos 快速开始 二. 准备Nacos环境 在公司里面很多的服务以及环境都是自己搭建的所以我在这里就从…...
计算机网络---知识点
ARPANET----NFSNET—ANSNET—Internet发展及协议 移动互联网 物联网 无线自组网、无线传感器网络、无线个域网 ISO/OSI网络体系结构 TCP/IP网络体系结构 对等通信、PDU 电路交换、报文交换、分组报文交换 虚电路、数据报 信道复用技术 网络性能的主要指标(…...
力扣42. 接雨水
双指针法 思路: 将数组前后设置为 left、right 指针,相互靠近;在逼近的过程中记录两端最大的值 leftMax、rightMax,作为容器的左右边界;更新指针规则: 如果数组左边的值比右边的小,则更新 left…...
SpringSecurity-2.7中跨域问题
SpringSecurity-2.7中跨域问题 访问测试 起因 写这篇的起因是会了解到 SSM(CrosOrigin)解决跨域,但是会在加入SpringSecurity配置后,这个跨域解决方案就失效了,而/login这个请求上是无法添加这个注解或者通过配置(WebMvcConfig)去解决跨域,所以只能使用SpringSecurity提供的.c…...
Java解决字典序最小回文串
Java解决字典序最小回文串 01 题目 给你一个由 小写英文字母 组成的字符串 s ,你可以对其执行一些操作。在一步操作中,你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 ,使 s 变成一个 回文串 。如果执行 最少 操…...
【力扣100】207.课程表
添加链接描述 class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:# 思路是计算每一个课的入度,然后使用队列进行入度为0的元素的进出# 数组:下标是课程号,array[下标]是这个课程的入度# 哈希…...
2024年生成式AI支出将翻倍,到2027年将超1500亿美元
据国际数据公司(IDC)的预测,2023年全球企业在生成式人工智能(GenAI)解决方案上的投资已达194亿美元,预计在2024年将翻番。该预测还指出,包括GenAI软件、相关硬件和服务在内的支出将在2027年达到1511亿美元,…...
【代码随想录】刷题笔记Day42
前言 这两天机器狗终于搞定了,一个控制ROS大佬,一个计院编程大佬,竟然真把创新点这个弄出来了,牛牛牛牛(菜鸡我只能负责在旁边喊加油)。下午翘了自辩课来刷题,这次应该是元旦前最后一刷了&…...
数据库云平台新数科技完成B轮融资,打造全链路智能化数据库云平台
数据库云平台软件厂商「北京新数科技有限公司」(以下简称「新数科技」)已于2023年完成B1轮和B2轮融资,分别由渤海创富和彬复资本投资;义柏资本担任本轮融资独家财务顾问。 新数科技成立于2014年,当前产品矩阵包括数据库…...
【Linux 内核源码分析】Linux内核通知链机制
Linux内核通知链(notifier chain)是一种机制,用于实现内核中的事件通知和处理。它提供了一种灵活的方式,让不同的模块可以注册自己感兴趣的事件,并在事件发生时接收到通知。 通知链由一个或多个注册在其中的回调函数组…...
2023年度回顾:怿星科技的转型与创新
岁月不居,时节如流。随着2023年的落幕,怿星科技在这一年中不仅实现了自身的转型,还在技术创新、产品研发、行业合作和人才培养等方面取得了显著的成就。这一年,怿星科技正式完成了从服务型公司向产品型公司的战略转变,…...
STM32MP157D-DK1 Qt程序交叉编译与运行测试
上篇文章介绍了STM32MP157D-DK1开发板Qt镜像的构建,通过在Ubuntu中重新编译带有Qt功能的系统来实现。 本篇在上篇的基础上,继续搭建Qt的交叉编译环境,实现Qt程序在Ubuntu中编译,在STM32MP157板子中运行。 1 编译安装SDK 在上篇…...
Rancher 单节点 docker 部署备份与恢复
Rancher 单节点 docker 部署备份与恢复 1. 备份集群 获取 rancher server 容器名,本例为 angry_aryabhata docker ps | grep rancher/rancher6a27b8634c80 rancher/rancher:v2.5.14 xxx angry_aryabhata停止容器 docker stop angry_aryabhata创建备…...
WPF容器的背景对鼠标事件的影响
背景:在实现鼠标拖动窗口的过程中发现对父容器设置了鼠标拖动窗口的事件MouseLeftButtonDown private void DragWindow(object sender, MouseButtonEventArgs e) {if (e.LeftButton MouseButtonState.Pressed)DragMove(); } 问题:非常困惑的是&#x…...
pve虚拟机无法开机‘ha-manager set vm:101 --state started‘ failed: exit code 255
pve虚拟机无法开机,提示 ha-manager set vm:101 --state started failed: exit code 255 () Requesting HA start for VM 101 service vm:101 in error state, must be disabled and fixed first TASK ERROR: command ha-manager set vm:101 --state started fail…...
官宣!亚信安全TrustOne实力代言“中国新一代终端安全”
近日,IDC《中国新一代终端安全市场洞察,2023——安全防御的“最前线”》发布,正式定义了“中国新一代终端安全”的技术概念、技术演进和技术特点。该报告基于大量市场调研和数据分析,深入阐释了中国终端安全市场现状及面临的困局&…...
Text visualization : pipeline,wordle,phrase net,word tree
Text visualization(文本可视化)是一种将文本数据转换为可视形式的技术,以便更好地理解和分析文本内容。以下是可能会涉及的几个知识点: 1. Pipeline(流程图):Pipeline是指将文本可视化的过程划…...
C# WPF上位机开发(报表导出)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于在工厂上班的小伙伴来说,导出生产数据、生成报表,这是很习以为常的一个工作。之前的文章中,虽然我们也介绍…...
CentOS7安装部署Zookeeper
文章目录 CentOS7安装部署Zookeeper一、前言1.简介2.架构3.集群角色4.特点5.环境 二、正文1.部署服务器2.基础环境1)主机名2)Hosts文件3)关闭防火墙4)JDK 安装部署 3.单机部署1)下载和解压2)配置文件3&…...
OceanBase入选Gartner®云数据库管理系统魔力象限“荣誉提及”
近日,全球IT市场研究和咨询公司Gartner发布最新报告《Magic Quadrant™ for Cloud Database Management Systems》(全球云数据库管理系统魔力象限)。全自研分布式数据库 OceanBase 入选“荣誉提及”,2022 年推出的云数据库 OB Clo…...
Oracle 19C DBA管理常用命令
登入数据库主机,查看 CRS 资源状态: 集群资源启动完毕后,在任意一节点上利用crsctl查看集群状态。 查看:/u01/app/19c/grid/bin/crsctl status res -t 集群资源管理命令: 启动:/u01/app/19c/grid/bin/cr…...
BIO和NIO编程(待完善)
目录 IO模型 BIO NIO 常见问题 IO模型 Java共支持3种网络编程IO模式:BIO,NIO,AIO BIO 同步阻塞模型,一个客户端连接对应一个处理线程 代码示例: Server端: public class BioServer {private static …...
基于RocketMQ实现分布式事务
前言 在上一篇文章Spring Boot自动装配原理以及实践我们完成了服务通用日志监控组件的开发,确保每个服务都可以基于一个注解实现业务功能的监控。 而本文我们尝试基于RocketMQ实现下单的分布式的事务。可能会有读者会有疑问,之前我们不是基于Seata完成了…...
恩施市住房和城乡建设局网站/seo工具软件
闭包的优点,延长或扩大了变量的使用范围,延长了变量的使用时间,2.避免了变量命名的冲突 缺点:如果乱用闭包,会造成空间的浪费 创建person新实列:1创建一个新对象 2.将构造函数的作用域赋给新对象࿰…...
ps个人网站怎么做/外国网站的浏览器
linux可以与很多文件系统完美的结合,可以很容易地把Windows、其他Unix系统、甚至在市场上很小众的文件系统轻松地移植到linux中。 这对于linux今天的成功是功不可没的,那为什么这么厉害了,linux是怎么做到的呢?这里的功臣就是VFS&…...
湖北自适应网站建设报价/广州专门做网站
2019独角兽企业重金招聘Python工程师标准>>> 本文纯粹是个整理。 以下代码和图片来自C 11右值引用。 class CMyString { public:// 构造函数CMyString(const char *pszSrc NULL){cout << "CMyString(const char *pszSrc NULL)" << endl;if …...
wordpress tob8.0/谷歌sem推广
一 问题描述 问题描述前,请允许我,吐槽一下,这个问题困扰了一天,下面在业务层下的代码中,cache注解标注了value的名称,但是没有设置key,且传递的参数为 CrawlRecordParamVo crawlRecordParamV…...
wordpress h1标签/免费平台
文章目录散列查找1. 基本思想2. 基本工作3. 散列函数的构造1. 考虑因素2. 数字关键词1. 直接定址法2. 除留余数法3. 数字分析法4. 折叠法5. 平方取中法3. 字符串关键字1. ASCII码加和法2. 前3个字符移位法3. 移位法4. 冲突处理方法1. 常用策略2. 开放定址法1. 线性探测2. 平方探…...
男做女爱网站/东莞网络推广策略
这里是修真院web小课堂,每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解web知识/技能,本篇分享的是: 【简述JS中的event delegate】 在javasript中deleg…...