01 您所在的位置:网站首页 怎么保存python的图片 01

01

2023-07-18 09:37| 来源: 网络整理| 查看: 265

Numpy的图片处理(读取,变换,保存)

使用Numpy的ndarray可以读取图片文件,并且可以对图片进行各种各样的处理。 例如:图片像素值的读取,替换,随机剪裁,拼接等等都可以使用ndarray。对于已经习惯使用Numpy的人们来说,已经可以不使用OpenCV进行图像处理。

即便是使用OpenCV进行图片处理的时候,OpenCV图像的读取也是使用的ndarray形式,所以直接使用Numpy将会更加的方便与快捷。

在此:对图片文件的基础读取,保存方法进行介绍

Numpy图片文件的读取方法Numpy图片文件的保存方法

和一些Numpy的图像处理的实例进行介绍

像素值的读取和修改图片的单色化和图片的拼接减色处理二值化处理四则演算切片修剪按切片或函数的拆分切片粘贴Alpha混合和遮罩处理旋转和上/下/左/右 反转 等等进行说明。 图片文件读取(Numpy的ndarray形式)

使用以下的图片为例。 在这里插入图片描述 np.array中调用PIL.Image.open()函数进行读取,并且可以查看数据的类型和形状(shape,行(高),列(宽),色(通道数))等信息。 需要注意的是色(通道数)的读取顺序是RGB(红,绿,蓝)。而OpenCV的cv2.imread()的读取顺序是(BGR),稍有不同。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena.jpg')) print(type(im)) # print(im.dtype) # uint8 print(im.shape) # (225, 400, 3)

convert(‘L’)函数可以把图片转换成黑白图片(灰度图)之后,将图片作为2维数据进行读取。 此时形状只剩下了行(高)和列(宽)。

im_gray = np.array(Image.open('./data/01/lena.jpg').convert('L')) print(im_gray.shape) # (225, 400)

使用np.asarray()同样可以返回得到一个ndarray的数组。但是使用np.array()返回的是一个允许被更改的ndarray,np.asarray()返回的ndarra不允许被更改。

'''np.array()''' print(im.flags.writeable) # True print(im[0, 0, 0]) # 109 im[0, 0, 0] = 0 print(im[0, 0, 0]) # 0 '''np.asarray()''' im_as = np.asarray(Image.open('./data/01/lena.jpg')) print(type(im_as)) # print(im_as.flags.writeable) # False # im_as[0, 0, 0] = 0 # ValueError: assignment destination is read-only

图片的数据类型是以uint8(8位无符号整型)进行的读取。若想以float类型进行读取时,可以使用astype()进行转换,或者指定np.array()和np.asarray()的第2个参数(指定类型的读取)。

im_f = im.astype(np.float64) print(im_f.dtype) # float64 im_f = np.array(Image.open('./data/01/lena.jpg'), np.float64) print(im_f.dtype) # float64 图片文件保存(Numpy的ndarray形式)

使用Image.fromarray()函数读取ndarray数据时,可以得到一个PIL.Image类型的文件。再使用save()函数可以将其保存下来。被保存的文件格式,将根据其指定的扩展名自动进行判别。

pil_img = Image.fromarray(im) print(pil_img.mode) # RGB pil_img.save('./data/01/lena_save_pillow.jpg')

黑白图片的保存也可以。

pil_img_gray = Image.fromarray(im_gray) print(pil_img_gray.mode) # L pil_img_gray.save('./data/01/lena_save_pillow_gray.jpg')

简洁的写法

Image.fromarray(im).save('./data/01/lena_save_pillow.jpg') Image.fromarray(im_gray).save('./data/01/lena_save_pillow_gray.jpg')

float类型进行保存时,有可能会出现错误。此时,需要将其类型转换成uint8之后,再保存。

# pil_img = Image.fromarray(im_f) # TypeError: Cannot handle this data type pil_img = Image.fromarray(im_f.astype(np.uint8)) pil_img.save('./data/01/lena_save_pillow.jpg')

使用astype()进行类型转换保存的时候,不会进行比例的缩放,所以当像素值为0.0-1.0之间的时候,需要先将其乘以255,再保存。

像素值的读取和修改

index[]可以取得指定坐标点的像素值。指定的顺序是行,列。xy的话,y,x的顺序指定。原点(0,0)为图片的左上角。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena.jpg')) print(im.shape) # (225, 400, 3) print(im[100, 150]) # [111 81 109] print(type(im[100, 150])) #

上述的实例中,(y,x)=(100,150)为第100行,150列的像素值。和上述的一样,使用Pillow,ndarray数组读取时,颜色的排列读取顺序为RGB,(R,G,B)=(110,81,109)。

R, G, B = im[100, 150] print(R) # 111 print(G) # 81 print(B) # 109

index[]指定像素值的读取。

print(im[100, 150, 0]) # 111 print(im[100, 150, 1]) # 81 print(im[100, 150, 2]) # 109

修改像素值的时候,可以RGB三色同时进行修改,或者单色修改。

im[100, 150] = (0, 50, 100) print(im[100, 150]) # [ 0 50 100] im[100, 150, 0] = 150 print(im[100, 150]) # [150 50 100]

在实际的日常操作中,通常是对图片整体或者是切片的部分进行操作,对单个像素值的操作并不常见。

图片的单色化和拼接

其他的像素值修改为0,单色图片的生成,以及横向的图片拼接。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena_square.png')) im_R = im.copy() im_R[:, :, (1, 2)] = 0 im_G = im.copy() im_G[:, :, (0, 2)] = 0 im_B = im.copy() im_B[:, :, (0, 1)] = 0 # 向的图片拼接 im_RGB = np.concatenate((im_R, im_G, im_B), axis=1) # im_RGB = np.hstack((im_R, im_G, im_B)) # im_RGB = np.c_['1', im_R, im_G, im_B] pil_img = Image.fromarray(im_RGB) pil_img.save('./data/01/lena_numpy_split_color.jpg')

处理结果 在这里插入图片描述

像素值的反转

用像素值的最大值(uint8类型)255减去其像素值。

import numpy as np from PIL import Image im = np.array(Image.open('./data/01/lena_square.png').resize((256, 256))) im_i = 255 - im Image.fromarray(im_i).save('./data/01/lena_numpy_inverse.jpg') 在这里插入图片描述 减色处理

用//求其舍去余数值之后,再次相乘。则像素值为离散值,并且可以减少颜色的数量。

import numpy as np from PIL import Image im = np.array(Image.open('./data/01/lena_square.png').resize((256, 256))) im_32 = im // 32 * 32 im_128 = im // 128 * 128 im_dec = np.concatenate((im, im_32, im_128), axis=1) Image.fromarray(im_dec).save('./data/01/lena_numpy_dec_color.png') 在这里插入图片描述 二值化处理

设定一个中间值,对图片进行非黑即白的二值化处理 在这里插入图片描述

四则运算

乘法,除法,累乘等计算。 函数可以对图片全体进行计算,所以无需使用for等循环函数。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena_square.png')) im_1_22 = 255.0 * (im / 255.0)**(1 / 2.2) im_22 = 255.0 * (im / 255.0)**2.2 im_gamma = np.concatenate((im_1_22, im, im_22), axis=1) pil_img = Image.fromarray(np.uint8(im_gamma)) pil_img.save('./data/01/lena_numpy_gamma.jpg')

在这里插入图片描述 计算的结果ndarray类型为float类型。所以最后保存时,需要先转换成uint8类型之后,再保存。

切片修剪

指定范围的矩形切片。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena_square.png')) print(im.shape) # (512, 512, 3) im_trim1 = im[128:384, 128:384] print(im_trim1.shape) # (256, 256, 3) Image.fromarray(im_trim1).save('./data/01/lena_numpy_trim.jpg')

在这里插入图片描述 以左上角为原点,指定宽和高的裁剪。

def trim(array, x, y, width, height): return array[y:y + height, x:x+width] im_trim2 = trim(im, 128, 192, 256, 128) print(im_trim2.shape) # (128, 256, 3) Image.fromarray(im_trim2).save('./data/01/lena_numpy_trim2.jpg') 在这里插入图片描述 按切片或函数的拆分

可以使用切片分割图片。与从图片边裁进行裁剪相同。

from PIL import Image import numpy as np im = np.array(Image.open('./data/01/lena_square.png').resize((256, 256))) print(im.shape) # (256, 256, 3) im_0 = im[:, :100] im_1 = im[:, 100:] print(im_0.shape) # (256, 100, 3) print(im_1.shape) # (256, 156, 3) Image.fromarray(im_0).save('./data/01/lena_numpy_split_0.jpg') Image.fromarray(im_1).save('./data/01/lena_numpy_split_1.jpg')

在这里插入图片描述 在这里插入图片描述 横向分割函数为np.hsplit()。第二个参数为整数值时,将进行相等的分割。

im_0, im_1 = np.hsplit(im, 2) print(im_0.shape) # (256, 128, 3) print(im_1.shape) # (256, 128, 3)

第二个参数值为列表时,在那个值的位置处进行分割。

im_0, im_1, im_2 = np.hsplit(im, [100, 150]) print(im_0.shape) # (256, 100, 3) print(im_1.shape) # (256, 50, 3) print(im_2.shape) # (256, 106, 3)

np.hsplit()和np.vsplit()指定第二个参数值时,不能进行等份分割时,便会发生错误。此时,用np.array_split()的话,会自动调节尺寸,进行分割。

# im_0, im_1, im_2 = np.hsplit(im, 3) # ValueError: array split does not result in an equal division im_0, im_1, im_2 = np.array_split(im, 3, axis=1) print(im_0.shape) # (256, 86, 3) print(im_1.shape) # (256, 85, 3) print(im_2.shape) # (256, 85, 3) 切片粘贴

切片可以将一个矩阵中的矩形区域替换到另一个矩阵中去。 比如:图片的一部分粘贴到全图片中。

import numpy as np from PIL import Image src = np.array(Image.open('./data/01/lena_square.png').resize((128, 128))) dst = np.array(Image.open('./data/01/lena_square.png').resize((256, 256))) // 4 dst_copy = dst.copy() dst_copy[64:128, 128:192] = src[32:96, 32:96] Image.fromarray(dst_copy).save('data/dst/lena_numpy_paste.jpg')

在这里插入图片描述

dst_copy = dst.copy() dst_copy[64:192, 64:192] = src Image.fromarray(dst_copy).save('./data/01/lena_numpy_paste_all.jpg') 在这里插入图片描述 Alpha混合和遮罩处理

由于可以很容易的对矩阵中的每个元素进行操作,因此可以对2个图片进行混合和遮罩处理。 在这里插入图片描述

选择 上/下/左/右 反转

矩阵的旋转,反转等函数的应用效果。 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有