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

基本图像操作和处理

我简单看了一下这本书,大体上是一本实战类的书。此处我假定所有的读者都有一定的python基础,知道如何安装库,能大致看懂python语法。下面正式开始本书内容。

要用到什么库

我们本次要使用的库如下:

  1. PIL:Python Imaging Library,能提供通用的图像处理功能,如图像缩放、裁剪、旋转等
  2. Matplotlib:画图用的库,能画各种各样的图,稍后就会见到
  3. numpy:科学计算工具包,矩阵之类的计算非常有用,可以说科学领域只要用python,这个库八成避免不了
  4. scipy:科学计算工具包,但是相对于numpy来讲封装的更好,比如可以实现高斯模糊等等操作

由于本书侧重与实践,因此下面将开始对这四个库的实战讲解:

PIL

输入输出

前文有提到过PIL能提供图片处理的基本功能,那么首先让我们尝试一下输入输出:

# 导入PIL
from PIL import Image
# 导入plt,注意,只是因为我用jupyter了暂时无法直接显示PIL的图片才需要导入,否则不需要
import matplotlib.pyplot as plt

# 读取图片
img = Image.open('img.png')

# 显示图片
plt.imshow(img)
plt.show()

运行结果如下:
在这里插入图片描述
为了验证我们是不是真的读取了图片,现在再让我们试一下颜色转换:

# 导入PIL
from PIL import Image
# 导入plt,注意,只是因为我用jupyter了暂时无法直接显示PIL的图片才需要导入,否则不需要
import matplotlib.pyplot as plt
import matplotlib



# 读取图片
img = Image.open('img.png')

# 颜色转换
img = img.convert('L')

# 显示图片
# 由于jupyter会将灰度映射为其他颜色,因此需要指定cmap='gray'
plt.imshow(img, cmap='gray')
plt.show()

运行结果:
在这里插入图片描述
可以看到图片成功的转为灰色了,注释中我提到了一个小坑,但是如果是本地运行的话应该不会出现上述问题,感兴趣的话可以自行尝试一下。

基本操作

由于很多操作都只有一行,因此,此处我们将转换图像格式、创建缩略图、复制与粘贴图像区域、调整尺寸与旋转全部放到一起来描述、同样的,所有需要注意的地方都注释在了代码中:

# 导入PIL
from PIL import Image
import matplotlib.pyplot as plt


# 读取图片
img_png = Image.open('img.png')

# 转换图像格式
# 此处与书上讲的不一样,其实PIL没有那么智能,png默认编码是RGBA,保存为JPEG格式需要先转化一下才可以保存
img_png = img_png.convert('RGB')
img_png.save('img.jpg')

img_jpg = Image.open('img.jpg')

plt.imshow(img_jpg)
plt.show()

# 缩略图
img_thumbnail = img_jpg
img_thumbnail.thumbnail((128,128))

plt.imshow(img_thumbnail)
plt.show()

# 复制粘贴
# 规定裁剪区域
box = (10,10,50,50)
# 从原图裁剪一块
region = img_jpg.crop(box)
# 粘贴回去
past_box = (50,50,90,90)
img_jpg.paste(region, past_box)

plt.imshow(img_jpg)
plt.show()

# 旋转
img_rotate = img_jpg.rotate(45)
plt.imshow(img_rotate)
plt.show()

# 调整尺寸
img_resize = img_rotate.resize((50, 50))
plt.imshow(img_resize)
plt.show()

运行结果如下:
请添加图片描述
看大小不是很直观,但是我们看一下坐标就可以很容易的发现,原始图像大小是200多,经过了resize等之后大小变为了100左右,50左右。

Matplotlib

由于我的使用的是远程环境,有一部分操作要借助Matplotlib显示,因此前面其实我们已经初步用过了Matplotlib,下面开始较为详细的介绍

绘制图像、点、线

下面将直接以代码的形式展示要如何画图:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

# 读取图像到数组中
im = np.array(Image.open('img.jpg'))
# 绘制图像
plt.imshow(im)

# 一些点,注意,x和y在一起才构成完整的几个点
x = [100,100,400,400]
y = [200,500,200,500]

# 使用红色星状标记绘制点
plt.plot(x,y,'r*')

# 绘制连接前两个点的线
plt.plot(x[:2],y[:2])

# 添加标题,显示绘制的图像
plt.title('Plotting: "img.jpg"')

# 控制是否显示坐标轴
plt.axis('off')
plt.show()


最终画出来的图如下:在这里插入图片描述
之所以有大量空白是因为我们设置的点的坐标超过了图片的大小,否则应该会全部在图片中。另外,我们关闭了坐标轴的显示来让图片更清晰。

图像轮廓与直方图

首先来看代码与运行结果:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

# 读取图像到数组中,如果不是为了显示直方图可以不用转为np
im = np.array(Image.open('img.jpg').convert('L'))

# 绘制图像
# 在图像窗口中绘制轮廓线
plt.contour(im,origin='image')
# 设置x与y的刻度相等
plt.axis('equal')

# 控制是否显示坐标轴
plt.axis('off')
plt.show()

# 画直方图
plt.hist(im.flatten(),128)
plt.show()

在这里插入图片描述
在这里插入图片描述

NumPy

我们在上一小节之中其实已经用过numpy了,就在生成直方图这里。除此之外,numpy还可以存储图片,进行矩阵运算等等操作

存储图片

我们先来看一段代码:

from PIL import Image
import numpy as np


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


img = np.array(Image.open('img.jpg'))
print(img.shape,img.dtype)




这是其输出:
在这里插入图片描述
可以看到,图像被编码成了矩阵的形式,灰度图是单通道的,彩色是三通道的。在创建数组时使用额外的参数“f”可以将数据类型转换为浮点型。
此外,numpy的使用与python的数组非常相似,由于这一点无法在图像中很好的展示,因此下面将简单介绍一下而没有运行实例:
在这里插入图片描述

灰度变换

示例代码:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np


image1 = np.array(Image.open('img.jpg').convert('L')) # 原图


image2 = 255 - image1 # 求反

image3 =  (100.0/255) * image1 + 100 # 将图像像素值变换到 100...200 区间

image4 = 255.0 * (image1/255.0)**2 # 对图像像素值求平方后得到的图像




# 创建2x2的图像布局,并在每个子图中显示图片
plt.subplot(2, 2, 1)
plt.imshow(image1, cmap='gray')
plt.title('Image 1')

plt.subplot(2, 2, 2)
plt.imshow(image2, cmap='gray')
plt.title('Image 2')

plt.subplot(2, 2, 3)
plt.imshow(image3, cmap='gray')
plt.title('Image 3')

plt.subplot(2, 2, 4)
plt.imshow(image4, cmap='gray')
plt.title('Image 4')

# 调整子图之间的间距
plt.tight_layout()

# 显示图像
plt.show()

运行结果:
请添加图片描述

SciPy

scipy提供了很多已经封装好的操作,但是在这里我们只测试一下图像滤波,形态学。

滤波

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from scipy import ndimage


# 读取原图像
image1 = np.array(Image.open('img.jpg').convert('L'))

# 高斯,模糊图像
image2 =  ndimage.gaussian_filter(image1,5)

# 单通道模糊图像
image3 = np.array(Image.open('img.jpg'))
image3[:,:,1] =  ndimage.gaussian_filter(image3[:,:,1],10)

# 求梯度图
image4 = ndimage.gaussian_gradient_magnitude(image1, sigma=3)




# 创建2x2的图像布局,并在每个子图中显示图片
plt.subplot(2, 2, 1)
plt.imshow(image1, cmap='gray')
plt.title('Image 1')

plt.subplot(2, 2, 2)
plt.imshow(image2, cmap='gray')
plt.title('Image 2')

plt.subplot(2, 2, 3)
plt.imshow(image3, cmap='gray')
plt.title('Image 3')

plt.subplot(2, 2, 4)
plt.imshow(image4, cmap='gray')
plt.title('Image 4')

# 调整子图之间的间距
plt.tight_layout()

# 显示图像
plt.show()

在这里插入图片描述

重要的代码已经都在代码中注释了,现在我们来看一下运行结果。
首先是image1,这是原图的灰度图,用于与其他几张图片对比。
然后是image2,对其进行了高斯模糊,可以很清楚的看到模糊了很多。
然后是image3,这是对原图在红色通道上进行了高斯模糊,可以看到图标周围有一圈红晕,这就是单通道模糊的结果。
最后是image4,对灰度图进行了梯度处理。

形态学

import numpy as np
from PIL import Image
from scipy.ndimage import binary_dilation, binary_erosion
from matplotlib import pyplot as plt

# 读取图像
image_path = "img.jpg"
image = Image.open(image_path)

# 将图像转换为灰度图像
gray_image = image.convert("L")

# 将灰度图像转换为NumPy数组
threshold = 175
image_array = np.array(gray_image)
image_array[image_array < threshold] = 0


# 定义膨胀和侵蚀的结构元素
structure_element = np.ones((3, 3), dtype=bool)  # 这里使用3x3的正方形结构元素

# 进行形态学膨胀操作
dilated_array = binary_dilation(image_array, structure=structure_element)

# 进行形态学侵蚀操作
eroded_array = binary_erosion(image_array, structure=structure_element)

# 将NumPy数组转换回图像
dilated_image = Image.fromarray(dilated_array.astype(np.uint8))
eroded_image = Image.fromarray(eroded_array.astype(np.uint8) )



# 显示图像

plt.subplot(1, 2, 1)

plt.gray()
plt.title('dilated_image')
plt.imshow(dilated_image)
plt.subplot(1, 2, 2)
plt.title('eroded_image')
plt.imshow(eroded_image)
plt.show()

在这里插入图片描述
我们首先是读取了图片,然后阈值处理,再然后用scipy对其进行了形态学操作,最后使用了plt显示图片。可以看到scipy的形态学处理效果还是非常好的。

小结

这一章其实没有讲太多东西,所有的东西基本上前面都做过了,而且我感觉我还是比较习惯用opencv来做这些操作,尤其是scipy和PIL,这两个在这一章的所有内容都可以用opencv来做。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值