计算机视觉1—基本图像操作和处理

目录

1 PIL-Python图像库

1.1 对图片进行格式转换

1.2 创建缩略图

1.3 拷贝并粘贴区域

1.4 调整尺寸及旋转

2 Matplotlib库

2.1 画图、描点和线

2.2 图像轮廓和直方图

2.3 交互注释

3 NumPy库

扫描二维码关注公众号,回复: 9685057 查看本文章

3.1 图像数组表示

3.2 灰度变换

3.3 调整图像尺寸

3.4 直方图均衡化

3.5 图像平均

4 SciPy模块

4.1 高斯模糊


1 PIL-Python图像库

PIL (Python Imaging Library)图像库提供了很多常用的图像处理及很多有用的图像基本操作,如图像缩放、裁剪、旋转、颜色转换等。PIL库可以通过pip安装,其他库也是一样可以通过pip安装,可参考博客PIL、Matplotlib、PCV等库的安装,详细的说明了安装过程。我采用的是python2.7版本,编译环境是pycharm,只要把涉及的库都安装好,代码就没什么问题了。

PIL库演示例子如下:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *

# 转换为灰度图
# 调用系统文字,宋体 14
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
figure()

pil_im = Image.open('data/py1.jpg')
gray()
subplot(121)
title(u'原图',fontproperties=font)
axis('off')
imshow(pil_im)

# 使用convert将模式“RGB”转换为其他不同模式“L”灰度图(“1”二值图像)
pil_im = Image.open('data/py1.jpg').convert('L')
subplot(122)
title(u'灰度图',fontproperties=font)
axis('off')
imshow(pil_im)

show()

运行上面的代码,可以得出两幅图片,如下:

P002-Fig1-1

1.1 对图片进行格式转换

利用save()方法,PIL可以将图片保存问很多不同的图像格式。

# -*- coding: utf-8 -*-
from PCV.tools.imtools import get_imlist #导入PCV模块
from PIL import Image
import os
import pickle

# 对图片进行格式转换jpg->png

filelist = get_imlist('data/py/') #获取py文件夹下的图片文件名(包括后缀名)
imlist = file('data/py/imlist.txt','w') #将获取的图片文件列表保存到imlist.txt中
pickle.dump(filelist,imlist) #序列化
imlist.close()

for infile in filelist:
    outfile = os.path.splitext(infile)[0] + ".png" #分离文件名与扩展名
    if infile != outfile:
        try:
            Image.open(infile).save(outfile)
        except IOError:
            print("cannot convert", infile)

上面py文件夹放的是测试图片,共3幅图像,如下图示,测试图片全部为.jpg格式的。先将获取的图像文件名列表保存下来,同时将原来的所有图像转化为.png格式的图像,得到转化格式后的图像,运行结果为:

 

1.2 创建缩略图

利用PIL可以创建缩略图,通过调用thumnail()方法,thumbnail函数接受一个元组作为参数,分别对应着缩略图的宽高,在缩略时,函数会保持图片的宽高比例;如果输入的参数宽高和原图像宽高比不同,则会依据最小对应边进行原比例缩放。 创建缩略图的代码见下面。

1.3 拷贝并粘贴区域

crop((x0,y0,x1,y1))方法可以对图片做裁切,区域由一个4元组定义,表示为坐标是 (left, upper, right, lower)。调用crop()方法即可从一幅图像中进行区域拷贝,拷贝出区域后,可以对区域进行旋转等变换。关于拷贝、旋转粘贴的代码见下面。

1.4 调整尺寸及旋转

要对一幅图像的尺寸进行调整,可以调用resize()方法,元组中放置的便是你要调整尺寸的大小。如果要对图像进行旋转变换的话,可以调用rotate()方法,rotate的主要目的就是将【first~middle】的元素和【middle~last】的元素互换位置,middle所指向的元素会成为整个容器的第一个元素。

下面代码显示上面提到的所有的图像处理操作,即原图显示、RGB图像转为灰度图像、拷贝粘贴区域、生成缩略图、调整图像尺寸、图像旋转变换的实例代码:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *

# 调整尺寸及旋转

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
figure()

# 显示原图
pil_im = Image.open('data/py1.jpg')
print pil_im.mode, pil_im.size, pil_im.format
subplot(231)
title(u'原图', fontproperties=font)
axis('off')
imshow(pil_im)

# 显示灰度图
pil_im = Image.open('data/py1.jpg').convert('L')
gray()
subplot(232)
title(u'灰度图', fontproperties=font)
axis('off')
imshow(pil_im)

#拷贝粘贴区域
pil_im = Image.open('data/py1.jpg')
box = (100,100,400,400)
region = pil_im.crop(box)
region = region.transpose(Image.ROTATE_180)
pil_im.paste(region,box)
subplot(233)
title(u'拷贝粘贴区域', fontproperties=font)
axis('off')
imshow(pil_im)

# 缩略图
pil_im = Image.open('data/py1.jpg')
size = 128, 128
pil_im.thumbnail(size)
print pil_im.size
subplot(234)
title(u'缩略图', fontproperties=font)
axis('off')
imshow(pil_im)
pil_im.save('images/Spy1.jpg') #保存缩略图

# 调整图像尺寸
pil_im = Image.open('data/py1.jpg')
pil_im = pil_im.resize(size)
print pil_im.size
subplot(235)
title(u'调整尺寸后的图像', fontproperties=font)
axis('off')
imshow(pil_im)

# 旋转图像45°
pil_im = Image.open('data/py1.jpg')
pil_im = pil_im.rotate(45)
subplot(236)
title(u'旋转45°后的图像', fontproperties=font)
axis('off')
imshow(pil_im)

show()

运行上面代码,结果如下:

2 Matplotlib库

当在处理数学及绘图或在图像上描点、画直线、曲线时,Matplotlib是一个很好的绘图库,它比PIL库提供了更有力的特性。

2.1 画图、描点和线

虽然Matplotlib可以创建漂亮的条状图、饼图、散点图等,但是在很多计算机视觉应用场合,其实只用到了一些常用的命令。下面展示在一幅图像上描一些点和画一条直线的例子。

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *

# 在图上画图、描点和线

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

im = array(Image.open('data/py1.jpg'))
figure()

# 画有坐标轴的
subplot(121)
imshow(im)
x = [100, 100, 400, 400]
y = [200, 500, 200, 500]
plot(x, y, 'r*')
plot(x[:2], y[:2])
title(u'绘图: "py1.jpg"', fontproperties=font)

# 不显示坐标轴
subplot(122)
imshow(im)
x = [100, 100, 400, 400]
y = [200, 500, 200, 500]
plot(x, y, 'r*')
plot(x[:2], y[:2])
axis('off')  #显示坐标轴
title(u'绘图: "py1.jpg"', fontproperties=font)

show()

运行上面代码,运行结果如下:

ch01_P005_fig1-2_matplot

 

2.2 图像轮廓和直方图

下面我们看两个特别的例子:图像轮廓线和图线等高线。在画图像轮廓前需要转换为灰度图像,因为轮廓需要获取每个坐标[x,y]位置的像素值。下面是画图像轮廓和直方图的代码:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *

# 图像轮廓和直方图

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
im = array(Image.open('data/py1.jpg').convert('L'))  # 打开图像,并转成灰度图像

figure()
subplot(121)
gray()
contour(im, origin='image')
axis('equal')
axis('off')
title(u'图像轮廓', fontproperties=font)

subplot(122)
hist(im.flatten(), 200)
title(u'图像直方图', fontproperties=font)
plt.xlim([0,250])
plt.ylim([0,300000])

show()

运行上面代码,得到的结果:

2.3 交互注释

有时,用户需要和应用进行交互,比如在图像中用点做标识,或者在一些训练数据中进行注释。PyLab提供了一个很简洁好用的函数ginput(),它可以完成该任务:

from PIL import Image
from pylab import *

im = array(Image.open('data/py1.jpg'))
imshow(im)
print 'Please click 3 points'
imshow(im)
x = ginput(3)
print 'You clicked:', x

show()

上面代码先读取py1.jpg图像,显示读取的图像,然后用ginput()交互注释,这里设置的交互注释数据点设置为3个,用户在注释后,会将注释点的坐标打印出来。

 

3 NumPy库

NumPy是Python一个流行的用于科学计算包。它包含了很多诸如矢量、矩阵、图像等其他非常有用的对象和线性代数函数。

3.1 图像数组表示

在前面载入图像的示例中,我们将图像用array()函数转为NumPy数组对象,但是并没有提到它表示的含义。数组就像列表一样,只不过它规定了数组中的所有元素必须是相同的类型。下面的例子用于说明图像数组表示:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *

# 图像数组表示

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

运行上面代码,得到结果:

数组可以通过索引访问和操作其中的元素。比如:value=im[i,j,k]。i,j是坐标,k是颜色通道。对于多个元素,可以用切片操作,如:

im[i,:] = im[j,:] # set the values of row i with values from row j
im[:,i] = 100 # set all values in column i to 100
im[:100,:50].sum() # the sum of the values of the first 100 rows and 50 columns
im[50:100,50:100] # rows 50-100, columns 50-100 (100th not included)
im[i].mean() # average of row i
im[:,-1] # last column
im[-2,:] (or im[-2]) # second to last row

3.2 灰度变换

灰度变换是指根据某种目标条件按一定变换关系逐点改变源图像中每一个像素灰度值的方法。目的是为了改善画质,使图像的显示效果更加清晰。 图像的灰度变换处理是图像增强处理技术中的一种非常基础、直接的空间域图像处理方法,也是图像数字化软件和图像显示软件的一个重要组成部分。

在读入图像到NumPy数组后,就可以对它进行任何我们想要的操作了。对图像进行灰度变换便是一个简单的例子,如下示:

# -*- coding: utf-8 -*-
from PIL import Image
from numpy import *
from pylab import *

# 灰度变换

im = array(Image.open('data/py1.jpg').convert('L'))
print int(im.min()), int(im.max())

im2 = 255 - im  # invert image
print int(im2.min()), int(im2.max())

im3 = (100.0/255) * im + 100  # clamp to interval 100...200
print int(im3.min()), int(im3.max())

im4 = 255.0 * (im/255.0)**2  # squared
print int(im4.min()), int(im4.max())

figure()
gray()
subplot(1, 3, 1)
imshow(im2)
axis('off')
title(r'$f(x)=255-x$')

subplot(1, 3, 2)
imshow(im3)
axis('off')
title(r'$f(x)=\frac{100}{255}x+100$')

subplot(1, 3, 3)
imshow(im4)
axis('off')
title(r'$f(x)=255(\frac{x}{255})^2$')
show()

上面左边灰度变换函数采用的是f(x)=255-x,中间采用的是f(x)=(100/255)x+100,右边采用的是变换函数是f(x)=255(x/255)^2。运行上面代码,可以得到结果:ch01_fig1-5_graylevel-transforms

如果你对每幅图像用到了打印最小像素值和最大像素值,你会得到下面的输出结果:

0 234
21 255
100 191
0 214

3.3 调整图像尺寸

NumPy数组是我们对图像及数据进行处理的最主要工具,但是调整矩阵大小并没有一种简单的方法。我们可以用PIL图像对象转换写一个简单的图像尺寸调整函数:

def imresize(im,sz):
    """    Resize an image array using PIL. """
    pil_im = Image.fromarray(uint8(im))

    return array(pil_im.resize(sz))

3.4 直方图均衡化

直方图均衡化是一种增强图像对比度的方法,其主要思想是将一副图像的直方图分布变成近似均匀分布,从而增强图像的对比度。一个极其有用的例子是灰度变换后进行直方图均衡化。图像均衡化作为预处理操作,在归一化图像强度时是一个很好的方式,并且通过直方图均衡化可以增加图像对比度。下面是对图像直方图进行均衡化处理的例子:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from PCV.tools import imtools

# 直方图均衡化

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

im = array(Image.open('data/py1.jpg').convert('L'))  # 打开图像,并转成灰度图像
#im = array(Image.open('../data/AquaTermi_lowcontrast.JPG').convert('L'))
im2, cdf = imtools.histeq(im)

figure()
subplot(2, 2, 1)
axis('off')
gray()
title(u'原始图像', fontproperties=font)
imshow(im)

subplot(2, 2, 2)
axis('off')
title(u'直方图均衡化后的图像', fontproperties=font)
imshow(im2)

subplot(2, 2, 3)
axis('off')
title(u'原始直方图', fontproperties=font)
#hist(im.flatten(), 128, cumulative=True, normed=True)
hist(im.flatten(), 128, density=True)

subplot(2, 2, 4)
axis('off')
title(u'均衡化后的直方图', fontproperties=font)
#hist(im2.flatten(), 128, cumulative=True, normed=True)
hist(im2.flatten(), 128, normed=True)

show()

运行上面代码,可以得到结果:

3.5 图像平均

因为图像是现实世界的反映,图像中每个像素点的值与其旁边的像素点的值比较接近,除了对象边界外,每个对象反映在图像中,其覆盖的区域亮度都比较近似。既然图像中的每个像素点的值与其旁边像素的值比较接近,如果一个像素点的值被噪声干扰,就可以用其周边区域的像素平均值来代替这个像素点的值呢。这就是平均操作:即把每个像素的值改变为其与领域像素组成区域的平均值。

对图像取平均是一种图像降噪的简单方法,经常用于产生艺术效果。假设所有的图像具有相同的尺寸,我们可以对图像相同位置的像素相加取平均,下面是一个演示对图像取平均的例子:

# -*- coding: utf-8 -*-
from PCV.tools.imtools import get_imlist
from PIL import Image
from pylab import *
from PCV.tools import imtools

# 图像平均

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

filelist = get_imlist('data/py/') #获取py文件夹下的图片文件名(包括后缀名)
avg = imtools.compute_average(filelist)

for impath in filelist:
        im1 = array(Image.open(impath))
        subplot(2, 2, filelist.index(impath)+1)
        imshow(im1)
        imNum=str(filelist.index(impath)+1)
        title(u'待平均图像'+imNum, fontproperties=font)
        axis('off')
subplot(2, 2, 4)
imshow(avg)
title(u'平均后的图像', fontproperties=font)
axis('off')

show()

运行上面代码,可得对3幅图像平均后的效果,如下图:

ch10_P011_avg

4 SciPy模块

Scipy是一个用于数学、科学、工程领域的常用软件包,可以处理插值、积分、优化、图像处理、常微分方程数值解的求解、信号处理等问题。它用于有效计算Numpy矩阵,使Numpy和Scipy协同工作,高效解决问题。

4.1 高斯模糊

高斯模糊是图像处理软件中广泛使用的处理效果,通常用它来减少图像噪声以及降低细节层次。这种模糊技术生成的图像,其视觉效果就像是经过一个毛玻璃在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果。 从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅里叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波器。

一个经典的并且十分有用的图像卷积例子是对图像进行高斯模糊。高斯模糊可以用于定义图像尺度、计算兴趣点以及很多其他的应用场合。下面是对图像进行模糊显示的例子。

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from scipy.ndimage import filters

# 图像模糊

# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)

#im = array(Image.open('board.jpeg'))
im = array(Image.open('data/py1.jpg').convert('L'))

figure()
gray()
axis('off')
subplot(1, 4, 1)
axis('off')
title(u'原图', fontproperties=font)
imshow(im)

for bi, blur in enumerate([2, 5, 10]):
  im2 = zeros(im.shape)
  im2 = filters.gaussian_filter(im, blur)
  im2 = np.uint8(im2)
  imNum=str(blur)
  subplot(1, 4, 2 + bi)
  axis('off')
  title(u'标准差为'+imNum, fontproperties=font)
  imshow(im2)

#如果是彩色图像,则分别对三个通道进行模糊
#for bi, blur in enumerate([2, 5, 10]):
#  im2 = zeros(im.shape)
#  for i in range(3):
#    im2[:, :, i] = filters.gaussian_filter(im[:, :, i], blur)
#  im2 = np.uint8(im2)
#  subplot(1, 4,  2 + bi)
#  axis('off')
#  imshow(im2)

show()

运行上面代码,可得结果:

发布了13 篇原创文章 · 获赞 5 · 访问量 1205

猜你喜欢

转载自blog.csdn.net/qq_43653930/article/details/104406926