python 图像处理学习笔记
python数字图像处理学习笔记
环境安装和配置
下载安装anaconda
通过命令来安装和更新python库
conda install ***
conda update ***
from skimage import io
img=io.imread('d:/dog.jpg')
io.imshow(img)
图像的读取、显示与保存
读取灰度图片 skimage.io.imread(fname,as_grey=True)
保存图片 io.imsave(fname,arr)
from skimage import io,data
img=data.chelsea()
io.imshow(img)
io.imsave('d:/cat.jpg',img)
from skimage import io,data
img=data.chelsea()
io.imshow(img)
print(type(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()) #像素平均值
图像像素的访问与裁剪
#输出G通道的某个位置的像素值
from skimage import io,data
img=data.chelsea()
pixel=img[20,30,1]
print(pixel)
#显示红色单通道图片
from skimage import io,data
img=data.chelsea()
R=img[:,:,0]
io.imshow(R)
#对图片随机添加椒盐
from skimage import io,data
import numpy as np
img=data.chelsea()
#随机生成5000个椒盐
rows,cols,dims=img.shape
for i in range(5000):
x=np.random.randint(0,rows)
y=np.random.randint(0,cols)
img[x,y,:]=255
io.imshow(img)
裁剪图片
from skimage import io,data
img=data.chelsea()
roi=img[80:180,100:200,:]
io.imshow(roi)
img[i,:] = im[j,:] # 将第 j 行的数值赋值给第 i 行
img[:,i] = 100 # 将第 i 列的所有数值设为 100
img[:100,:50].sum() # 计算前 100 行、前 50 列所有数值的和
img[50:100,50:100] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)
img[i].mean() # 第 i 行所有数值的平均值
img[:,-1] # 最后一列
img[-2,:] (or im[-2]) # 倒数第二行
#将图片进行二值化,像素值大于128的变为1,否则变为0
from skimage import io,data,color
img=data.lena()
img_gray=color.rgb2gray(img)
rows,cols=img_gray.shape
for i in range(rows):
for j in range(cols):
if (img_gray[i,j]<=0.5):
img_gray[i,j]=0
else:
img_gray[i,j]=1
io.imshow(img_gray)
from skimage import io,data
img=data.chelsea()
reddish = img[:, :, 0] >170
img[reddish] = [0, 255, 0]
io.imshow(img)
这个例子先对R通道的所有像素值进行判断,如果大于170,则将这个地方的像素值变为[0,255,0], 即G通道值为255,R和B通道值为0。
图像数据类型及颜色空间转换
一张图片的像素值范围是[0,255], 因此默认类型是unit8, 可用如下代码查看数据类型:
from skimage import io,data
img=data.chelsea()
print(img.dtype.name)
一张彩色图片转换为灰度图后,它的类型就由unit8变成了float
float转uint8
from skimage import img_as_ubyte
import numpy as np
img = np.array([0, 0.5, 1], dtype=float)
print(img.dtype.name)
dst=img_as_ubyte(img)
print(dst.dtype.name)
在color模块的颜色空间转换函数中,还有一个比较有用的函数是
skimage.color.label2rgb(arr), 可以根据标签值对图片进行着色。以后的图片分类后着色就可以用这个函数。
例:将lena图片分成三类,然后用默认颜色对三类进行着色
from skimage import io,data,color
import numpy as np
img=data.lena()
gray=color.rgb2gray(img)
rows,cols=gray.shape
labels=np.zeros([rows,cols])
for i in range(rows):
for j in range(cols):
if(gray[i,j]<0.4):
labels[i,j]=0
elif(gray[i,j]<0.75):
labels[i,j]=1
else:
labels[i,j]=2
dst=color.label2rgb(labels)
io.imshow(dst)
图像的绘制
matplotlib是一个专业绘图的库,相当于matlab中的plot,可以设置多个figure窗口,设置figure的标题,隐藏坐标尺,甚至可以使用subplot在一个figure中显示多张图片。一般我们可以这样导入matplotlib库:
import matplotlib.pyplot as plt
用subplots来创建显示窗口与划分子图
import matplotlib.pyplot as plt
from skimage import data,color
img = data.immunohistochemistry()
hsv = color.rgb2hsv(img)
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
ax0.imshow(img)
ax0.set_title("Original image")
ax1.imshow(hsv[:, :, 0], cmap=plt.cm.gray)
ax1.set_title("H")
ax2.imshow(hsv[:, :, 1], cmap=plt.cm.gray)
ax2.set_title("S")
ax3.imshow(hsv[:, :, 2], cmap=plt.cm.gray)
ax3.set_title("V")
for ax in axes.ravel():
ax.axis('off')
fig.tight_layout() #自动调整subplot间的参数
图像的批量处理
图片集合函数为:
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))
io.imshow(coll[10]) #显示其中一张图片
读取不同类型的图片
str='d:/pic/*.jpg:d:/pic/*.png'
例:把系统自带的所有png示例图片,全部转换成256*256的jpg格式灰度图,保存在d:/data/文件夹下
改变图片的大小,我们可以使用tranform模块的resize()函数,后续会讲到这个模块。
from skimage import data_dir,io,transform,color
import numpy as np
def convert_gray(f):
rgb=io.imread(f) #依次读取rgb图片
gray=color.rgb2gray(rgb) #将rgb图片转换成灰度图
dst=transform.resize(gray,(256,256)) #将灰度图片大小转换为256*256
return dst
str=data_dir+'/*.png'
coll = io.ImageCollection(str,load_func=convert_gray)
for i in range(len(coll)):
io.imsave('d:/data/'+np.str(i)+'.jpg',coll[i]) #循环保存图片
图像的形变与缩放
改变图片尺寸resize
skimage.transform.resize(image, output_shape)
image: 需要改变尺寸的图片
output_shape: 新的图片尺寸
from skimage import transform,data
import matplotlib.pyplot as plt
img = data.camera()
dst=transform.resize(img, (80, 60))
plt.figure('resize')
plt.subplot(121)
plt.title('before resize')
plt.imshow(img,plt.cm.gray)
plt.subplot(122)
plt.title('before resize')
plt.imshow(dst,plt.cm.gray)
plt.show()
按比例缩放rescale
skimage.transform.rescale(image, scale[, ...])
scale参数可以是单个float数,表示缩放的倍数,也可以是一个float型的tuple,如[0.2,0.5],表示将行列数分开进行缩放
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倍
旋转 rotate
skimage.transform.rotate(image, angle[, ...],resize=False)
angle参数是个float类型数,表示旋转的度数
resize用于控制在旋转时,是否改变大小 ,默认为False
from skimage import transform,data
import matplotlib.pyplot as plt
img = data.camera()
print(img.shape) #图片原始大小
img1=transform.rotate(img, 60) #旋转90度,不改变大小
print(img1.shape)
img2=transform.rotate(img, 30,resize=True) #旋转30度,同时改变大小
print(img2.shape)
plt.figure('resize')
plt.subplot(121)
plt.title('rotate 60')
plt.imshow(img1,plt.cm.gray)
plt.subplot(122)
plt.title('rotate 30')
plt.imshow(img2,plt.cm.gray)
plt.show()
图像金字塔
以多分辨率来解释图像的一种有效但概念简单的结构就是图像金字塔。图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低的图像集合。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。当向金字塔的上层移动时,尺寸和分辨率就降低。
skimage.transform.pyramid_gaussian(image, downscale=2)
downscale控制着金字塔的缩放比例
import numpy as np
import matplotlib.pyplot as plt
from skimage import data,transform
image = data.astronaut() #载入宇航员图片
rows, cols, dim = image.shape #获取图片的行数,列数和通道数
pyramid = tuple(transform.pyramid_gaussian(image, downscale=2)) #产生高斯金字塔图像
#共生成了log(512)=9幅金字塔图像,加上原始图像共10幅,pyramid[0]-pyramid[1]
composite_image = np.ones((rows, cols + cols / 2, 3), dtype=np.double) #生成背景
composite_image[:rows, :cols, :] = pyramid[0] #融合原始图像
i_row = 0
for p in pyramid[1:]:
n_rows, n_cols = p.shape[:2]
composite_image[i_row:i_row + n_rows, cols:cols + n_cols] = p #循环融合9幅金字塔图像
i_row += n_rows
plt.imshow(composite_image)
plt.show()
除了高斯金字塔外,还有其它的金字塔,如:
skimage.transform.pyramid_laplacian(image, downscale=2):
对比度与亮度调整
图像亮度与对比度的调整,是放在skimage包的exposure模块里面
gamma调整
原理:I=Ig
对原图像的像素,进行幂运算,得到新的像素值。公式中的g就是gamma值。
如果gamma>1, 新图像比原图像暗
如果gamma<1,新图像比原图像亮
skimage.exposure.adjust_gamma(image, gamma=1)
gamma参数默认为1,原像不发生变化 。
from skimage import data, exposure, img_as_float
import matplotlib.pyplot as plt
image = img_as_float(data.moon())
gam1= exposure.adjust_gamma(image, 2) #调暗
gam2= exposure.adjust_gamma(image, 0.5) #调亮
plt.figure('adjust_gamma',figsize=(8,8))
plt.subplot(131)
plt.title('origin image')
plt.imshow(image,plt.cm.gray)
plt.axis('off')
plt.subplot(132)
plt.title('gamma=2')
plt.imshow(gam1,plt.cm.gray)
plt.axis('off')
plt.subplot(133)
plt.title('gamma=0.5')
plt.imshow(gam2,plt.cm.gray)
plt.axis('off')
plt.show()
log对数调整(和gamma相反)
from skimage import data, exposure, img_as_float
import matplotlib.pyplot as plt
image = img_as_float(data.moon())
gam1= exposure.adjust_log(image) #对数调整
plt.figure('adjust_gamma',figsize=(8,8))
plt.subplot(121)
plt.title('origin image')
plt.imshow(image,plt.cm.gray)
plt.axis('off')
plt.subplot(122)
plt.title('log')
plt.imshow(gam1,plt.cm.gray)
plt.axis('off')
plt.show()
判断图像对比度是否偏低
is_low_contrast(img)
from skimage import data, exposure
image =data.moon()
result=exposure.is_low_contrast(image)
print(result)
调整强度
skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')
in_range 表示输入图片的强度范围,默认为'image', 表示用图像的最大/最小像素值作为范围
out_range 表示输出图片的强度范围,默认为'dype', 表示用图像的类型的最大/最小值作为范围