>>> from env_helper import info; info()
页面更新时间: 2024-04-07 16:01:44
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-18-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
1.6. python数字图像处理:图像的批量处理¶
有些时候,我们不仅要对一张图片进行处理,可能还会对一批图片处理。这时候,我们可以通过循环来执行处理,也可以调用程序自带的图片集合来处理。
图片集合函数为:
skimage.io.ImageCollection(load_pattern,load_func=None)
这个函数是放在io模块内的,带两个参数,第一个参数load_pattern, 表示图片组的路径,可以是一个str字符串。第二个参数load_func是一个回调函数,我们对图片进行批量处理就可以通过这个回调函数实现。回调函数默认为imread(),即默认这个函数是批量读取图片。
先看一个例子:
>>> import skimage.io as io
>>> from skimage import data_dir
>>> str=data_dir + '/*.png'
>>> coll = io.ImageCollection(str)
>>> print(len(coll))
30
显示结果为 30
, 说明系统自带了 30
张 PNG 的示例图片,
这些图片都读取了出来,放在图片集合coll里。
如果我们想显示其中一张图片,则可以使用索引:
>>> io.imshow(coll[10])
<matplotlib.image.AxesImage at 0x7f14b5e8fc90>
如果一个文件夹里,我们既存放了一些jpg格式的图片,又存放了一些png格式的图片,现在想把它们全部读取出来,该怎么做呢?
>>> import skimage.io as io
>>> from skimage import data_dir
>>> str=data_dir+'/*.jpg:'+data_dir+'/*.png'
>>> coll = io.ImageCollection(str)
>>> print(len(coll))
33
注意这个地方 data_dir+'/*.jpg:'+data_dir+'/*.png'
,是两个字符串合在一起的。 第一个是 data_dir+'/*.jpg:'
, 第二个是
data_dir+'/*.png'
。
合在一起后,中间用冒号来隔开,这样就可以把文件夹下的jpg和png格式的图片都读取出来。
如果还想读取存放在其它地方的图片,也可以一并加进去,只是中间同样用冒号来隔开。
io.ImageCollection()
这个函数省略第二个参数,就是批量读取。
如果我们不是想批量读取,而是其它批量操作,如批量转换为灰度图,那又该怎么做呢?
那就需要先定义一个函数,然后将这个函数作为第二个参数,如:
>>> from skimage import data_dir,io,color
>>>
>>> def convert_gray(f):
>>> rgb=io.imread(f)
>>> # return rgb
>>> return color.rgb2gray(rgb)
>>> data_dir
'/usr/lib/python3/dist-packages/skimage/data'
>>>
>>> str_d=data_dir+'/*.png'
>>> coll = io.ImageCollection(str_d,load_func=convert_gray)
>>> coll
<skimage.io.collection.ImageCollection at 0x7f14ac9d8310>
>>> # io.imshow(coll[10])
在 skimg 中上面结果无法显示,出错信息:
ValueError: the input array must have size 3 along `channel_axis`, got (300, 400)
这里给出使用 opencv2 的方法:
>>> import cv2
>>>
>>> image = cv2.imread(data_dir + '/chelsea.png')
>>> grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
libpng warning: iCCP: known incorrect sRGB profile
>>> import matplotlib.pyplot as plt
>>>
>>> plt.imshow(image) # Original Image
>>> plt.imshow(grayscale, cmap="gray"); # Grayscale Image
以下是另外一个完整的例子。来自: https://scikit-image.org/docs/stable/auto_examples/color_exposure/plot_rgb_to_gray.html
>>> import matplotlib.pyplot as plt
>>>
>>> from skimage import data
>>> from skimage.color import rgb2gray
>>>
>>> original = data.astronaut()
>>> grayscale = rgb2gray(original)
>>>
>>> fig, axes = plt.subplots(1, 2, figsize=(8, 4))
>>> ax = axes.ravel()
>>>
>>> ax[0].imshow(original)
>>> ax[0].set_title("Original")
>>> ax[1].imshow(grayscale, cmap=plt.cm.gray)
>>> ax[1].set_title("Grayscale")
>>>
>>> fig.tight_layout()
>>> plt.show()
1.6.1. 读取视频文件¶
这种批量操作对视频处理是极其有用的,因为视频就是一系列的图片组合。
首先使用 iamgeio 模块来读取磁盘中的视频文件:
>>> import imageio
>>> vid = imageio.get_reader('/cvdata/vtest.avi', 'ffmpeg')
>>> type(vid)
imageio.plugins.ffmpeg.FfmpegFormat.Reader
下面看一下用 skimage 来读取:
>>> def vidread_step(f, step):
>>> vid = imageio.get_reader(f)
>>> seq = [v for v in vid.iter_data()]
>>> return seq[::step]
>>>
>>> ic = io.ImageCollection('/cvdata/vtest.avi', load_func=vidread_step, step=30)[0]
这段代码的意思,就是将这个视频中每隔 30 帧的图片读取出来,放在图片集合中。
>>> import matplotlib.pyplot as plt
>>> plt.imshow(ic[0])
<matplotlib.image.AxesImage at 0x7f14afec8510>
>>> plt.imshow(ic[20])
<matplotlib.image.AxesImage at 0x7f14afa00550>
得到图片集合以后,我们还可以将这些图片连接起来,构成一个维度更高的数组,连接图片的函数为:
>>> joined = io.concatenate_images(ic)
带一个参数,就是以上的图片集合,如:
>>> from skimage import data_dir,io,color
>>>
>>> coll = io.ImageCollection('*.png')
>>> # mat=io.concatenate_images(coll)
使用 concatenate_images()
函数的前提是读取的这些图片尺寸必须一致,否则会出错。
我们看看图片连接前后的维度变化:
>>> print(len(ic)) #连接的图片数量
>>> print(ic[0].shape) #连接前的图片尺寸,所有的都一样
>>>
>>>
>>> mat=io.concatenate_images(joined)
>>> print(mat.shape) #连接后的数组尺寸
27
(576, 768, 3)
(27, 576, 768, 3)
可以看到,将2个3维数组,连接成了一个4维数组
如果我们对图片进行批量操作后,想把操作后的结果保存起来,也是可以办到的。
例:把系统自带的所有png示例图片,全部转换成256*256的jpg格式灰度图,并进行保存:¶
改变图片的大小,我们可以使用 tranform
模块的 resize()
函数。
>>> from skimage import data_dir,io,transform,color
>>> import numpy as np
>>>
>>> def convert_gray(f):
>>> rgb=io.imread(f) #依次读取rgb图片
>>>
>>> # 由于不同来源的数据波段或通道不一定是3个,可能会触发异常。
>>> try:
>>> gray=color.rgb2gray(rgb) #将rgb图片转换成灰度图
>>> except:
>>> return np.array(
>>> [[0,1],
>>> [0,254],
>>> [0,0] ]
>>> )
>>>
>>> dst=transform.resize(gray,(256,256)) #将灰度图片大小转换为256*256
>>> return dst
>>>
>>> # str='*.png'
>>> str_d=data_dir+'/*.png'
>>> coll = io.ImageCollection(str_d,load_func=convert_gray)
>>> for i in range(len(coll)):
>>> # io.imsave( 'xx_' + np.str(i)+'.jpg',coll[i]) #循环保存图片
>>> io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_2.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_4.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_5.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_6.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_8.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_10.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_12.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_14.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_15.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_16.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_17.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_18.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_20.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_21.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_22.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_25.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_26.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_27.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
WARNING:root:Lossy conversion from float64 to uint8. Range [0, 1]. Convert image to uint8 prior to saving to suppress this warning.
/tmp/ipykernel_44368/1922167539.py:25: UserWarning: xx_29.jpg is a low contrast image
io.imsave( 'xx_' + f'{i}.jpg',coll[i]) #循环保存图片
WARNING:root:Lossy conversion from int64 to uint8. Range [0, 254]. Convert image to uint8 prior to saving to suppress this warning.
同样的方式,我们把开始读取的视频文件保留成单独的图片:
>>> coll = io.ImageCollection('/cvdata/vtest.avi', load_func=vidread_step, step=30)[0]
>>> for i in range(len(coll)):
>>> io.imsave( f'xx_{i}.jpg',coll[i]) #循环保存图片