阿齐兹的PyCV学习笔记——NumPy

NumPy

Numpy是一个基础的Python科学计算工具包,它包含了:

  • 强大的N维数组对象
  • 复杂的函数
  • 用于融合C/C++和Fortran的工具
  • 实用的线性代数、傅里叶变换、随机数功能

使用array()方法将图像转换成NumPy的数组对象,第一个参数是数组式的对象,第二个可选参数data-type默认为可以存储该对象的最小数据类型,使用‘f’时可将数据类型转换为浮点型

from PIL import Image
from pylab import *
im = array(Image.open('C:/Users/0AQZ0/Documents/exercisecode/Python/PyCV/Images/002.jpg'))
print(im.shape, im.dtype)

im = array(Image.open('C:/Users/0AQZ0/Documents/exercisecode/Python/PyCV/Images/002.jpg').convert('L'),'f')
print(im.shape, im.dtype)

输出结果:

(874, 650, 3) uint8
(874, 650) float32

第一个元组表示图像数组的大小(行、列、颜色通道),由于灰度图像没有颜色信息,所以没有颜色通道。第二个字符串表示数据类型

为什么导入pylab模块?因为Pylab中包含NumPy的一些内容

数组中的元素可以使用下标访问,多个数组元素可以使用数组切片方式访问

value = im[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列
im[:,-1]           #最后一列
im[-2,:]           #倒数第二行

将图像转换为NumPy数组对象后,可以进行任意的数学操作,例如图像的灰度变换。图像的灰度变换就是使用任意函数f,使得(0,255)区间映射到它自身

from PIL import Image
from numpy import *

im = array(Image.open('C:/Users/0AQZ0/Documents/exercisecode/Python/PyCV/Images/002.jpg').convert('L'))

im2 = 255 - im #反相处理

im3 = (100.0/255) * im +100 #变换到(100,200)区间

im4 = 255.0 * (im/255.0)**2 #二次函数变换,使暗的像素值更小

array()方法的相反操作是PIL的fromarry()方法,将数组逆映射为PIL图像

pil_im = Image.fromarray(im)

对浮点数做乘积或者除法操作时,会将整数型数组变为浮点型,所以逆映射前要转换数据类型

pil_im = Image.fromarray(unit8(im))

定义图像缩放函数,并添加到imtool.py文件中

def imresize(im,sz):
    """使用PIL对象重新定义图像数组的大小"""
    pil_im = Image.fromarray(unit8(im))

    return array(pil_im.resize(sz))

直方图均衡化是指将一幅图像的灰度直方图变平,使每个灰度值的分布概率相同,可以增强图像对比度

定义histeq()函数来获得直方图均衡化后的图像,以及像素值的累积分布函数,第一个参数是灰度图像,第二个是直方图中使用的小区间数目

def histeq(im,nbr_bins=256):
    """对一幅灰度图像进行直方图均衡化"""

    #计算图像的直方图
    imhist,bins = histogram(im.flatten(),nbr_bins,normed=True)
    cdf = imhist.cumsum() #cumulative distribution function
    cdf = 255 * cdf /cdf[-1] #归一化

    #使用累积分布函数的线性插值,计算新的像素值
    im2 = interp(im.flatten(),nins[:-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)

        #将浮点型转换为unit8型
        return array(averageim, 'unit8')

使用mean()方法也可以计算平均图像,但是需要占用很多内存

主成分分析PCA(Principal Component Analysis)是降维的一种技巧,即在使用尽可能少维数的情况下,尽量多地保留训练数据的信息,PCA产生的投影矩阵可以将原始坐标变换到现有的坐标系,坐标系中的各个坐标按重要性递减排列

进行PCA变换时,先使用NumPy的flatten()方法将图像转换成一维向量,再堆积成一个矩阵,矩阵的一行表示一幅图像,然后所有的行图像进行中心化,计算协方差矩阵对应的最大特征值的特征向量,再使用简明的技巧(维数较高时)或者SVD分解(维数较低时)

奇异值分解SVD(Singular Value Decomposition)可以计算主成分,当矩阵的维数很大时计算非常慢

from PIL import Image
from numpy import *

def pca(X):
    """主成分分析:
      输入:矩阵X,其中存储训练数据,每行为一条训练数据
      返回:投影矩阵(按维度的重要性排序),方差,均值"""

    #获取维数
    num_data,dim = X.shape

    #数据中心化
    mean_X = X.mean(axis=0)
    X = X - mean_X

    if dim>num_data:
        #维数高时使用紧致技巧
        M = dot(X,X.T) #协方差矩阵
        e,EV = linalg.eigh(M) #特征值和特征向量
        tmp = dot(X.T,EV).T #这就是紧致技巧
        V = tmp[::-1] #需要最后的特征向量,所以将其逆转
        S = sqrt(e)[::-1] #由于特征值是按递增顺序排列的,所以将其逆转
        for i in range(V.shape[1]):
            V[:,i] /= S
    else:
        #维数较低使用SVD方法
        U,S,V = linalg.svd(X)
        V = V[:num_data] #仅返回前num_data维的数据

    #返回投影矩阵、方差、均值
    return V,S,mean_X

计算图像主成分的脚本:

from PIL import Image
from numpy import *
from pylab import *
import pca

im = array(Image.open(imlist[0]))
m,n = im.shape[0:2] #获取图像的大小
imnbr = len(imlist) #获取图像的数目

#创建矩阵,保存压平后的图像数据
immatrix = array([array(Image.open(im)).flatten() for im in imlist],'f')

#执行PCA操作
V,S,immean = pca.pca(immatrix)

#显示均值图像和前7个模式
figure()
gray()
subplot(2,4,1)
imshow(immean.reshape(m,n))
for i in range(7):
    subplot(2,4,i+2)
    imshow(V[i].reshape(m,n))

show()

reshape()方法可以将一维图像重新转换为二维图像
PyLab的subplot()方法可以在一个窗口中放置多个图像

NumPy中的savetxt()方法和loadtxt()方法可以读写文本文件,savetxt()方法中最后一个参数表示使用整数格式

savetxt('text.txt',x,'%i')
x = loadtxt('test.txt')

参考资料:https://docs.scipy.org/doc/numpy/reference/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值