当前位置:   article > 正文

Python计算机视觉编程 第一章——基本的图像操作和处理_array(image.open())

array(image.open())

目录

1.1 PIL:Python图像处理类库

1.1.1 转换图像格式

1.1.2 创建缩略图

1.1.3 复制和粘贴图像区域

1.1.4 调整尺寸和旋转

1.2 Matplotlib

1.2.1 绘制图像、点和线

1.2.2 图像轮廓和直方图

1.2.3 交互式标注

1.3 Unmpy

1.3.1 图像数组表示

1.3.2 灰度变换

1.3.3 图像缩放

1.3.4 直方图均衡化

1.3.5 图像平均

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

1.3.7 使用pickle模块

1.4 Scipy

1.4.1 图像模糊

1.4.2 图像导数

1.4.3 形态学:对数计数

1.4.4 一些有用的Scipy模块

1.读写.mat文件

2.以图像形式保存数组

1.5 高级示例:图像去噪


1.1 PIL:Python图像处理类库

读取一幅图像:

  1. from PIL import Image
  2. pil_im=Image.open('empire.jpg')

上述代码的返回值pil_im是一个PIL图像对象。

读取图像同时转化为灰度图像:

pil_im=Image.open('empire.jpg').convert('L')

1.1.1 转换图像格式

转换为JPEG格式:

  1. from PIL import Image
  2. import os
  3. for infile infilelist:
  4. outfile=os.path.splitext(infile)[0]+".jpg"
  5. if infile !=outfile:
  6. try:
  7. Image.open(infile).save(outfile)
  8. except IOError:
  9. print "cannot convert",infile

PIL的open()函数用于创建PIL图像对象,save()方法一用于保存图像到具有指定文件名的文件。

下面将创建一个包含文件夹中所有图像的文件名列表,首先新建一个文件,命名为imtools.py,来存储一些经常使用的图像操作,然后将下面的函数添加进去:

  1. import os
  2. def get_imlist(path):
  3. """ 返回目录中所有 JPG 图像的文件名列表 """
  4. return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]

1.1.2 创建缩略图

thumbnail()方法接受一个元组参数(该参数指定生成缩略图的大小),然后将图像转换成符合元组参数指定大小的缩略图。例如:

pil_im.thumbnail((128,128))

1.1.3 复制和粘贴图像区域

使用crop()方法可以从一幅图像中裁剪指定区域:

  1. box = (100,100,400,400)
  2. region = pil_im.crop(box)

改区域使用坐标依次是(左,上,右,下)的四元组来指定。PIL中指定坐标系的左上角坐标为(0,0)。旋转上面代码获取区域,然后使用paste()方法将该区域放回去:

  1. region = region.transpose(Image.ROTATE_180)
  2. pil_im.paste(region,box)

1.1.4 调整尺寸和旋转

调整图像尺寸:

out = pil_im.resize((128,128))

旋转图像:

out = pil_im.rotate(45)

1.2 Matplotlib

1.2.1 绘制图像、点和线

一个使用点和线绘制图像的例子:

  1. from PIL import Image
  2. from pylab import *
  3. # 读取图像到数组中
  4. im = array(Image.open(r'G:\1.jpg'))
  5. # 绘制图像
  6. imshow(im)
  7. # 一些点
  8. x = [1000,4000,1000,4000]
  9. y = [500,500,3000,3000]
  10. # 使用红色星状标记绘制点
  11. plot(x,y,'r*')
  12. # 绘制连接前两个点的线
  13. plot(x[:2],y[:2])
  14. # 添加标题,显示绘制的图像
  15. title('Plotting: "empire.jpg"')
  16. show()

每个脚本只能调用一次show()命令,而且通常是在脚本的结尾调用。

关闭坐标轴显示:

axis('off')

 绘图时控制图像颜色和样式的短命令:

  1. plot(x,y) # 默认为蓝色实线
  2. plot(x,y,'r*') # 红色星状标记
  3. plot(x,y,'go-') # 带有圆圈标记的绿线
  4. plot(x,y,'ks:') # 带有正方形标记的黑色虚线

1.2.2 图像轮廓和直方图

绘制图像轮廓:

  1. from PIL import Image
  2. from pylab import *
  3. # 读取图像到数组中
  4. im = array(Image.open('2.jpg').convert('L'))
  5. # 新建一个图像
  6. figure()
  7. # 不使用颜色信息
  8. gray()
  9. # 在原点的左上角显示轮廓图像
  10. contour(im, origin='image')
  11. axis('equal')
  12. show()

绘制图像直方图:

  1. figure()
  2. hist(im.flatten(),128)

hist()只接受一维数组作为输入,所以在绘制图像直方图之前,必须先对图像进行压平处理。

1.2.3 交互式标注

绘制一幅图像,然后等待用户点击三次,依序将这些点击的坐标[x,y]自动保存在x列表里:

  1. from PIL import Image
  2. from pylab import *
  3. im = array(Image.open('8.jpg'))
  4. imshow(im)
  5. print ('Please click 3 points')
  6. x = ginput(3)
  7. print ('you clicked:',x)
  8. show()

1.3 Unmpy

1.3.1 图像数组表示

Numpy中的数组对象是多维的,但是元素必须有相同的数据类型。

  1. im = array(Image.open('empire.jpg'))
  2. print im.shape, im.dtype
  3. im = array(Image.open('empire.jpg').convert('L'),'f')
  4. print im.shape, im.dtype

输出结果:

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

数组中的元素可以使用下标访问。i,j为坐标,k为颜色通道。

value = im[i,j,k]

多个数组元素可以使用数组切片方式访问。切片方式返回的是以指定间隔下标访问该数组的元素值。下面是有关灰度图像的一些例子:

  1. im[i,:] = im[j,:] # 将第 j 行的数值赋值给第 i 行
  2. im[:,i] = 100 # 将第 i 列的所有数值设为 100
  3. im[:100,:50].sum() # 计算前 100 行、前 50 列所有数值的和
  4. im[50:100,50:100] # 50~100 行,50~100 列(不包括第 100 行和第 100 列)
  5. im[i].mean() # 第 i 行所有数值的平均值
  6. im[:,-1] # 最后一列
  7. im[-2,:] (or im[-2]) # 倒数第二行

如果仅使用一个下标,则该下标为行下标。

1.3.2 灰度变换

下面是对一幅图像进行灰度变换的一些例子:

  1. from PIL import Image
  2. from numpy import *
  3. from pylab import *
  4. im=array(Image.open('14.jpg').convert('L'))
  5. print(int(im.min()),int(im.max()))
  6. im2=255-im #对图像进行反向处理
  7. print(int(im2.min()),int(im2.max())) #查看最大/最小元素
  8. im3=(100.0/255)*im+100 #将图像像素值变换到100...200区间
  9. print(int(im3.min()),int(im3.max()))
  10. im4=255.0*(im/255.0)**2 #对像素值求平方后得到的图像
  11. print(int(im4.min()),int(im4.max()))
  12. figure()
  13. gray()
  14. subplot(131)
  15. imshow(im2)
  16. axis('off')
  17. title(r'$f(x)=255-x$')
  18. subplot(132)
  19. imshow(im3)
  20. axis('off')
  21. title(r'$f(x)=\frac{100}{255}x+100$')
  22. subplot(133)
  23. imshow(im4)
  24. axis('off')
  25. title(r'$f(x)=255(\frac{x}{255})^2$')
  26. show()

图像中最大和最小像素值:

 array()变换的相反操作可以使用PIL的formarray()函数完成:

pil_im=Image.fromarray(im)

 如果之前的操作将“uint8”数据类型转换为其他数据类型,那么在创建PIL图像之前,需要将数据类型转换回来:

pil_im=Image.fromarray(uint8(im))

Numpy总是将数组数据类型转换成能够表示数据的“最低”数据类型。对浮点数做乘积或除法操作会使整数类型的数组变成点类型。

1.3.3 图像缩放

想要对图像进行缩放处理没有现成简单的方法。我们可以使用之前PIL对图像对象转换的操作,写一个简单的用于图像缩放的函数。

  1. def imresize(im,sz):
  2. """ Resize an image array using PIL. """
  3. pil_im = Image.fromarray(uint8(im))
  4. return array(pil_im.resize(sz))

1.3.4 直方图均衡化

直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。在对图像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。

直方图均衡化的变换函数是图像中像素值的累积分布函数:

  1. from PIL import Image
  2. from pylab import *
  3. from PCV.tools import imtools
  4. # 添加中文字体支持
  5. from matplotlib.font_manager import FontProperties
  6. font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
  7. im = array(Image.open('14.jpg').convert('L'))
  8. # 打开图像,并转成灰度图像
  9. #im = array(Image.open('../data/AquaTermi_lowcontrast.JPG').convert('L'))
  10. im2, cdf = imtools.histeq(im)
  11. figure()
  12. subplot(2, 2, 1)
  13. axis('off')
  14. gray()
  15. title(u'原始图像', fontproperties=font)
  16. imshow(im)
  17. subplot(2, 2, 2)
  18. axis('off')
  19. title(u'直方图均衡化后的图像', fontproperties=font)
  20. imshow(im2)
  21. subplot(2, 2, 3)
  22. axis('off')
  23. title(u'原始直方图', fontproperties=font)
  24. #hist(im.flatten(), 128, cumulative=True, normed=True)
  25. hist(im.flatten(), 128, density=True)
  26. subplot(2, 2, 4)
  27. axis('off')
  28. title(u'均衡化后的直方图', fontproperties=font)
  29. #hist(im2.flatten(), 128, cumulative=True, normed=True)
  30. hist(im2.flatten(), 128, density=True)
  31. show()

明显可以看出均衡化后的直方图有了明显变化,图像对比度也增加。此外,参考代码有一些改动:

normed=True

由于 Rectangle 这个库更新,现在已经没有normed属性了。需要将其改为如下形式:

density=True

1.3.5 图像平均

图像平均操作是减少图像噪声的一种简单方式。我们可以简单地从图像列表中计算出一幅平均图像。下面的函数可以用于计算平均图像,将其添加到文件中:

  1. def compute_average(imlist):
  2. """ 计算图像列表的平均图像"""
  3. # 打开第一幅图像,将其存储在浮点型数组中
  4. averageim = array(Image.open(imlist[0]), 'f')
  5. for imname in imlist[1:]:
  6. try:
  7. averageim += array(Image.open(imname))
  8. except:
  9. print imname + '...skipped'
  10. averageim /= len(imlist)
  11. # 返回uint8 类型的平均图像
  12. return array(averageim, 'uint8')

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

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

为了对图像数据进行 PCA 变换,图像需要转换成一维向量表示。我们可以使用 NumPy 类库中的flatten()方法进行变换。

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

该函数首先通过减去每一维的均值将数据中心化,然后计算协方差矩阵对应最大特征值的特征向量,此时可以使用简明的技巧或者 SVD 分解。这里我们使用了 range() 函数,该函数的输入参数为一个整数 n,函数返回整数 0…(n-1) 的一个列表。你也可以使用 arange() 函数来返回一个数组,或者使用 xrange() 函数返回一个产生器(可能会提升速度)。我们在本书中贯穿使用range() 函数。

如果数据个数小于向量的维数,我们不用 SVD 分解,而是计算维数更小的协方差矩阵 XXT 的特征向量。通过仅计算对应前 k(k 是降维后的维数)最大特征值的特征向量,可以使上面的 PCA 操作更快。由于篇幅所限,有兴趣的读者可以自行探索。矩阵 V 的每行向量都是正交的,并且包含了训练数据方差依次减少的坐标方向。

1.3.7 使用pickle模块

python中的pickle模块可以保存一些结果或者数据以便后续使用。pickle模块可以接受几乎所有的python对象,并且将其转换成字符串表示,这个过程叫做封装(pickling)。从字符串表示中重构该对象,称为拆封(unpickling)。这些字符串表示可以方便地存储和传输。

pickle模块中有很多不同的协议可以生成.pkl文件;如果不确定的话,最好以二进制文件的形式读取和写入。在其他python会话中载入数据,只需要使用load()方法。

with语句可以自动打开和关闭文件(即使在文件打开时发生错误)。

1.4 Scipy

1.4.1 图像模糊

图像的高斯模糊是非常经典的图像卷积例子。本质上,图像模糊就是将(灰度)图像I和一个高斯核进行卷积操作:

I_{\delta}=I * G_{\delta}

其中*表示卷积操作;Gδ是标准差为δ的二位高斯核,定义为:

G_{\sigma}=\frac{1}{2 \pi \sigma} \mathrm{e}^{-\left(x^{2}+y^{2}\right) / 2 \sigma^{2}}

高斯模糊通常是其他图像处理操作的一部分,比如图像差值操作、兴趣点计算以及其他应用。

滤波操作:scipy.ndimage.filters

  1. from PIL import Image
  2. from numpy import *
  3. from pylab import *
  4. from scipy.ndimage import filters
  5. # 添加中文字体支持
  6. from matplotlib.font_manager import FontProperties
  7. font=FontProperties(fname=r"c:\windows\fonts\SimSun.ttc",size=14)
  8. im=array(Image.open('14.jpg').convert('L'))
  9. figure()
  10. gray()
  11. axis('off')
  12. subplot(141)
  13. axis('off')
  14. title(u'原图',fontproperties=font)
  15. imshow(im)
  16. for bi,blur in enumerate([2,5,10]):
  17. im2=zeros(im.shape)
  18. im2=filters.gaussian_filter(im,blur)
  19. im2=np.uint8(im2)
  20. imNum=str(blur)
  21. subplot(1,4,2+bi)
  22. axis('off')
  23. title(u'标准差为'+imNum,fontproperties=font)
  24. imshow(im2)
  25. show()

随着δ值增加,图像逐渐变模糊,图像细节丢失越多。

1.4.2 图像导数

在很多应用中图像强度的变化情况是非常重要的信息。强度的变化可以用灰度图像I(对于彩色图像,通常对每个颜色通道分别计算导数)的x和y方向导数Ix和Iy进行描述。

梯度大小描述了图像强度变化的强弱:

|\nabla I|=\sqrt{I_{x}^{2}+I_{y}^{2}}

梯度角度描述了图像在每个点(像素)上强度变化最大的方向:

\alpha=\arctan 2\left(I_{x}, I_{y}\right)

Numpy中的arctan2()函数返回弧度表示的有符号角度,角度的变化区间为-π...π。

我们可以用离散近似的方式来计算图像的导数。图像导数大多数可以通过卷积简单地实现:

\boldsymbol{I}_{x}=\boldsymbol{I} * D_{x} ,\boldsymbol{I}_{y}=\boldsymbol{I} * D_{y}

prewitt滤波器:

D_{x}=\left[\begin{array}{rrr} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \end{array}\right] , D_{y}=\left[\begin{array}{rrr} -1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1 \end{array}\right]

或者sobel滤波器:

D_{x}=\left[\begin{array}{ccc} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{array}\right] , D_{y}=\left[\begin{array}{rrr} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{array}\right]

这些导数滤波器可以使用scipy.ndimage.filters模块的标准卷积操作来简单地实现,例如:

  1. from PIL import Image
  2. from pylab import *
  3. from scipy.ndimage import filters
  4. import numpy
  5. # 添加中文字体支持
  6. from matplotlib.font_manager import FontProperties
  7. font=FontProperties(fname=r"c:\windows\fonts\SimSun.ttc",size=14)
  8. im=array(Image.open('14.jpg').convert('L'))
  9. gray()
  10. subplot(141)
  11. axis('off')
  12. title(u'(a)原图',fontproperties=font)
  13. imshow(im)
  14. # sobel derivative filters
  15. imx=zeros(im.shape)
  16. filters.sobel(im,1,imx)
  17. subplot(142)
  18. axis('off')
  19. title(u'(b)x方向差分',fontproperties=font)
  20. imshow(imx)
  21. imy=zeros(im.shape)
  22. filters.sobel(im,0,imy)
  23. subplot(143)
  24. axis('off')
  25. title(u'(c)y方向差分',fontproperties=font)
  26. imshow(imy)
  27. mag=255-numpy.sqrt(imx**2+imy**2)
  28. subplot(144)
  29. title(u'(d)梯度幅值',fontproperties=font)
  30. axis('off')
  31. imshow(mag)
  32. show()

上面的脚本使用Sobel滤波器计算x和y方向导数以及梯度大小。在导数图像中,正导数显示为亮的像素,负倒数显示为暗的像素,灰色区域表示导数的值接近于零。 

高斯导数滤波器:

\boldsymbol{I}_{x}=\boldsymbol{I} * G_{\sigma x} ,\boldsymbol{I}_{y}=\boldsymbol{I} * G_{\sigma y}

  1. from PIL import Image
  2. from pylab import *
  3. from scipy.ndimage import filters
  4. import numpy
  5. # 添加中文字体支持
  6. #from matplotlib.font_manager import FontProperties
  7. #font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
  8. def imx(im, sigma):
  9. imgx = zeros(im.shape)
  10. filters.gaussian_filter(im, sigma, (0, 1), imgx)
  11. return imgx
  12. def imy(im, sigma):
  13. imgy = zeros(im.shape)
  14. filters.gaussian_filter(im, sigma, (1, 0), imgy)
  15. return imgy
  16. def mag(im, sigma):
  17. # there's also gaussian_gradient_magnitude()
  18. #mag = numpy.sqrt(imgx**2 + imgy**2)
  19. imgmag = 255 - numpy.sqrt(imgx ** 2 + imgy ** 2)
  20. return imgmag
  21. im = array(Image.open('14.jpg').convert('L'))
  22. figure()
  23. gray()
  24. sigma = [2, 5, 10]
  25. for i in sigma:
  26. subplot(3, 4, 4*(sigma.index(i))+1)
  27. axis('off')
  28. imshow(im)
  29. imgx=imx(im, i)
  30. subplot(3, 4, 4*(sigma.index(i))+2)
  31. axis('off')
  32. imshow(imgx)
  33. imgy=imy(im, i)
  34. subplot(3, 4, 4*(sigma.index(i))+3)
  35. axis('off')
  36. imshow(imgy)
  37. imgmag=mag(im, i)
  38. subplot(3, 4, 4*(sigma.index(i))+4)
  39. axis('off')
  40. imshow(imgmag)
  41. show()

结果反映了x、y倒数图形及梯度大小图像,δ值越大模糊效果越强,图像细节丢失越多。

1.4.3 形态学:对数计数

形态学(或数学形态学)是度量和分析基本形状的图像处理方法的基本框架与集合。形态学通常用于处理二值图像,但是也能够用于灰度图像。二值图像是指图像的每个像素只能取两个值,通常是0和1。二值图像通常是,在计算物体的数目,或者度量其大小时,对一幅图像进行阈值化后的结果。

scipy.ndimage中的morphology模块可以实现形态学操作,可以使用scipy.ndimage中的measurements模块来实现二值图像的计数和度量功能。

  1. from scipy.ndimage import measurements,morphology
  2. # 载入图像,然后使用阈值化操作,以保证处理的图像为二值图像
  3. im = array(Image.open('houses.png').convert('L'))
  4. im = 1*(im<128)
  5. labels, nbr_objects = measurements.label(im)
  6. print "Number of objects:", nbr_objects

上述脚本:

  1. 首先载入该图像,通过阈值化方式确保该图像是二值图像。通过和1相乘,脚本将布尔数组转换成二进制表示。
  2. 使用label()函数寻找单个的物体,并且按照它们属于哪个对象将证书标签给像素赋值。
  3. 图像灰度值表示对象的标签。可以看到,在一些对象之间是有一些小的连接。进行二进制开操作,我们可以将其移除:
  1. # 形态学开操作更好地分离各个对象
  2. im_open = morphology.binary_opening(im,ones((9,5)),iterations=2)
  3. labels_open, nbr_objects_open = measurements.label(im_open)
  4. print "Number of objects:", nbr_objects_open

binary_opening()函数的第二个参数指定一个数组元素。该数组表示以一个像素为中心时,使用哪些相邻像素。参数iterations决定执行该操作的次数。

  1. from PIL import Image
  2. from numpy import *
  3. from scipy.ndimage import measurements, morphology
  4. from pylab import *
  5. """ This is the morphology counting objects example in Section 1.4. """
  6. # 添加中文字体支持
  7. from matplotlib.font_manager import FontProperties
  8. font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
  9. # load image and threshold to make sure it is binary
  10. figure()
  11. gray()
  12. im = array(Image.open('jishu.jpg').convert('L'))
  13. subplot(221)
  14. imshow(im)
  15. axis('off')
  16. title(u'原图', fontproperties=font)
  17. im = (im < 128)
  18. labels, nbr_objects = measurements.label(im)
  19. print ("Number of objects:", nbr_objects)
  20. subplot(222)
  21. imshow(labels)
  22. axis('off')
  23. title(u'标记后的图', fontproperties=font)
  24. # morphology - opening to separate objects better
  25. im_open = morphology.binary_opening(im, ones((9, 5)), iterations=2)
  26. subplot(223)
  27. imshow(im_open)
  28. axis('off')
  29. title(u'开运算后的图像', fontproperties=font)
  30. labels_open, nbr_objects_open = measurements.label(im_open)
  31. print ("Number of objects:", nbr_objects_open)
  32. subplot(224)
  33. imshow(labels_open)
  34. axis('off')
  35. title(u'开运算后进行标记后的图像', fontproperties=font)
  36. show()

 

随着迭代次数iterations值增加,对象数目逐渐减少,直到iterations=12时对象数目为0。

1.4.4 一些有用的Scipy模块

1.读写.mat文件

使用scipy.io模块读取.mat文件:

data = scipy.io.loadmat('test.mat')

上面代码中,data对象包含一个字典,字典中的键对应于保存在原始.mat文件中的变量名。由于这些变量是数组格式的,因此可以很方便地保存到.mat文件中。你仅需创建一个字典(其中要包含你想要保存的所有变量),然后使用savemat()函数:

  1. data = {}
  2. data['x'] = x
  3. scipy.io.savemat('test.mat',data)

因为上面的脚本保存的是数组x,所以当读入到Matlab中时,变量的名字仍为x。

2.以图像形式保存数组

imsave()函数可以从scipy.misc模块载入。要将数组im保存到文件中,可以使用下面的命令:

  1. from scipy.misc import imsave
  2. imsave('test.jpg',im)

1.5 高级示例:图像去噪

图像去噪是在去除图像噪声的同时,尽可能地保留图像细节和结构的处理技术。我们这里使用 ROF(Rudin-Osher-Fatemi)去噪模型。

一幅(灰度)图像I的全变差定义为梯度范数之和。在连续表示的情况下,全变差表示为:

J(\boldsymbol{I})=\int|\nabla \boldsymbol{I}| \mathrm{d} \mathbf{x}

在离散表示的情况下,全变差表示为:

J(\boldsymbol{I})=\sum_{\mathbf{x}}|\nabla \boldsymbol{I}|

其中,上面的式子是在所有图像坐标x=[x,y]上取和。

在ROF模型里,目标函数为寻找降噪后的图像U,使下式最小:

\min _{U}\|\boldsymbol{I}-\boldsymbol{U}\|^{2}+2 \lambda J(\boldsymbol{U}),

  1. from pylab import *
  2. from numpy import *
  3. from numpy import random
  4. from scipy.ndimage import filters
  5. import imageio
  6. from PCV.tools import rof
  7. """ This is the de-noising example using ROF in Section 1.5. """
  8. # 添加中文字体支持
  9. from matplotlib.font_manager import FontProperties
  10. font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
  11. # create synthetic image with noise
  12. im = zeros((500,500))
  13. im[100:400,100:400] = 128
  14. im[200:300,200:300] = 255
  15. im = im + 30*random.standard_normal((500,500))
  16. U,T = rof.denoise(im,im)
  17. G = filters.gaussian_filter(im,10)
  18. # save the result
  19. #imsave('synth_original.pdf',im)
  20. #imsave('synth_rof.pdf',U)
  21. #imsave('synth_gaussian.pdf',G)
  22. # plot
  23. figure()
  24. gray()
  25. subplot(1,3,1)
  26. imshow(im)
  27. #axis('equal')
  28. axis('off')
  29. title(u'原噪声图像', fontproperties=font)
  30. subplot(1,3,2)
  31. imshow(G)
  32. #axis('equal')
  33. axis('off')
  34. title(u'高斯模糊后的图像', fontproperties=font)
  35. subplot(1,3,3)
  36. imshow(U)
  37. #axis('equal')
  38. axis('off')
  39. title(u'ROF降噪后的图像', fontproperties=font)
  40. show()

其中第一幅图示原噪声图像,中间一幅图示用标准差为10进行高斯模糊后的结果,最右边一幅图是用ROF降噪后的图像。上面原噪声图像是模拟出来的图像,现在我们在真实的图像上进行测试:

  1. from PIL import Image
  2. from pylab import *
  3. from numpy import *
  4. from numpy import random
  5. from scipy.ndimage import filters
  6. import imageio
  7. from PCV.tools import rof
  8. """ This is the de-noising example using ROF in Section 1.5. """
  9. # 添加中文字体支持
  10. from matplotlib.font_manager import FontProperties
  11. font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
  12. im = array(Image.open('jy.png').convert('L'))
  13. U,T = rof.denoise(im,im)
  14. G = filters.gaussian_filter(im,10)
  15. # save the result
  16. #imsave('synth_original.pdf',im)
  17. #imsave('synth_rof.pdf',U)
  18. #imsave('synth_gaussian.pdf',G)
  19. # plot
  20. figure()
  21. gray()
  22. subplot(1,3,1)
  23. imshow(im)
  24. #axis('equal')
  25. axis('off')
  26. title(u'原噪声图像', fontproperties=font)
  27. subplot(1,3,2)
  28. imshow(G)
  29. #axis('equal')
  30. axis('off')
  31. title(u'高斯模糊后的图像', fontproperties=font)
  32. subplot(1,3,3)
  33. imshow(U)
  34. #axis('equal')
  35. axis('off')
  36. title(u'ROF降噪后的图像', fontproperties=font)
  37. show()

上面的功能实现中,由于版本升级,参考代码中:

from scipy.misc import imsave

应更改为:

import imageio

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/648989
推荐阅读
相关标签
  

闽ICP备14008679号