【干货】计算机视觉实战系列02——用Python做图像处理

【导读】在当今互联网蓬勃发展的时代,图像处理技术也随着人们的需求不断进步,专知成员Hui计划推出一系列计算机视觉入门实战讲解,参照Jan Erik Solem编写的《Python计算机视觉编程》这本书,以时下最流行的Python语言为工具,对图像处理技术的具体操作进行详细讲述,上一次的内容中已经为大家介绍了PIL python图像处理类库的使用,包括读取图像,转换灰度图像,创建缩略图,裁剪图像区域,调整尺寸和旋转。这一次为大家介绍Matplotlib的使用,包括绘图,绘制点和线,以及图像的轮廓和直方图,代码简洁,通俗易懂,旨在让零基础的读者也可以轻松上手!


【干货】计算机视觉实战系列01——用Python做图像处理

 


Matplotlib基本的图像操作和处理

 

Python中有好多工具包应用于图像处理当中,本章作为入门章节,首先来介绍Python中最基本的几个工具包,也希望读者可以在之后自行练习。

 

Matplotlib




Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。它可以很好地帮助我们处理数学运算,绘制图表,或者在图像上绘制点、直线和曲线,具有比PIL更强大的绘图功能。Matplotlib中的PyLib接口包含很多方便用户创建图像的函数。


使用默认的绘图属性绘图



 

以绘制正弦余弦函数曲线为例,介绍相应的函数

代码如下:

from PIL import Image
from pylab import *

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(x), np.sin(x)
plt.plot(x, C)
plt.plot(x, S)

show()

numpy.linspace:在指定的间隔内返回均匀间隔的数字。返回num均匀分布的样本,在[start, stop]。这个区间的端点可以任意的被排除在外。第一个参数为序列的起始点,第二个参数为序列的结束点,第三个参数为步长,第四个参数意为:如果是True,则一定包括stop,如果为False,一定不会有stop。

结果如下图所示:

上面的两行plot代码为绘制图像,当然还可以对绘制图像做更加具体的要求,比如:

plt.plot(x,C,color='red',linewidth=2.5,linestyle='-')  
plt.plot(x,S,color='blue',linewidth=2.5,linestyle='-.')


本文只提供plot的部分使用方法,如果读者想了解更多plot的操作,请参考官方网站:http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot

 

除此之外,我们还可以对坐标轴的绘制进行设置,具体代码如下:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(x), np.sin(x)
plt.xlim(x.min() * 1.1, x.max() * 1.1)
plt.xticks([-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, 0, +1],
          [r'$-1$', r'$0$', r'$+1$'])
plt.plot(x, C, color='red', linewidth=2.5, linestyle='-')
plt.plot(x, S, color='blue', linewidth=2.5, linestyle='-.')

plt.show()


输出结果如下:

 

看到yticks和xticks后面一 串的数字,看到就觉得可能有点不知道写的什么,熟悉LaTex的人觉得我们这种想法的人有点傻。其实就是很简单的字符串,但是是为了方便Latex去解析这段字符串。一般以r开始,中间的字符串用$字符串$包围起来。这里是matplotlib中的有关LaTex的使用介绍:Latex的使用

链接:https://matplotlib.org/users/mathtext.html

 

在完成了坐标轴的设置后,我们还可以通过Matplotlib设置坐标轴位置,Spines 是连接轴刻度标记的线,而且标明了数据区域的边界。 他们可以被放置在任意位置。直到现在,他们仍是轴的边界。我们将要改变现状,因为我们想要spines 置于中间。因为有四个spine(上下左右),我们将要通过设置颜色(无)丢弃上面和右侧的部分。 进而我们移动下面和左边的线到坐标0(数据空间)。

 

用法为:

Spine(axes, spine_type, path, **kwargs)axes :包含spine的轴实例。spine_type :指定spine类型的字符串path :用于绘制spine的路径实例。例如:我们调用’right’边的spine的’set_color’方法,并且传入’none’参数,这样,左边框的颜色就变成了无色,而’set_position()’方法则使边框的位置改变,“0”代表中心,依靠这个方法我们就能自己“拼凑”出坐标轴,并且能够把其他边框屏蔽掉。’ax.xaxis.set_ticks_position()’方法则设置了坐标轴数据的位置,括号内为传入的位置信息。

 

此外,我们还可以通过legend()方法添加图例。

 

完整的代码为:

import numpy as np
import matplotlib.pyplot as plt

ax = plt.subplot(111)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))

x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
C, S = np.cos(x), np.sin(x)

plt.plot(x, C, color='red', linewidth=2.5, linestyle='-', label=r'$cos(t)$')
plt.plot(x, S, color='blue', linewidth=2.5, linestyle='-', label=r'$sin(t)$')
plt.legend(loc='upper left', frameon=False)

plt.xlim(x.min() * 1.1, x.max() * 1.1)
plt.xticks([-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi],
          [r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])

plt.ylim(C.min() * 1.1, C.max() * 1.1)
plt.yticks([-1, 0, +1],
          [r'$-1$', r'$0$', r'$+1$'])
plt.show()

输出图像为:



绘制点和线



 

下面,我们来看一下在已绘制的图像上绘制点和线。我们首先用到上一节中绘制的图片“test.jpg”

代码如下:

from PIL import Image
from pylab import *

im = array(Image.open("test.jpg"))
imshow(im)
x = [100, 400, 600, 800]
y = [100, 200, 1000, 1200]
plot(x[:2], y[:2], 'b*')

show()

输出结果如下:

 

我们看到,我们成功在一张导入的图片上绘制出了两个蓝色的五角星。如果加一行代码:

plot(x,y,linewidth=3.5)

我们就将x,y对应点连接在一起了

结果如下图所示:


那么我们回过头来看一下上面的代码:首先为绘制原始图像,然后再x,y列表中给定点的x坐标,y坐标上绘制出蓝色五角星状标记点,注意,我们取x[:2]意为取x列表元素的第零个和第一个,不包含第二个元素,y列表同理,需要注意的是,x,与y列表的取值数量应该一致,否则,系统会报错。而当我们用plot()方法将各个点相连时,程序会自动将所有的x与y的对应点相连,此时,若x与y列表元素数量不一致,系统同样会报错。

 

绘图时有很多选项可以控制图像的颜色和样式:

plot(x,y)       #默认为蓝色实线
plot(x,y,’r*’) #红色星状标记
plot(x,y,’go-’) #带有圆圈标记的绿线
plot(x,y,’ks-’) #带有正方形标记的黑色点线


颜色标注:

‘b’ #蓝色
‘g’ #绿色
‘r’ #红色
‘c’ #青色
‘m’ #品红
‘y’ #黄色
‘k’ #黑色
‘w’ #白色


线型格式命令:

‘-’ #实线
‘--’#虚线
‘:’#点线


绘制标记格式命令:

‘.’ #点
‘o’ #圆圈
‘s’ #正方形
‘*’ #星形
‘+’ #加号
‘x’ #叉号

 

图像的轮廓和直方图



 

绘制图像的轮廓(或者其它二位函数的等轮廓线)在工作中非常有用,因为绘制轮廓需要对每个坐标[x,y]的像素值施加一个相同的阈值,所以首先需要将图像灰度化

 

完整代码如下:

from PIL import Image
from pylab import *

image = array(Image.open('test.jpg').convert('L'))
figure() # 新建一个图像
gray() # 不使用颜色信息
contour(image, origin='image')

axis('equal')
plt.show()


 显示图像如图所示:

 

这样我们就成功生成了一张图片的轮廓了。

其中contour()本应用于设置等高线,用法为:

contour(Z) :绘制矩阵Z的等高线 
contour(Z,n) :设置等高线的根数(画出来有n根等高线) 
contour(Z,v) :v是元素随下标单调递增的一维向量,用来设置等高线的值。即在固定的几个值的位置设置等高线。

其中的origin可以传入’upper’,’lower’,’None’,以及’image’等参数用于固定图像的位置。

 

图像的直方图用来表征该图像的像素值分布情况,用一定数目的小区间(bin)来表征像素值的范围,每个小区间会得到落入该小区域间表示范围的像素数目,该灰度图像的直方图可以使用hist()函数绘制,完整代码如下:

from PIL import Image
from pylab import *

fig = plt.figure(figsize=(15, 15))
image = array(Image.open('test.jpg').convert('L'))

plt.subplot(2, 1, 1)
plt.imshow(image, cmap=cm.gray)
plt.axis("off")
plt.subplot(2, 1, 2)
plt.hist(image.flatten(), 256) # flatten可以将矩阵转化成一维序列
plt.show()

显示图像如图所示:

 


hist()函数的第二个参数指定小区间的数目,需要注意的是,因为hist()只接受一维数组作为输入,所以我们在绘制图像直方图之前,必须先对图像进行平压处理,flatten()方法将任意数组按照行优先准则转换成一维数组。

 

plt.subplot()意为创建子图像。其中括号内传入了三个参数,第一个表示Y轴方向的子图个数,第二个表示X轴方向的子图个数,第三个则表示当前要画图的焦点。


参考文献:

python计算机视觉编程:http://yongyuan.name/pcvwithpython/

-END-

专 · 知

人工智能领域主题知识资料查看获取【专知荟萃】人工智能领域26个主题知识资料全集(入门/进阶/论文/综述/视频/专家等)

请PC登录www.zhuanzhi.ai或者点击阅读原文,注册登录专知,获取更多AI知识资料

请扫一扫如下二维码关注我们的公众号,获取人工智能的专业知识!

请加专知小助手微信(Rancho_Fang),加入专知主题人工智能群交流!

点击“阅读原文”,使用专知

展开全文
Top
微信扫码咨询专知VIP会员