欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > python计算机视觉编程第一章——基本的图像操作和处理

python计算机视觉编程第一章——基本的图像操作和处理

2024/10/26 6:19:14 来源:https://blog.csdn.net/qq_67725022/article/details/141526727  浏览:    关键词:python计算机视觉编程第一章——基本的图像操作和处理

一、PIL: Python图像处理类库 

from PIL import Image
from matplotlib import pyplot as plt
img = Image.open(r'eye.jpg') # 打开图片img1 = Image.open(r'eye.jpg').convert('L') # 转换为灰度图img2 = Image.open(r'eye.jpg')
img2.thumbnail((50, 100)) # 生成大小为100*100的缩略图img3 = img.crop((50, 50, 150, 150)) # 剪切图片img4 = Image.open(r'eye.jpg')
region = img3.rotate(180)
img4.paste(region,(50, 50, 150, 150))# 旋转180度放回img5 = img.resize((128,128)) # 调整尺寸plt.rcParams['font.sans-serif'] = ['SimHei']# 用来设置字体样式以正常显示中文标签
plt.subplot(231), plt.imshow(img), plt.title('原始图像'), plt.axis('off')
plt.subplot(232), plt.imshow(img1, plt.cm.gray), plt.title('灰度图像'), plt.axis('off')
plt.subplot(233), plt.imshow(img2), plt.title('缩略图'), plt.axis('off')
plt.subplot(234), plt.imshow(img3), plt.title('剪切图片'), plt.axis('off')
plt.subplot(235), plt.imshow(img4), plt.title('旋转180度后放回图像'), plt.axis('off')
plt.subplot(236), plt.imshow(img5), plt.title('调整尺寸后图像'), plt.axis('off')
plt.show()

二、Matplotlib

1绘制图像、点和线

from PIL import Image
from pylab import *img = array(Image.open(r'eye.jpg'))imshow(img)  # 绘制图像
# 设置点
x = [100, 100, 300, 300]
y = [50, 200, 50, 200]plot(x[:2], y[:2], 'r*')  # 前两点使用红色星状标记绘制点# 绘制连接前两个点的线
plot(x[:2], y[:2])  # 默认为蓝色实线
plot(x[1:3], y[1:3],'g--')   # 绿线虚线
plot(x[2:4], y[2:4],'ks:')   # 带有正方形标记的黑色点线plt.axis('off')  # 不显示坐标轴title('plotting:"eye.jpg"')
show()

2图像轮廓和直方图

from PIL import Image
import numpy as np
from pylab import pltimg = Image.open(r'eye.jpg')
img = img.convert('L')
img = np.array(img)plt.figure(figsize=(10, 5))plt.subplot(121)
plt.gray()
plt.contour(img, origin='image')
plt.title('contour Image')
plt.axis('off')plt.subplot(122)
plt.hist(img.flatten(), 128)
plt.title('Histogram')
plt.xlabel('Pixel Intensity')
plt.ylabel('Frequency')
plt.xlim([0, 256])
plt.show()

3交互式标注

from PIL import Image
from pylab import *im = array(Image.open('eye.jpg'))
imshow(im)
print('Please click 3 points')
x = ginput(3)
print('you clicked:',x)
show()

 三、NumPy

1图像数组表示

im = array(Image.open('eye.jpg'))
print(im.shape, im.dtype)im = array(Image.open('eye.jpg').convert('L'),'f')
print(im.shape, im.dtype)

 

每行的第一个元组表示图像数组的大小(行、列、颜色通道),紧接着的字符串表示数组元素的数据类型。图像通常被编码成无符号八位整数(uint8)。在第二种情况下,对图像进行灰度化处理,并且在创建数组时使用额外的参数“f”;该参数将数据类型转换为浮点型。由于灰度图像没有颜色信息,所以在形状元组中,它只有两个数值。 

数组中的元素可以使用下标访问。位于坐标i、j,以及颜色通道k的像素值可以像下面这样访问:

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 列(不包括第 100 行和第 100 列)
im[i].mean()           # 第 i 行所有数值的平均值
im[:,-1]               # 最后一列
im[-2,:] (or im[-2])   # 倒数第二行

 2灰度变换

from PIL import Image
from matplotlib import pyplot as plt
import numpy as npim = Image.open(r'eye.jpg').convert('L')
im = np.array(im)im2 = 255 - im # 对图像进行反相处理
im3 = (100.0/255) * im + 100 # 将图像像素值变换到100...200 区间
im4 = 255.0 * (im/255.0)**2 # 对图像像素值求平方后得到的图像plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(141), plt.imshow(im, plt.cm.gray), plt.title('原始灰度图像'), plt.axis('off')
plt.subplot(142), plt.imshow(im2, plt.cm.gray), plt.title('反向处理'), plt.axis('off')
plt.subplot(143), plt.imshow(im3, plt.cm.gray), plt.title('区间变换'), plt.axis('off')
plt.subplot(144), plt.imshow(im4, plt.cm.gray), plt.title('求平方'), plt.axis('off')
plt.show()
# 查看图像中的最小和最大像素值
print(int(im.min()), int(im.max()))
print(int(im2.min()), int(im2.max()))
print(int(im3.min()), int(im3.max()))
print(int(im4.min()), int(im4.max()))

变换函数图像:

最大值和最小值: 

3图像缩放

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

 4直方图均衡化

def histeq(im,nbr_bins=256):""" 对一幅灰度图像进行直方图均衡化"""# 计算图像的直方图imhist,bins = histogram(im.flatten(),nbr_bins,density=True)cdf = imhist.cumsum() # cumulative distribution functioncdf = 255 * cdf / cdf[-1] # 归一化# 使用累积分布函数的线性插值,计算新的像素值im2 = interp(im.flatten(),bins[:-1],cdf)return im2.reshape(im.shape), cdfim = array(Image.open('eye.jpg').convert('L'))
im2, cdf = histeq(im)plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221), plt.imshow(im, plt.cm.gray), plt.title('原始灰度图像'), plt.axis('off')
plt.subplot(222), plt.imshow(im2, plt.cm.gray), plt.title('直方图均衡化后图像'), plt.axis('off')
plt.subplot(223), plt.hist(im.flatten(), 128), plt.title('原始灰度图像直方图'), plt.xlabel('Pixel Intensity'), plt.ylabel('Frequency'), plt.xlim([0, 256])
plt.subplot(224), plt.hist(im2.flatten(), 128), plt.title('直方图均衡化后图像直方图'), plt.xlabel('Pixel Intensity'), plt.ylabel('Frequency'), plt.xlim([0, 256])
plt.show()

 错误:

原文:
imhist, bins = np.histogram(img.flatten(), nbr_bins, normed=True)报错:
TypeError: histogram() got an unexpected keyword argument 'normed'原因:
numpy.histogram函数中的normed参数在NumPy版本1.21.0中被弃用,并在版本1.24.0中被删除。改为:
imhist, bins = np.histogram(img.flatten(), nbr_bins, density=True)

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)# 返回uint8 类型的平均图像return array(averageim, 'uint8')

 该函数可以自动跳过不能打开的图像。

还可以使用 mean() 函数计算平均图像。mean() 函数需要将所有的图像堆积到一个数组中;也就是说,如果有很多图像,该处理方式需要占用很多内存。

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

PCA(Principal Component Analysis,主成分分析)是一个非常有用的降维技巧。在使用尽可能少维数的前提下,尽量多地保持训练数据的信息。一兆像素的图像具有百万维。由于图像具有很高的维数,在许多计算机视觉应用中,我们经常使用降维操作。PCA 产生的投影矩阵可以被视为将原始坐标变换到现有的坐标系,坐标系中的各个坐标按照重要性递减排列。

将变平的图像堆积起来,我们可以得到一个矩阵,矩阵的一行表示一幅图像。在计算主方向之前,所有的行图像按照平均图像进行了中心化。我们通常使用 SVD(Singular Value Decomposition,奇异值分解)方法来计算主成分;但当矩阵的维数很大时,SVD 的计算非常慢,所以此时通常不使用 SVD 分解。

import os
from PIL import Image
from numpy import *
from pylab import *def pca(X):""" 主成分分析:输入:矩阵X ,其中该矩阵中存储训练数据,每一行为一条训练数据返回:投影矩阵(按照维度的重要性排序)、方差和均值"""# 获取维数num_data,dim = X.shape# 数据中心化mean_X = X.mean(axis=0)X = X - mean_Xif dim > num_data :# PCA- 使用紧致技巧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] /= Selse:# PCA- 使用SVD 方法U,S,V = linalg.svd(X)V = V[:num_data] # 仅仅返回前nun_data 维的数据才合理# 返回投影矩阵、方差和均值return V,S,mean_Xdef get_imlist(path):return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.png')]imlist = get_imlist('mnist_train/0/')
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(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()

 7使用pickle模块

pickle模块可以接受几乎所有的 Python 对象,并且将其转换成字符串表示,该过程叫做封装(pickling)。从字符串表示中重构该对象,称为拆封(unpickling)。这些字符串表示可以方便地存储和传输。 

# 保存均值和主成分数据
f = open('font_pca_modes.pkl', 'wb')
pickle.dump(immean,f)
pickle.dump(V,f)
f.close()# 载入均值和主成分数据
f = open('font_pca_modes.pkl', 'rb')
immean = pickle.load(f)
V = pickle.load(f)
f.close()print(immean)

保存: 

读取: 

在本书接下来的章节中,我们将使用 with 语句处理文件的读写操作。可以自动打开和关闭文件(即使在文件打开时发生错误) 

# 打开文件并保存
with open('font_pca_modes.pkl', 'wb') as f:pickle.dump(immean,f)pickle.dump(V,f)# 打开文件并载入
with open('font_pca_modes.pkl', 'rb') as f:immean = pickle.load(f)V = pickle.load(f)

如果数据中不包含复杂的数据结构,比如在一幅图像上点击的点列表,NumPy 的读写函数会很有用。保存一个数组 x 到文件中 

#保存
savetxt('test.txt',x,'%i')
#读取
x = loadtxt('test.txt')

 四、SciPy

SciPy 提供很多高效的操作,可以实现数值积分、优化、统计、信号处理,以及图像处理功能。

1图像模糊

图像的 高斯模糊是非常经典的图像卷积例子。通常是其他图像处理操作的一部分,比如图像插值操作、兴趣点计算以及 很多其他应用。
黑白图像:
from PIL import Image
from numpy import *
from scipy.ndimage import filtersfrom matplotlib import pyplot as pltim = array(Image.open('eye.jpg').convert('L'))
im2 = filters.gaussian_filter(im,2)
im3 = filters.gaussian_filter(im,5)
im4 = filters.gaussian_filter(im,10)plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(141), plt.imshow(im, plt.cm.gray), plt.title('原始灰度图像'), plt.axis('off')
plt.subplot(142), plt.imshow(im2, plt.cm.gray), plt.title('σ=2高斯滤波器'), plt.axis('off')
plt.subplot(143), plt.imshow(im3, plt.cm.gray), plt.title('σ=5高斯滤波器'), plt.axis('off')
plt.subplot(144), plt.imshow(im4, plt.cm.gray), plt.title('σ=10高斯滤波器'), plt.axis('off')plt.show()

彩色图像: 

im = array(Image.open('eye.jpg'))
im2 = zeros(im.shape)
for i in range(3):im2[:,:,i] = filters.gaussian_filter(im[:,:,i],5)
im2 = uint8(im2)

2图像导数

强度的 变化可以用灰度图像 I (对于彩色图像,通常对每个颜色通道分别计算导数)的 x y 方向导数I_{x}I_{y} 进行描述。
from PIL import Image
from numpy import *
from scipy.ndimage import filters
from matplotlib import pyplot as pltim = array(Image.open('eye.jpg').convert('L'))
# 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.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(141), plt.imshow(im, plt.cm.gray), plt.title('原始灰度图像'), plt.axis('off')
plt.subplot(142), plt.imshow(imx, plt.cm.gray), plt.title('x导数图像'), plt.axis('off')
plt.subplot(143), plt.imshow(imy, plt.cm.gray), plt.title('y导数图像'), plt.axis('off')
plt.subplot(144), plt.imshow(magnitude, plt.cm.gray), plt.title('梯度大小图像'), plt.axis('off')plt.show()

3形态学:对象计数

from scipy.ndimage import measurements,morphology
from PIL import Image
from matplotlib import pyplot as plt
from numpy import *
# 载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
im = array(Image.open('ta.jpg').convert('L'))
im = 1*(im<128)
labels, nbr_objects = measurements.label(im)
print("Number of objects:", nbr_objects)# 形态学开操作更好地分离各个对象
im_open = morphology.binary_opening(im,ones((9,5)),iterations=2)
labels_open, nbr_objects_open = measurements.label(im_open)
print("Number of objects:", nbr_objects_open)plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(221), plt.imshow(im, plt.cm.gray), plt.title('二值化图像'), plt.axis('off')
plt.subplot(222), plt.imshow(labels, plt.cm.gray), plt.title('labels数组图像'), plt.axis('off')
plt.subplot(223), plt.imshow(im_open, plt.cm.gray), plt.title('开操作后图像'), plt.axis('off')
plt.subplot(224), plt.imshow(labels_open, plt.cm.gray), plt.title('开操作后labels数组图像'), plt.axis('off')
plt.show()

五、高级示例:图像去噪

图像去噪是在去除图像噪声的同时,尽可能地保留图像细节和结构的处理技术。我们这里使用ROF(Rudin-Osher-Fatemi)去噪模型。图像去噪对于很多应用来说都非常重要;这些应用范围很广,小到让你的假期照片看起来更漂亮,大到提高卫星图像的质量。ROF模型具有很好的性质:使处理后的图像更平滑,同时保持图像边缘和结构信息。

from numpy import *
from numpy import random
from scipy.ndimage import filters
import rof
from matplotlib import pyplot as plt
# 使用噪声创建合成图像
im = zeros((500,500))
im[100:400,100:400] = 128
im[200:300,200:300] = 255
im = im + 30*random.standard_normal((500,500))
U,T = rof.denoise(im,im)
G = filters.gaussian_filter(im,10)plt.rcParams['font.sans-serif'] = ['SimHei']
plt.subplot(131), plt.imshow(im, plt.cm.gray), plt.title('原始图像'), plt.axis('off')
plt.subplot(132), plt.imshow(G, plt.cm.gray), plt.title('经过高斯模糊后图像'), plt.axis('off')
plt.subplot(133), plt.imshow(U, plt.cm.gray), plt.title('经过 ROF 模型去噪后图像'), plt.axis('off')
plt.show()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com