python图像处理
PIL库处理图像
导入库
from PIL import Image
读取图像
im = Image.open(r'./pictures/boy.jpg')
im
保存图像
im.save(r'./pictures/boyL.jpg')
转为灰度图
im.convert('L')
创建缩略图
thumbnail()
方法接受一个元组参数(该参数指定生成缩略图的大小),然后将图像转换成符合元组参数指定大小的缩略图。例如,创建最长边为 128 像素的缩略图,可以使用下列命令:
im.thumbnail((128,128))
复制和粘贴图像区域
使用crop()
方法可以从一幅图像中裁剪指定区域:
box = (100,100,400,400)
region = im.crop(box)
该区域使用四元组来指定。四元组的坐标依次是(左,上,右,下)。PIL 中指定坐标系的左上角坐标为(0,0)。我们可以旋转上面代码中获取的区域,然后使用paste()
方法将该区域放回去,具体实现如下:
region = region.transpose(Image.ROTATE_180)
im.paste(region,box)
调整尺寸和旋转
要调整一幅图像的尺寸,我们可以调用resize()
方法。该方法的参数是一个元组,用来指定新图像的大小:
im.resize((128,128))
要旋转一幅图像,可以使用逆时针方式表示旋转角度,然后调用rotate()
方法:
im.rotate(45)
NumPy读取图像到数组
np.array()
方法可将Image
对象转化为数组对象,读取成功后会返回一个数组array,其大小如下:
- (M, N) for grayscale images .#灰度图像
- (M, N, 3) for RGB images. #24位彩色图像
- (M, N, 4) for RGBA images. #RGBA32位彩色图像
from PIL import Image
import numpy as np
im = np.array(Image.open(r'./pictures/boy.jpg'))
im
array([[[146, 208, 255],
[146, 208, 255],
[146, 208, 255],
...,
[198, 225, 255],
[197, 224, 254],
[196, 223, 253]],
[[113, 178, 232],
[113, 178, 232],
[113, 178, 232],
...,
[177, 203, 238],
[176, 202, 237],
[175, 201, 236]],
[[ 87, 157, 216],
[ 87, 157, 216],
[ 87, 157, 216],
...,
[163, 188, 228],
[162, 187, 227],
[161, 186, 226]],
...,
[[155, 146, 139],
[146, 137, 130],
[135, 126, 119],
...,
[ 76, 121, 144],
[ 77, 122, 145],
[ 78, 123, 146]],
[[154, 145, 138],
[148, 139, 132],
[139, 130, 123],
...,
[ 84, 129, 152],
[ 83, 128, 151],
[ 83, 128, 151]],
[[153, 144, 137],
[149, 140, 133],
[142, 133, 126],
...,
[ 90, 135, 158],
[ 88, 133, 156],
[ 87, 132, 155]]], dtype=uint8)
im.shape
(1080, 1080, 3)
可以知道这幅图像是一幅三颜色通道的24位彩色图像,每行每列有1080个像素。
图像轮廓和直方图
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
#plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
#plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#读取图像到数组中
im = np.array(Image.open(r'./pictures/boy.jpg').convert('L'))
#不使用颜色信息
plt.gray()
#在原点左上角显示轮廓图像
plt.contour(im,origin='image')
plt.axis('equal')
plt.axis('off')
图像的直方图用来表征该图像像素值的分布情况。用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。该(灰度)图像的直方图可以使用 hist()
函数绘制:
plt.hist(im.flatten(),128)
#flatten() 方法将任意数组按照行优先准则换成一维数组
#hist() 函数第二个参数制定小区间的数目
plt.show()
灰度变换
将图像读入 NumPy 数组对象后,我们可以对它们执行任意数学操作。一个简单的例子就是图像的灰度变换。考虑任意函数 f,它将 0…255 区间(或者 0…1 区间)映射到自身(意思是说,输出区间的范围和输入区间的范围相同)。下面是关于灰度变换的一些例子:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
im = np.array(Image.open(r'./pictures/boy.jpg').convert('L'))
im1 = 255 - im # 对图像进行反转处理
im2 = (100.0/255) * im + 100 # 将图像像素值变换到100...200 区间
im3 = 255.0 * (im/255.0)**2 # 对图像像素值求平方后得到的图像
第一个例子将灰度图像进行反相处理;第二个例子将图像的像素值变换到 100…200 区间;第三个例子对图像使用二次函数变换,使较暗的像素值变得更小。
plt.axis('off')
plt.imshow(im1)
plt.axis('off')
plt.imshow(im2)
plt.axis('off')
plt.imshow(im3)
效果分别如下:
Matplotlib读取图像
从matplotlib
库中导入image
模块和pyplot
模块,image
模块用于读取图像,pyplot
模块用于显示图像,其中image
模块中的imread
方法直接将图像读取为一个数组。
import matplotlib.pyplot as plt
import matplotlib.image as img
import numpy as np
im = img.imread(r'./pictures/boy.jpg') #读取图像
print(im.shape)
plt.imshow(im) #图像显示
img.imsave(r'./pictures/boy.jpg',im) #图像保存
有了图像读取、显示、保存之后,可以开始numpy图像处理编程了。
CV2处理图像
与matplotlib
类似,cv2
库中的imread
方法直接将图片读取为一个数组。
import cv2
import numpy as np
#读入图像
im = cv2.imread(r'./pictures/boy.jpg',1)
# 1读取彩色图像,0读取灰度图像
# im 为一个numpy矩阵
#显示图像
cv2.imshow('boy',im)
cv2.waitKey() # 暂停cv2模块 不然图片窗口一瞬间即就会消失 观察不到
cv2.destroyWindow('boy')
# 复制图像
new_im = im.copy()
# 保存图像
cv2.imwrite("boy-new.png", new_im)
色彩变换
# new_im = cv2.cvtColor(old_im, cv2.COLOR_X2Y)
# 其中X,Y = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS
# 转为灰度图,得到的gray仍为一个数组,需要用imshow显示图像
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)
cv2.waitKey()
注意CV2读取的图片的通道是BGR
# BGR转RGB
im1 = cv2.cvtColor(im,cv2.COLOR_BGR2RGB)
# 分离通道
b,g,r = cv2.split(im)
#合 并通道
im2 = cv2.merge((b,g,r))
NumPy处理图像
图像裁剪
def imgCrop(im, x, y, w, h):
"""
image crop function.
im: source image
x: x of crop position
y: y of crop position
w: width of crop
h: height of crop
Return cropped image.
"""
img = im[x:np.clip(x+w,0,im.shape[0]),y:np.clip(y+h,0,im.shape[1])]
return img
# test
im = img.imread(r'.\pictures\boy.jpg')
plt.subplot(121)
plt.imshow(im)
plt.subplot(122)
im = imgCrop(im,600,400,400,300)
plt.imshow(im)
灰度变换
def imgGray(im):
"""
image gray
im: source image
Return gray image.
"""
img = np.array(im)
rows = im.shape[0]
cols = im.shape[1]
for i in range(rows):
for j in range(cols):
img[i, j, :] = (img[i, j, 0] * 0.299 + img[i, j, 1] * 0.587 + img[i, j, 2] * 0.114)
return img
#test
im = img.imread(r'.\pictures\boy.jpg')
im = imgGray(im)
plt.imshow(im)
图像二值化
def imgThreshold(im, threshold):
"""
im: source image
threshold: 0-255
Return blackwhite image.
"""
img = np.array(im)
rows = im.shape[0]
cols = im.shape[1]
for i in range(rows):
for j in range(cols):
gray = (img[i, j, 0] * 0.299 + img[i, j, 1] * 0.587 + img[i, j, 2] * 0.114)
if gray <= threshold :
img[i,j,:] = 0
else:
img[i,j,:] = 255
return img
#test
im = img.imread(r'.\pictures\boy.jpg')
im = imgThreshold(im, 128)
plt.imshow(im)