Python 读取显示保存图片----python skimage图像处理

转载:https://blog.csdn.net/weixin_41500849/article/details/80366991

基于python脚本语言开发的数字图片处理包,比如PIL,Pillow, opencv, scikit-image等。PIL和Pillow只提供最基础的数字图像处理,功能有限;opencv实际上是一个c++库,只是提供了python接口,更新速度非常慢。scikit-image是基于scipy的一款图像处理包,它将图片作为numpy数组进行处理,正好与matlab一样。这里选择Skimage模块进行数字图像处理。

 本文主要介绍了图像的读取,显示,保存,色彩转换,批量处理,缩放,对比度调,直方图均衡化等操作。

1,skimage包的子模块

​  skimage包的全称是scikit-image SciKit (toolkit for SciPy) ,它对scipy.ndimage进行了扩展,提供了更多的图片处理功能。它是由python语言编写的,由scipy 社区开发和维护。skimage包由许多的子模块组成,各个子模块提供不同的功能。主要子模块列表如下:

子模块名称 主要实现功能
io 读取、保存和显示图片或视频
data 提供一些测试图片和样本数据
color 颜色空间变换
filters 图像增强、边缘检测、排序滤波器、自动阈值等
draw 操作于numpy数组上的基本图形绘制,包括线条、矩形、圆和文本等
transform 几何变换或其它变换,如旋转、拉伸和拉东变换等
morphology 形态学操作,如开闭运算、骨架提取等
exposure 图片强度调整,如亮度调整、直方图均衡等
feature 特征检测与提取等
measure 图像属性的测量,如相似性或等高线等
segmentation 图像分割
restoration 图像恢复
util 通用函数

程序自带图片

 skimage程序自带了一些示例图片,如果我们不想从外部读取图片,就可以直接使用这些示例图片:

名称 说明 名称 说明 名称 说明
astronaut 航员图片 coffee 一杯咖啡 lena lena美女
camera 拿相机的人 coins 硬币图片 moon 月亮图片
checkerboard 棋盘图片 horse 马图片 page 书页图片
chelsea 小猫图片 hubble_deep_field 星空图片 text 文字图片
clock 时钟图片 immunohistochemistry 结肠图片    

 显示这些图片可用如下代码,图片名对应的就是函数名。

from skimage import io, data
img=data.lena()
io.imshow(img)
  • 1
  • 2
  • 3

2,图像基本操作

2.1 读取

 图像的读取可以使用imread函数,返回的是浮点类型图像数组,代码如下

#常见的显示模块
import matplotlib.pyplot as plt
#使用skimage的io子模块中的imread,所以需要导入io模块
from skimage import io

# 图片文件的路径
filename = 'XXXXX'
# 使用imread读取图像
img = io.imread(filename)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.2 显示

 图像的显示可以使用plt子模块中的imshow函数,代码如下:

#设置图像的大小
plt.figure(figsize = (10,10))
# 使用灰度方式显示图片
plt.imshow(image,'gray')
  • 1
  • 2
  • 3
  • 4

 也可以使用io子模块下的imshow函数,代码如下:

from skimage import io,data
img = data.chelsea()
io.imshow(img)
  • 1
  • 2
  • 3

2.3 保存

 图像的保存可以使用io子模块下的imsave(fname,arr)函数来实现,第一个参数表示保存的路径和名称,第二个参数表示需要保存的数组变量

from skimage import io,data
img = data.chelsea()
io.imshow(img)
io.imsave('cat.jpg',img)
  • 1
  • 2
  • 3
  • 4

图片信息

 可以获得图像中的类型,尺寸,高度,宽度,通道数,总像素个数,最大像素值,最小像素值,像素平均值等信息,代码如下:

from skimage import io, data
img = data.chelsea()
io.imshow(img)       #显示类型
print(img.shape)     #显示尺寸
print(img.shape[0])  #图片高度
print(img.shape[1])  #图片宽度
print(img.shape[2])  #图片通道数
print(img.size)      #显示总像素个数
print(img.max())     #最大像素值
print(img.min())     #最小像素值
print(img.mean())    #像素平均值
print(img[0][0])     #图像的像素值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.4 图像色彩的转换

 使用了color模块的rgb2gray()函数,将色彩三通道图片转换成灰度图,转换结果为float64类型的数组,范围为[0,1]之间,将彩色三通道图片转换成灰度图,最后变成uint8,float64转换成uint8是有信息损失的。代码如下;

from skimage import io,color,img_as_ubyte,data

filename = 'XXXXX'
#读取图像,结果为M*N*3的矩阵,彩色形式
img = io.imread(filename)
# 彩色形式转成灰色形式,结果为M*N的矩阵,元素类型为float64,[0,1]
img_gray = color.rgb2grey(img)
# 将浮点类型转换成uint8型,[0,155],转换后有信息损失。
img_uint = img_as_ubyte(img)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

图像数据类型:

 在skimage中,一张图片就是一个简单的numpy数组,数组的数据类型有很多中,相互之间也可以转换。类型及取值范围如下:

数据类型 范围 数据类型 范围 数据类型 范围
uint8 0 to 255 uint16 0 to 65535 uint32 0 to 232
float -1 to 1 or 0 to 1 int8 -128 to 127 int16 -32768 to 32767
int32 -231 to 231 - 1        

 灰色图片默认的像素范围是[0,255],所以默认使用uint8,可以用如下代码查看数据类型:

from skimage import data
img=data.chelsea()
print(img.dtype.name)
  • 1
  • 2
  • 3

 常见的数据类型转换函数:

函数名称 描述
img_as_float Convert to 64-bit floating point
img_as_ubyte Convert to 8-bit uint
img_as_uint Convert to 16-bit uint
img_as_int Convert to 16-bit int

 类型转换还可以使用color模块下的convert_colorspace函数,代码如下:

from skimage import io,data,color
img=data.lena()
# 从RGB颜色空间转到gray颜色空间
img_gray=color.convert_colorspace(img,'RGB','Gray')
io.imshow(img_gray)
  • 1
  • 2
  • 3
  • 4
  • 5

 另外,label2rgb()函数可以根据标签纸对图片进行着色。

2.5 图像的批量处理

 如果需要对一批图片进行处理,可以调用程序自带的图片集合ImageCollection来处理。语法为:

skimage.io.ImageCollection(load_pattern,load_func=None)
  • 1

 这个函数是放在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)
  • 1
  • 2
  • 3
  • 4

 如果在一个文件夹里,既有jpg格式的图片,又有png的图片,想把它们都读出来,可用下面的代码:

import skimage.io as io
from skimage import data_dir
# 图片之间用冒号隔开
str='d:/pic1/*.jpg:d:/pic2/*.png'
coll = io.ImageCollection(str)
  • 1
  • 2
  • 3
  • 4
  • 5

 如果想对图片进行批量操作,比如转为灰度图,可以用下面的代码:

from skimage import data_dir,io,color
def convert_gray(f): 
       rgb=io.imread(f) 
       return color.rgb2gray(rgb) 

str=data_dir+'/*.png'
coll = io.ImageCollection(str,load_func=convert_gray)
io.imshow(coll[10])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.6 图片的形变与缩放

 图像的形变与缩放,可以使用skimagetransform模块,函数比较多,功能齐全。

改变图片尺寸

 改变图片尺寸可以使用resize函数,语法为:skimage.transform.resize(image, output_shape)

其中,image是需要改变尺寸的图片,output_shape是新的图片的尺寸,代码如下:

from skimage import transform,data
img = data.camera()
dst=transform.resize(img, (80, 60))
  • 1
  • 2
  • 3

图片缩放

 缩放图片可以使用rescale函数,语法为:skimage.transform.rescale(image, scale[, ...])

scale参数可以是单个float函数,表示缩放的倍数,也可以是一个float型的tuple,例子如下:

from skimage import transform,data
img = data.camera()
print(img.shape) #图片原始大小 
print(transform.rescale(img, 0.1).shape) #缩小为原来图片大小的0.1
print(transform.rescale(img, [0.5,0.25]).shape) #缩小为原来图片行数一半,列数四分之一
print(transform.rescale(img, 2).shape) #放大为原来图片大小的2倍
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 结果为:

(512, 512)
(51, 51)
(256, 128)
(1024, 1024)
  • 1
  • 2
  • 3
  • 4

图像旋转

 图像旋转可以使用roate函数,语法为:skimage.transform.rotate(image, angle[, ...],resize=False)

  • angle参数是个float类型数,表示旋转的度数
  • resize用于控制在旋转时,是否改变大小 ,默认为False

 代码如下:

from skimage import transform,data
img = data.camera()
img1=transform.rotate(img, 60) #旋转90度,不改变大小 
img2=transform.rotate(img, 30,resize=True) #旋转30度,同时改变大小
  • 1
  • 2
  • 3
  • 4

2.7 对比度与亮度调整

 图像亮度与对比度的调整,是放在skimage包里的exposure模块里面。

gamma调整

 原理:O=IγO=Iγ

 对原图像的像素,进行幂运算,得到新的像素值,公式中的g就是gamma值。如果gamma大于1,新图像比原图像暗,如果gamma<1,新图像比原图像亮。语法为:skimage.exposure.adjust_gamma(image, gamma=1)

gamma参数默认为1,原图像不发生变化。例子如下:

from skimage import data, exposure, img_as_float
image = img_as_float(data.moon())
gam1= exposure.adjust_gamma(image, 2) #调暗
gam2= exposure.adjust_gamma(image, 0.5) #调亮
  • 1
  • 2
  • 3
  • 4

log对数调整

 这个刚好和gamma相反,原理O=gain∗log(1+I)O=gain∗log(1+I),例子如下:

from skimage import data, exposure, img_as_float
image = img_as_float(data.moon())
gam1= exposure.adjust_log(image) #对数调整
  • 1
  • 2
  • 3

判断图像对比度是否偏低

 函数:is_low_contrast(img),返回一个bool型值。

from skimage import data, exposure
image =data.moon()
result=exposure.is_low_contrast(image)
print(result)
  • 1
  • 2
  • 3
  • 4

 输出为False

调整强度

 函数为rescale_intensity

 语法为skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')

in_range表示输入图片的强度范围,默认为’image’, 表示用图像的最大/最小像素值作为范围 
out_range 表示输出图片的强度范围,默认为’dype’, 表示用图像的类型的最大/最小值作为范围 
默认情况下,输入图片的[min,max]范围被拉伸到[dtype.min, dtype.max],如果dtype=uint8, 那么dtype.min=0, dtype.max=255

 例子为:

import numpy as np
from skimage import exposure
image = np.array([51, 102, 153], dtype=np.uint8)
mat=exposure.rescale_intensity(image)
print(mat)
  • 1
  • 2
  • 3
  • 4
  • 5

2.8 直方图与均衡化

 在图像处理中,直方图是非常重要的,也是非常有用的一个处理要素。在skimage库中,对直方图的处理,是放在exposure这个模块中。

计算直方图

 语法为:skimage.exposure.histogram(image, nbins=256)

 在numpy包中,也提供了一个计算直方图的函数histogram(),两者大同小义。 
返回一个tuple(hist, bins_center), 前一个数组是直方图的统计量,后一个数组是每个bin的中间值

import numpy as np
from skimage import exposure,data
image =data.camera()*1.0
hist1=np.histogram(image, bins=2) #用numpy包计算直方图hist2=exposure.histogram(image, nbins=2) #用skimage计算直方图
print(hist1)
print(hist2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

直方图均衡化

 如果一副图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。直方图均衡化就是一种能仅靠输入图像直方图信息自动达到这种效果的变换函数。它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。例子如下:

from skimage import data,exposure
import matplotlib.pyplot as plt
img=data.moon()
plt.figure("hist",figsize=(8,8))
arr=img.flatten()
plt.subplot(221)
plt.imshow(img,plt.cm.gray) #原始图像
plt.subplot(222)
plt.hist(arr, bins=256, normed=1,edgecolor='None',facecolor='red') #原始图像直方图
img1=exposure.equalize_hist(img) #进行直方图均衡化
arr1=img1.flatten() #返回数组折叠成一维的副本
plt.subplot(223)
plt.imshow(img1,plt.cm.gray) #均衡化图像
plt.subplot(224)
plt.hist(arr1, bins=256, normed=1,edgecolor='None',facecolor='red') #均衡化直方图
plt.show()

猜你喜欢

转载自blog.csdn.net/sinat_39372048/article/details/82695116