# 1.3.1 图像数组表示
# array方法将图像转换成Numpy的数组对象
# 数组对象是多维的,可以用来表示向量、矩阵和图像
# 数组对象很像列表,或者说是列表的列表,但其中所有元素须具有相同的数据类型
from PIL import Image
from pylab import *
# 读取图像到数组中
im = array(Image.open('C:/Users/Lenovo/Desktop/picture/call me the queen.jpg'))
print(im.shape, im.dtype)
# 第一个参数是元组 显示图像数组大小,行 列 颜色通道 第二个是数组类型
im = array(Image.open('C:/Users/Lenovo/Desktop/picture/call me the queen.jpg').convert('L'), 'f')
print(im.shape, im.dtype)
# 灰度图像没有颜色信息,故只有两个数值;array函数中'f'参数 将数据类型转换为浮点型
# 访问数组中元素value=im[i,j,k]坐标i,j,颜色通道k
# 多个数组元素可以使用数组切片方式访问
# im[i,:] = im[j,:] # 将第j 行的数值赋值给第i 行
# im[:,i] = 100 # 将第i 列的所有数值设为100
# im[:100,:50].sum() # 计算前100 行、前50 列所有数值的和
# im[50:100,50:100] # 50~100 行,50~100 列(不包括第100 行和第100 列)
# im[i].mean() # 第i 行所有数值的平均值
# im[:,-1] # 最后一列
# im[-2,:] (or im[-2]) # 倒数第二行
# 1.3.2 灰度变换
# array方法将图像转换成Numpy的数组对象
# 数组对象是多维的,可以用来表示向量、矩阵和图像
# 数组对象很像列表,或者说是列表的列表,但其中所有元素须具有相同的数据类型
from PIL import Image
from pylab import *
# 读取图像到数组中
im = array(Image.open('C:/Users/Lenovo/Desktop/picture/call me the queen.jpg').convert('L'))
im2 = 255-im # 对图像进行反相处理
im3 = (100.0/255)*im + 100 # 将图像像素值变换到100...200区间
im4 = 255.0*(im/255.0)**2 # 对图像像素值求平方后得到的图像 使较暗像素值变得更小
print(int(im.min()), int(im.max())) # 查看图像中的最小和最大像素值
print(im3.shape, im3.dtype)
# array变换的相反操作可以用PIL的fromarray函数完成
pil_im = Image.fromarray(uint8(im3)) # 先将数据类型转换 并创建PIL图像
# Numpy总是将数据类型转成能够表示数据的“最低”数据类型
imshow(pil_im)
from PIL import Image
from pylab import *
def imresize(im, sz):
"""使用PIL对象重新定义图像数组的大小"""
pil_im = Image.fromarray(uint8(im))
# 使用之前PIL对图像对象转换的操作,im为数组对象
return array(pil_im.resize(sz))
def histeq(im, nbr_bins=256):
"""对一幅灰度图像进行直方图均衡化
一个参数是灰度图像,一个是直方图中使用小区间的数目
返回值 直方图均衡化后的图像 以及 用来做像素值映射的累积分布函数"""
# 计算图像的直方图
imhist, bins = histogram(im.flatten(), nbr_bins)
cdf = imhist.cumsum() # cumulative distribution function
cdf = 255*cdf/cdf[-1] # 归一化
# 使用累积分布函数的线性插值,计算新的像素值
im2 = interp(im.flatten(), bins[:-1], cdf)
return im2.reshape(im.shape), cdf
def compute_average(imlist):
"""计算图像列表的平均图像
图像平均是减少图像噪声的一种简单方式,通常用于艺术特效"""
# 打开第一幅图像,将其存储在浮点型数组中
averageim = array(Image.open(imlist[0]), 'f')
for imname in imlist[1:]:
try:
averageim += array(Image.open(imname))
except:
print(imname+'...skipped')
averageim /= len(imlist)
# 返回uint8类型的平均图像
return array(averageim, ' uint8')
# 1.3.6 图像的主成分分析(PCA)
# 指的是降维技巧
from PIL import Image
from pylab import * # subplot函数属于pylab库
import os
# 批量处理图像类型的转换 ↓
def get_imlist(path):
"""返回目录中所有jpg图像的文件名列表"""
return [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".jpg")]
# ↑
def pca(X):
"""主成分分析:
输入:矩阵X,矩阵中存储训练数据,每一行为一条训练数据
输出:投影矩阵(按照维度的重要性排序)、方差和均值
"""
# 获取维数
num_data, dim = X.shape
print(dim)
# 数据中心化
mean_X = X.mean(axis=0) # 均值
print(mean_X.shape)
X = X - mean_X
if dim > num_data: # PCA-使用紧致技巧
M = dot(X, X.T) # 协方差矩阵 转置 num_data行 和 列
e, EV = linalg.eigh(M) # 特征值和特征向量 方阵的特征值和特征向量
tmp = dot(X.T, EV).T # 这就是紧致技巧
V = tmp[::-1] # 由于最后的特征向量是我们所需要的,所以需要将其逆转
S = (e[::-1]) # 由于特征值是按照递增顺序排列的,所以需要将其逆转
# 这里的sqrt什么意思,必须加吗??????
for i in range(V.shape[1]): # 列的数目
V[:, i] /= S
else: # PCA-使用SVD方法
U, S, V = linalg.svd(X)
V = V[:num_data] # 仅仅返回前num_data维的数据才合理
# 返回投影矩阵、方差和均值
return V, S, mean_X
imlist = get_imlist('C:/Users/Lenovo/Desktop/picture')
im = array(Image.open(imlist[0]).convert('L')) # 打开一幅图像,获取其大小
m, n = im.shape[0:2] # 获取图像的大小
print(im.flatten().shape)
print(m,n)
imnbr = len(imlist) # 获取图像的数目
# 创建矩阵,保存所有压平后的图像数据 图片大小须一致
immatrix = array([array(Image.open(im).convert('L')).flatten() for im in imlist], 'f')
print(immatrix.shape)
# 执行PCA操作
V, S, immean = pca(immatrix)
# 显示一些图像(均值图像和前7个模式)
figure()
gray()
subplot(2,2,1)
imshow(immean.reshape(m,n))
for i in range(3):
subplot(2,2,i+2)
imshow(V[i].reshape(m,n))
show()
# 保存平均图像和主成分
f = open('pca_modes.pkl', 'wb')
pickle.dump(immean, f)
pickle.dump(V, f)
f.close()
# 载入平均图像和主成分
f = open('pca_modes.pkl', 'rb')
immean = pickle.load(f)
V = pickle.load(f)
f.close()
# 注意载入对象的顺序必须和先前保存的一样
# 使用with语句处理文件的读写操作
# 自动打开和关闭文件(即使在文件打开时发生错误)
# 打开文件并保存
with open('pca_modes.pkl', 'wb') as f:
pickle.dump(immean, f)
pickle.dump(V, f)
# 打开文件并载入
with open('pca_modes.pkl', 'rb') as f:
immean = pickle.load(f)
V = pickle.load(f)
# numpy具有读写文本文件的简单函数
# 举例
a = [(2,3),(1,3),(8,9)]
savetxt('test.txt', a) # 最后一个参数表示使用整数格式
ae = loadtxt('test.txt')