首页 > 编程语言 >【python计算机视觉编程——1.基本的图像操作和处理】

【python计算机视觉编程——1.基本的图像操作和处理】

时间:2024-08-27 08:58:08浏览次数:12  
标签:plt python imshow Image 编程 im 图像 import 视觉

python计算机视觉编程——1.基本的图像操作和处理

1.基本的图像操作和处理

1.1 PIL:Python图像处理类库

from PIL import Image
pil_im=Image.open('sun.jpg')
imshow(pil_im)

在这里插入图片描述

  • convert参数有三个值
    • L:转换为8bit灰度图像
    • RGB:3×8像素图像
    • CMYK:4×8像素图像
pil_im=Image.open('sun.jpg').convert('L')    
plt.imshow(pil_im)

在这里插入图片描述

还可以给定转换矩阵,将RGB图像转换为CIE XYZ色彩空间

rgb2xyz = (
    0.412453, 0.357580, 0.180423, 0,
    0.212671, 0.715160, 0.072169, 0,
    0.019334, 0.119193, 0.950227, 0)
pil_im = Image.open('sun.jpg').convert("RGB", rgb2xyz)
plt.imshow(pil_im)

在这里插入图片描述

1.1.1 转换图像格式

from PIL import Image
import os
filelist=['sun.jpg']
for infile in filelist:
    outfile =os.path.splitext(infile)[0]+'.jpg'
    if infile!=outfile:
        try:
            Image.open(infile).save(outfile)
        except IOError:
            print('cannot convert',infile)

可以返回目录中所有jpg图像的列表

def get_imlist(path):
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.JPG')]
get_imlist(r'D:\20计本二班照片')

在这里插入图片描述

1.1.2 创建缩略图

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
pil_im=Image.open('sun.jpg')
pil_im.thumbnail((128,128))
plt.imshow(pil_im)

在这里插入图片描述

1.1.3 复制和粘贴图像区域

from PIL import Image
import matplotlib.pyplot as plt
pil_im=Image.open('sun.jpg')
box=(200,200,974,974)  # 四元组的坐标依次是(左,上,右,下),表示从左上裁切到右下
region=pil_im.crop(box)
plt.imshow(region)

在这里插入图片描述

region=region.transpose(Image.ROTATE_180)   #将图片旋转180°
pil_im.paste(region,box)
plt.imshow(region)

在这里插入图片描述

1.1.4 调整尺寸和旋转

from PIL import Image
import matplotlib.pyplot as plt
pil_im=Image.open('sun.jpg')
out=pil_im.resize((256,256))
plt.subplot(121)
plt.imshow(out)

out=pil_im.rotate(45)
plt.subplot(122)
plt.imshow(out)

在这里插入图片描述

1.2 Matplotlib

1.2.1绘制图像、点和线

  • 点的颜色(加粗为颜色简写):blue,green,red,cyan(青色),magenta(品红),yellow,black,white
  • 线的类型:‘-’ 实线,'–‘虚线,’:'点线
  • 点的形状:'.'点,'o’圆圈,‘s’正方形,’*‘星形,’+'加号,'x’叉号
from PIL import Image
from pylab import *
im=array(Image.open('sun.jpg'))#读取图像到数组中
imshow(im)
x=[200,100,1000,1000]
y=[800,500,200,500]

plot(x,y,'r*')
plot(x[:2],y[:2],':')
title('Plotting:"sun.jpg"')

在这里插入图片描述

1.2.2 图像轮廓和直方图

from PIL import Image
from pylab import *
im=array(Image.open('sun.jpg').convert('L'))
figure() # 保留图像显示,不进行覆盖
gray() # 不使用颜色信息
contour(im,origin='image') #设置origin='image'确保图像数据的原点在左上角
axis('equal')
axis('off')

在这里插入图片描述

图像像素值被分成128个区间,用于计算每个区间的像素值频率

figure()
hist(im.flatten(),128)  #flatten()把二维图像数组展品为一维数组
show()

在这里插入图片描述

1.3 Numpy

1.3.1 图像数组表示

from PIL import Image
from pylab import *
im=array(Image.open('sun.jpg'))
print(im.shape,im.dtype)

im=array(Image.open('sun.jpg').convert('L'),'f') # 对图像进行灰度值处理后,并转换为浮点型数值
print(im.shape,im.dtype)
imshow(im)

在这里插入图片描述

im=array(Image.open('sun.jpg').convert('L'),'f')
im[100:200,:]=im[0:100,:] # 将100-200行所有元素替换成0-100行的所有元素
imshow(im)

在这里插入图片描述

im=array(Image.open('sun.jpg').convert('L'),'f')
im[0:100,:]=0# 将0-100行的所有数值设为0
imshow(im)

print(im[:100,:50].sum())#因为刚刚把值全部设为了0,所以求和完还是0
print('--------')
print(im[100:200,:50].sum())
print('--------')
print(im[50:150,50:100])
print('--------')
print(im[101].mean())#均值

在这里插入图片描述

在这里插入图片描述

1.3.2灰度变换

from PIL import Image
from numpy import *
im=array(Image.open('sun.jpg').convert('L'))
im2=255-im # 对图像进行反向处理
im3=(100.0/255)*im+100 # 将图像像素值变换到100-200区间,im/255为归一化,最后100.0*(im/255)化为100中所对应的数值
im4=255.0*(im/255.0)**2# 对图像像素值求平方后得到的图像,使较暗的像素值变得更小,明暗区别程度更大
subplot(221)
imshow(im)
subplot(222)
imshow(im2)
subplot(223)
imshow(im3)
subplot(224)
imshow(im4)

在这里插入图片描述

1.3.3 图像缩放

from PIL import Image
from numpy import *
def imresize(im,sz):
    pil_im=Image.fromarray(uint8(im)) #把图像数组转换为图像
    return array(pil_im.resize(sz))

im=array(Image.open('sun.jpg').convert('L'))
new_size = (400, 300)#(长、宽)
new_im=imresize(im,new_size)
imshow(new_im)

在这里插入图片描述

1.3.4 直方图均衡化

from PIL import Image
from numpy import *
import matplotlib.pyplot as plt
def histeq(im,nbr_bins=256):
    #flatten()展平数组
    # nbr_bins:指定区间数量,这里指定直方图需要划分为256个区间

    # histogram函数返回两个参数
    # 1.imhist:一个一维数组,表示每个区间中的数据频数。
    # 2.bins:一个一维数组,表示直方图区间的边界值。
    imhist,bins=histogram(im.flatten(),nbr_bins,density=True)
    cdf=imhist.cumsum() # 计算累积分布函数 (CDF)

    # cdf:累积分布函数值,表示像素值小于或等于某—灰度值的概率。
    # cdf[-1]:累积分布函数的最大值。对于归一化的CDF,这个值通常是1;对于非归一化的CDF,这个值通常是数据的总数(像素的总数)。
    cdf=255*cdf/cdf[-1]#将CDF的值映射到0到255的范围,以便用于灰度图像的均衡化。

    # interp():用于执行一维线性插值。
    # im.flatten():需要插值的点
    # bins[:-1] 则是每个直方图区间的左边界(不包括最后一个边界)。表示每个区间的起始值,所以就是对应的横坐标
    # cdf为对应的纵坐标
    im2=interp(im.flatten(),bins[:-1],cdf)
    return im2.reshape(im.shape),cdf,bins
im=array(Image.open('sun.jpg').convert('L'))
figure()
subplot(121)
#bins:将数据分成30个箱子(区间);alpha:设置图形的透明度(0 是完全透明,1 是完全不透明)
plt.hist(im, bins=30, alpha=0.5)

subplot(122)
imshow(im)

figure()
im2,cdf,bins=histeq(im)
# print(cdf)
plt.plot(bins[1:], cdf, marker='.', linestyle='none')

figure()
subplot(121)
plt.hist(im2, bins=30, alpha=0.5)

subplot(122)
imshow(im2)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.3.5 图像平均

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)
    return array(averageim,'uint8')

1.3.6 图像的主成分分析(PCA)

from PIL import Image
from numpy import *
from pylab import *
import os
import matplotlib.pyplot as plt
def pca(X):
    # num_data:样本数量;dim:特征维数(列数)
    # 2359×625:有2359张图片,因为每张图片为25×25,所以压平后的长度就是625
    num_data,dim=X.shape
    # mean_X:计算每个特征的均值,axis=0表示按列计算
    mean_X=X.mean(axis=0)  #矩阵大小:1×625

    # 对数据进行中心化,即减去均值
    X=X-mean_X
    
    if dim>num_data:         # 如果特征维数大于样本数量,使用协方差矩阵
        M=dot(X,X.T)         #计算协方差矩阵
        # M=cov(X,rowvar=0)      #等效计算协方差矩阵,rowvar=0表示每一列是一个变量,每一行是一个观测值(rowvar=1表示每一行是一个变量,每一列是一个观测值)
        
        e,EV=linalg.eigh(M)  #特征值分解,e是特征值,EV是特征向量
        
        tmp=dot(X.T,EV).T    #计算主成分
        V=tmp[::-1]          #对主成分进行排序(按特征值的降序)
        S=sqrt(e)[::-1]      #计算特征值的平方根,并进行排序
        for i in range(V.shape[1]):#对V进行归一化,使其成为单位特征向量
            V[:,i]/=S
    else:    # 否则使用奇异值分解(SVD)的方法
        U,S,V=linalg.svd(X)  #奇异值分解,U和V是左右奇异向量,S是奇异值
        V=V[:num_data]       #主成分,提取前num_data个主成分
    return V,S,mean_X
  • 当特征维数小于样本数量时,使用SVD分解
    • 一个矩阵X,在本例中维数为2359×625,SVD 将其分解为: X = [ U S V T ] {\rm X}=[{\rm USV^T} ] X=[USVT]
      其中:
      • U:一个2359×2359的正交矩阵,包含左奇异向量。
      • S:一个2359×625 的对角矩阵,其中对角线上的值是奇异值,按降序排列。奇异值是矩阵X的平方根的特征值。
      • V T {\rm V^T} VT:一个625×625的正交矩阵的转置,包含右奇异向量。
# 可以返回目录中所有jpg图像的列表
def get_imlist(path):
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]
imlist=get_imlist(r'D:\pyFile\Python计算机视觉编程\data\fontimages\a_thumbs')
im=array(Image.open(imlist[0]))
m,n=im.shape#获取图像的大小 25×25
imnbr=len(imlist)#获取图像的数目

immatrix=array([array(Image.open(im)).flatten() for im in imlist],'f')#创建矩阵,保存所有压平后的图像数据
V,S,immean=pca(immatrix)
figure()
gray()
subplot(241)
imshow(immean.reshape(m,n))
axis('off')
for i in range(7):
    subplot(2,4,i+2)
    imshow(V[i].reshape(m,n))
    axis('off')
show()

在这里插入图片描述

1.3.7 使用pickle模块

import pickle
f=open('font_pca_modes.pkl','wb')
pickle.dump(immean,f)
pickle.dump(V,f)
f.close()

等价于

with open('font_pca_modes.pkl','wb') as f:
    pickle.dump(immean,f)
    pickle.dump(V,f)
f=open('font_pca_modes.pkl','rb')
immean=pickle.load(f)
V=pickle.load(f)
f.close()

等价于

with open('font_pca_modes.pkl','rb') as f:
    immean=pickle.load(f)
    V=pickle.load(f)

1.4 SciPy

1.4.1 图像模糊

from PIL import Image
from numpy import *
from scipy.ndimage import filters
import matplotlib.pyplot as plt
im=array(Image.open('sun.jpg').convert('L'))
im2=filters.gaussian_filter(im,5)#标准差为5

plt.figure()
plt.imshow(im)
plt.figure()
plt.imshow(im2)

在这里插入图片描述

im=array(Image.open('sun.jpg'))
im2=zeros(im.shape)
for i in range(3):#彩色图像则是对三个通道分别进行模糊
    im2[:,:,i]=filters.gaussian_filter(im[:,:,i],5)
im2=uint8(im2)
plt.imshow(im2)

在这里插入图片描述

1.4.2 图像导数

from PIL import Image
from numpy import *
from scipy.ndimage import filters
import matplotlib.pyplot as plt
Sobel导数滤波器
im=array(Image.open('sun.jpg').convert('L'))
plt.figure()
plt.imshow(im)
#Sobel导数滤波器
imx=zeros(im.shape)
filters.sobel(im,1,imx)

imy=zeros(im.shape)
filters.sobel(im,0,imy)

magnitude=sqrt(imx**2+imy**2)

plt.figure()
plt.subplot(121)
plt.imshow(imx)

plt.subplot(122)
plt.imshow(imy)

plt.figure()
plt.imshow(magnitude)

在这里插入图片描述

在这里插入图片描述

高斯滤波器
  • 高斯滤波器通过卷积操作将高斯函数应用于图像,从而实现平滑效果。在代码中,filters.gaussian_filter被用于计算图像的梯度。下面详细介绍函数的参数
  • filters.gaussian_filter(im,(sigma,sigma),(0,1),imx)
    • 第二个参数可以是一个标量或元组。它决定了滤波器的平滑程度。
      • 如果是一个标量,表示在所有维度上使用相同的标准差;
      • 如果是一个元组,可以为不同的维度指定不同的标准差。(sigma, sigma)表示在两个维度上都使用标准差 sigma。
    • 第三个参数是指定对每个方向计算哪种类型的导数。在这里指:滤波器在x方向上应用,而在y方向上不应用。
def gaussianFilter(sigma):
    plt.figure()
    imx=zeros(im.shape)  # 创建一个与输入图像im形状相同的零数组imx。这个数组将用于存储图像在x方向上的梯度信息。
    filters.gaussian_filter(im,(sigma,sigma),(0,1),imx)

    imy=zeros(im.shape)
    filters.gaussian_filter(im,(sigma,sigma),(1,0),imy)
    plt.title('sigma=%d Gaussian filter result' % sigma)
    plt.axis('off')
    plt.subplot(121)
    plt.imshow(imx)
    plt.subplot(122)
    plt.imshow(imy)
gaussianFilter(2)
gaussianFilter(5)
gaussianFilter(10)

参数sigma为标准差(σ),是高斯滤波器的一个重要参数,它控制滤波器的平滑程度。标准差越大,高斯函数的曲线越宽,滤波器的影响范围就越大。

标准差较小: 高斯滤波器会产生较小范围的平滑效果,图像的细节保留更多。

标准差较大: 高斯滤波器会在更大范围内进行平滑,使得图像变得更加模糊,细节和边缘特征会被更强地平滑掉。

  1. 卷积操作: 高斯滤波器通过卷积操作应用于图像。卷积操作将高斯函数应用于图像的每一个像素,以计算新像素值。对于每个像素,卷积操作涉及将高斯函数的加权平均值与周围像素进行计算。
  2. 平滑效果: 高斯滤波器的作用是将图像中每个像素的值替换为其周围像素的加权平均值。权重由高斯函数决定,因此离中心像素越远的像素权重越小。这种方式平滑了图像,并减少了噪声。

在这里插入图片描述

在这里插入图片描述

1.4.3 形态学:对象计数

from scipy.ndimage import measurements,morphology
import matplotlib.pyplot as plt
im=array(Image.open('D:\pyFile\Python计算机视觉编程\data\houses.png').convert('L'))
plt.figure()
plt.imshow(im, cmap='gray')
im=1*(im<128)#通过与1相乘,转换成二进制表示

# 对二值图像进行标记。该函数返回两个值:
# labels:一个与输入图像同样大小的数组,其中每个连通区域都有一个唯一的标签。
# nbr_objects: 图像中连通区域的数量。
labels,nbr_objects=measurements.label(im)

plt.figure()
plt.imshow(im, cmap='gray') #使用灰度颜色映射显示二值图像。
plt.title(f'Number of objects: {nbr_objects}')
plt.show()

在这里插入图片描述

plt.subplot(121)
plt.imshow(im, cmap='gray') #使用灰度颜色映射显示二值图像。
plt.title(f'Number of objects: {nbr_objects}')
# 形态学开操作更好的分离各个对象
# iterations为迭代次数
# ones((9,5)):创建一个9行5列的结构元素,作为开操作中的腐蚀和膨胀的形状。
im_open=morphology.binary_opening(im,ones((9,5)),iterations=2)

labels_opens,nbr_objects_open=measurements.label(im_open)
print("Number of objects:",nbr_objects_open)
plt.subplot(122)
plt.title(f'Number of objects: {nbr_objects_open}')
plt.imshow(im_open, cmap='gray')

1.5高级示例:图像去噪

from numpy import *
from scipy.ndimage import filters
import matplotlib.pyplot as plt
def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
    m,n=im.shape  #获取图像的高度和宽度
    
    #初始化
    U=U_init
    Px=im      # 对偶域的x分量
    Py=im      # 对偶域的y分量
    error=1
    while(error>tolerance):
        Uold=U

        #原始变量的梯度
        GradUx=roll(U,-1,axis=1)-U       #变量U梯度的x分量
        GradUy=roll(U,-1,axis=0)-U       #变量U梯度的y分量

        #更新对偶变量
        PxNew=Px+(tau/tv_weight)*GradUx  #更新Px
        PyNew=Py+(tau/tv_weight)*GradUy  #更新Py
        NormNew=maximum(1,sqrt(PxNew**2+PyNew**2))#计算PxNew和PyNew的范数,确保其最小值为1

        
        Px=PxNew/NormNew    #更新x分量
        Py=PyNew/NormNew    #更新y分量
        
        RxPx=roll(Px,1,axis=1)#计算Px在x方向上的右移
        RyPy=roll(Py,1,axis=0)#计算Px在y方向上的下移
        
        DivP=(Px-RxPx)+(Py-RyPy)#计算Px和Py的梯度
        
        U=im+tv_weight*DivP # 更新去噪后的图像U
        
        error=linalg.norm(U-Uold)/sqrt(n*m)# 计算当前误差
    return U,im-U            #返回去噪后的图像U和噪声图像
im=zeros((500,500))
im[100:400,100:400]=128
im[200:300,200:300]=255
im=im+30*random.standard_normal((500,500))

plt.subplot(131)
plt.imshow(im)

U,T=denoise(im,im)
G=filters.gaussian_filter(im,10)

plt.subplot(132)
plt.imshow(G)
plt.subplot(133)
plt.imshow(U)
plt.subplots_adjust(wspace=0.4)  #调整子图之间的水平间距

在这里插入图片描述

from PIL import Image
from pylab import *
im=array(Image.open('D:\pyFile\Python计算机视觉编程\data\empire.jpg').convert('L'))
U,T=denoise(im,im)
subplot(131)
imshow(im)
axis('off')
gray()

G=filters.gaussian_filter(im,5)
subplot(132)
imshow(G)
axis('off')

subplot(133)
imshow(U)
axis('off')
show()

在这里插入图片描述

标签:plt,python,imshow,Image,编程,im,图像,import,视觉
From: https://blog.csdn.net/m0_53694086/article/details/141570994

相关文章

  • 滚雪球学Java(91):Java GUI编程实战:精通组件开发技巧,真有点东西!
      咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及JavaSE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~......
  • 【网络编程通关之路】 Udp 基础回显服务器(Java实现)及你不知道知识原理详解 ! ! !
    本篇会加入个人的所谓鱼式疯言❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言而是理解过并总结出来通俗易懂的大白话,小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.......
  • 战争密码 Python实现二战德军恩格玛机(Enigma)
    战争密码Python实现二战德军恩格玛机(Enigma)恩格玛机原理介绍转轮类的实现恩格玛机类的实现加解密类的实现加密解密完整代码加密代码解密代码注意恩格玛机原理介绍恩格玛机,在密码学史中通常被称为恩尼格玛密码机(Enigma),是一种用于加密与解密文件的密码机。它最早......
  • python基础(10异常处理)
    python系列文章目录python基础(01变量&数据类型&运算符)python基础(02序列共性)python基础(03列表和元组)python基础(04字符串&字典)python基础(05集合set)python基础(06控制语句)python基础(07函数)python基础(08类和对象)python基础(09闭包&装饰器)文章目录python系列文章目......
  • 06、Python爬虫——前端JS相关知识(一)
    前端JS相关三元运算v1=条件?值A:值B;res=1===1?99:88#res=99如果条件成立则返回冒号前的那个值,如果条件不成立则返回冒号后面那个值 特殊的逻辑运算v1=1===1||2===2这种运算是比较运算+或运算,在或(||)的前面和后面都是比较运算,前后的返回值都是ture......
  • python实例演示贝叶斯定理在机器学习中的应用
    贝叶斯定理是一种概率论中的基本公式,用于计算在已知条件下事件发生的概率。它的通俗解释可以理解为:当你获得新信息时,如何更新对某个事件发生概率的判断。贝叶斯定理公式贝叶斯定理的数学表达式是:P(A∣B)=P(B∣A)⋅P(A)P(B)P(A|B)=\frac{P(B|A)\cdotP(A)}{P(B)}P(A∣B)=P......
  • 加减法| python矩阵运算(学习笔记一)
    python的数学运算部分基本都在使用numpy模块,如果初次使用python,安装该模块最简单的办法就是:搜索框输入cmd打开命令提示符,输入以下代码等待安装即可。pipinstallnumpy如果不确定是否安装好,打开pycharm(此处默认为已经安装该软件),输入以下代码:importnumpyasnp之后即可定......
  • python+flask计算机毕业设计电影网站系统(程序+开题+论文)
    文件加密系统的设计与实现tp835本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,网络娱乐已成为人们日常生活中不可或缺的一部分,其中电影作为重要的文化娱乐形式,......
  • python+flask计算机毕业设计高校宿舍信息管理系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着高等教育的普及与校园规模的不断扩大,高校宿舍作为学生日常生活与学习的重要场所,其管理效率与质量直接关系到学生的安全、健康及学习环......
  • python+flask计算机毕业设计高校科研申报系统(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着高等教育事业的蓬勃发展,高校科研活动日益频繁且复杂多样,成为推动科技进步和社会发展的重要力量。然而,传统的科研申报与管理模式往往依......