图像入门
使用PLT读取图像
Pillow -> Python Imaging Library
Image模块
打开和新建
Image.open(fp,mode)
打开图像,执行返回Image类的实例。如果文件不存在,会引发IOError错误
- fp:打开文件的路径
- mode:打开文件的方式,通常使用默认值r
Image.new(mode,size,color=0)
新建图像
- mode:图像模式
- size:图片尺寸,是使用宽和高两个元素构成的元祖
- color:默认颜色(黑色)
mode(模式) | bands(通道) | 说明 |
---|---|---|
“1” | 1 | 黑白二值图像,每个像素用0或者1共1位二进制代码表示 |
“RGB” | 3 | 24位真彩图,每个像素用3个字符的二进制代码表示 |
“RGBA” | 4 | “RGB”+透明通道表示,每个像素用4字符的二进制代码表示 |
“CMYK” | 4 | 印刷模式图像,每个像素用4字符的二进制代码表示 |
“LAB” | 3 | lab颜色空间,每个像素用3字符的二进制代码表示 |
“HSV” | 3 | 每个像素用3字符的二进制代码表示 |
from PIL import Image
#打开图片
img=Image.open('bjsxt.png')
#显示图片
# img.show()
print('图片的格式:',img.format) # PNG
print('图片的大小:',img.size) # (437, 196)
print('图片的高度:',img.height,'图片的宽度:',img.width) # 图片的高度: 196 图片的宽度: 437
print('获取(100,100)处像素值:',img.getpixel((100,100))) # 获取(100,100)处像素值: (188, 193, 133)
混合
Image.blend(im,im2,alpha)
透明度混合处理
Image.composite(im1,im2,mask)
遮罩混合处理
from PIL import Image
img1=Image.open('bjsxt.png').convert(mode='RGB')
img2=Image.new('RGB',img1.size,'red')
Image.blend(img1,img2,alpha=0.5).show()
img1=Image.open('blend1.jpg')
img2=Image.open('blend2.jpg')
img2=img2.resize(img1.size)
r,g,b=img2.split()
Image.composite(img2,img1,b).show()
复制和缩放
copy()
复制指定的图片
Image.eval(img,fun)
像素值缩放处理
Image.thmbnail(size,resample=3)
原生地缩放指定的图像
Image.resize(size, Image.ANTIALIAS)
antialias抗锯齿
from PIL import Image
#按像素缩放图片
img1= Image.open('bjsxt.png')
#.将每个像素值都扩大2倍
Image.eval(img1,lambda x:x*2).show()
img2=img1.copy()
#按尺寸进行缩放图片
img2.thumbnail((200,160)).show()
粘贴和裁剪
Image.paste(im,box=None,mask=None)
粘贴
- im 是源图像或像素值
- box 粘贴区域
- (x1,y1):将源图像左上角对齐(x1,y1)点,其余超出被粘贴图像的区域被抛弃
- (x1,y1,x2,y2):源图像与次区域必须一致
- None:源图像与粘贴的图像大小必须一致
- mask 遮罩
Image.crop(box)
box=(int(left),int(top),int(right),int(bottom))
裁剪图像
这个元组参数包含四个值,分别代表矩形四条边的距离X轴或者Y轴的距离。顺序是(左,顶,右,底)
from PIL import Image
img=Image.open('bjsxt.png')
#复制
imgb=img.copy()
imgc=img.copy()
#剪切
img_crop=imgb.crop((10,10,120,120))
#粘贴
imgc.paste(img_crop,(30,30))
imgc.show()
图像旋转和转换位置
Image.rotate(angle,resample=0,expand=0,center=None,translate=None,fillcoloor=None)
旋转图像
Image.covert(mode=None,matrix=None,dither=None,palette=0,colors=256)
图像转换
Image.transpose(method)
转换位置
- PIL.Image.FLIP_LEFT_RIGHT:左右镜像
- PIL.Image.FLIP_TOP_BOTTOM :上下镜像
- PIL.Image.ROTATE_90:旋转 90
- PIL.Image.ROTATE_180:旋转 180
- PIL.Image.TRANSPOSE :颠倒顺序
from PIL import Image
img=Image.open('bjsxt.png')
#图像的旋转
# img.rotate(180).show()
#格式转换
# img.transpose(Image.FLIP_TOP_BOTTOM).show() # 上下滤镜
# img.transpose(Image.FLIP_LEFT_RIGHT).show() # 左右滤镜
# img.transpose(Image.ROTATE_90).show() # 90滤镜
# img.transpose(Image.ROTATE_180).show() # 180滤镜
img.transpose(Image.TRANSPOSE).show() # 颠倒滤镜
分离和合并
Iamage.split()
分割多个通道列表
Image.merge(mode,bands)
合并到更多通道图像中
from PIL import Image
img1=Image.open('blend1.jpg')
img2=Image.open('blend2.jpg')
img2=img2.resize(img1.size)
#分隔
r1,g1,b1=img1.split()
r2,g2,b2=img2.split()
temp=[r1,g2,b1]
img=Image.merge('RGB',temp)
img.show()
其他内置参数
常用属性
Image.format
源图像格式Image.mode
图像模式字符串Image.size
图像尺寸
内置函数
-
Image.gethands()
获取图像每个通道的名称列表,例如RGB图像返回[‘R’,'G,'B] -
Image.getextrema()
获取图像最大、最小像素的值 -
Image.crop(int(left),int(top),int(right),int(bottom))
图片裁剪region=im.crop((100,100,500,500))
-
Image.getpixel(x,y)
获取像素点值im.getpixel((4,4))
-
Image.putpixel((x,y),(r,g,b))
写入像素点值img.putpixel((4,4),(255,0,0))
-
Image.point(function)
使用函数修改图像的每个像素out=img.point(lambda i:i*1.5)
对每个点进行50%的加强 -
Image.histogram(mask=None,extrema=None)
获取图像直方图,返回像素计数的列表 -
Image.putalpha(alpha)
添加或替换图像的alpha层 -
Image.blend(img1,img2,alpha)
两张图片相加 -
Image.save(fp,format=None,**params)
保存图片 -
Image.show(title=None,command=None)
显示图片 -
Image.transform(size,method,data=None,resample=0,fill=1)
变换图像 -
Image.verify()
检验文件是否损坏 -
Image.close()
关闭文件
其它模块
-
ImageFilter模块
image.filter(滤镜效果)
- ImageFilter.EMBOSS 浮雕效果
- ImageFilter.CONTOUR 铅画笔
- ImageFilter.BLUR 模糊效果
- ImageFilter.EDGE_ENHANCE 边界增强
-
ImageDraw模块
draw.point(坐标, 颜色)
- 坐标:两个元组的序列
[(x, y), (x, y), ...]
或类似的数值[x, y, x, y, ...]
draw.line(起始坐标+终点坐标, 颜色, 宽度)
- 坐标:两个元组的序列
[(x, y), (x, y), ...]
或类似的数值[x, y, x, y, ...]
draw.rectangle(坐标,填充颜色,轮廓颜色,宽度)
- 坐标: 任何一个的序列
[(x0, y0), (x1, y1)]
或[x0, y0, x1, y1]
draw.textsize(要测量的文本,font)
- 坐标:两个元组的序列
-
ImageFont模块
ImageFont.truetype(字体文件, 字号)
draw.text(坐标, 文字内容, fill=文字颜色, font=字体对象 )
随机验证码
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from random import randint
class L_BLUR(ImageFilter.BuiltinFilter):
name = "l_blur"
filterargs = (5, 5), 16, 0, (
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1,
)
# random.randint(M, N) 产生一个M到N的随机整数
def rand_img_color():
return randint(0,255), randint(0,255), randint(0,255)
def rand_num_color():
return randint(0,127), randint(0,127), randint(0,127)
def rand_zh():
return chr(randint(0x4E00,0x9FBF))
def rand_char():
# 小写字母
return chr(randint(97,122))
# 大写字母
# return chr(randint(65,90))
def rand_num():
return str(randint(0,9))
# 1.创建空图片
image = Image.new('RGB',(120,60),(255,255,255))
draw = ImageDraw.Draw(image)
# 2.渲染背景
for x in range(0,120):
for y in range(0,60):
draw.point((x, y), rand_img_color())
w, h = (image.size)
draw.line((w/4,0) + (w/4,h), fill=rand_img_color(), width=3)
draw.line((w/2,0) + (w/2,h), fill=rand_img_color(), width=3)
draw.line((w/4*3,0) + (w/4*3,h), fill=rand_img_color(), width=3)
draw.line((0,h/2) + (w,h/2), fill=rand_img_color(), width=3)
image = image.filter(L_BLUR)
# 3.渲染文字
font = ImageFont.truetype('simhei.ttf', 30)
draw = ImageDraw.Draw(image)
for x in range(4):
y = randint(10,30)
draw.text((30*x,y), rand_num(), rand_num_color(), font)
image.show()
使用OpenCV读取图像
-
cv.imread()
读取图像第一个参数是路径
第二个参数是一个标志,指定读取图像的方式,如下:
cv.IMREAD_COLOR
:可以传递整数1,加载彩色图像。任何图像的透明度都会忽视。默认cv.IMREAD_GRAYSCALE
:可以传递整数0,以灰度模式加载图像cv.IMREAD_UNCHANGED
:可以传递整数-1,加载图像,包括alpha通道
即使图像路径错误,它也不会引发任何错误,但是
print(img) -> None
-
cv.imshow()
显示图像第一个参数是窗口名称,字符串类型
第二个参数是我们的读取的图片
cv.namedWindow
调整指定窗口大小cv.WINDOW_NORMAL
默认cv.WINDOW_NORMAL
可以调整窗口大小
cv.waitKey()
键盘绑定函数,其参数以毫秒为单位的时间cv.destoryAllWindows()
破坏我们创建的所有窗口 -
cv.imwrite()
保存图像第一个参数是文件名
第二个参数是要保存的图像
import cv2 as cv
import numpy as np
#加载灰度图像
img = cv.imread('messi5.jpg',0)
#cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image', img)
k = cv.waitKey(0)
if k == 27; # 等待ESC退出 KeyCode
cv.destoryAllWindows()
elif k == ord('s'): # 等待关键字,保存和退出
cv.imwrite('messigray.png', img)
cv.destoryAllWindows()
切割图片
先用np.fromfile()
读取为np.uint8
格式,再使用cv2.imdecode()
解码
import cv2
import numpy as np
# cv2.imread路径为中文时返回None
# 读取图像,解决imread不能读取中文路径的问题
img = cv2.imdecode(np.fromfile(image_path,dtype=np.uint8),-1)
cropped = img[coor_y1:coor_y2,coor_x1:coor_x2]
cv2.imencode('.jpg', cropped)[1].tofile(save_path)
各种图像转换
OpenCv使用BGR格式,PIL使用的是RGB格式
img.reshape(2,-1)
转换成两行
img.reshape(-1,2)
转换成两列
img.resize((width, height),Image.ANTIALIAS)
- Image.NEAREST :低质量
- Image.BILINEAR:双线性
- Image.BICUBIC :三次样条插值
- Image.ANTIALIAS:高质量
img = cv2.imdecode(np.fromfile(image_path,dtype=np.uint8),-1)
# 输出图像每个BGR像素值,转换成列表可一一遍历出来
img.reshape(-1,3)
# 更改图片大小
img_small = cv2.resize(img (320,180), interpolation=cv2.INTER_NEAREST)
img_height, img_width = img.shape
# 转RGB图
img_rgb = np.zeros((img_height, img_width), dtype=np.uint8)
图片信息
img.shape
它返回一组行、列和通道的元组 (如果图像是彩色的)
img.dtype
获得图像数据类型
# img.shape: (480, 640, 3)
img.shape[0] = height: 480
img.shape[1] = width: 640
img.shape[2] = channel: 3
print(img.dtype) # uint8
# 由于图片格式是BGR格式,需要把RGB转换成BGR
file = codecs.open(file_path, 'r', 'utf-8')
color_dict = {}
for line in file:
label_id, scene, color = line.strip().split('\t')
color_dict[(int(color.split(',')[2]), int(color.split(',')[1]), int(color.split(',')[0]))] = int(label_id)
# 读取每一个像素点色值
color_set = {}
for img_color in list(img.reshape(-1,3)):
if tuple(list(img_color)) not in color_set:
color_set[tuple(list(img_color))] = 1
# print(img_color)
# 获取颜色近似值
def get_similar_color(color, color_list):
dist_min = 3
for c in color_list:
sim_color = color
distance = (c[0]-color[0])**2 + (c[1]-color[1])**2 + (c[2]-color[2])**2
if distance <= dist_min:
sim_color = c
print(sim_color)
return sim_color
get_similar_color((1, 1, 1), color_dict)
使用Matplotlib 读取图像
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messo5.jpg', 0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
# 隐藏 x 轴和 y 轴的刻度值
plt.xticks([]),plt.yticks([])
plt.show()
使用OpenCV读取视频
-
要捕获视频,需要创建一个 VideoCapture 对象,它的参数可以是设备索引(哪个摄像头的名字)或视频文件的名称
FourCC
全称Four-Character Codes
,代表四字符代码, 它是一个32位的标示符,其实就是typedef unsigned int FOURCC
;是一种独立标示视频数据流格式的四字符代码。cv2.VideoWriter_fourcc()
函数的作用是输入四个字符代码即可得到对应的视频编码器 -
cap.read()
返回布尔值(True/False),如果帧读取的是正确的,就是True。所以可以通过检查他的返回值来查看视频文件是否已经到了结尾 -
cap.isOpened()
,来检查是否成功初始化,如果返回值是True,那就没有问题。否则就要使用函数cap.open()
。你可以使用函数cap.get(propId)
来获得视频的一些参数信息。这里propId可以是0到18的任何整数。每一个数代表视频的一个属性 -
你要想设置新值,例如:可以使用
cap.get(3)
和cap.get(4)
来查看每一帧的宽和高。默认情况下得到的值是 640×480。但是我们可以使用ret=cap.set(3,320)
和ret=cap.set(4,240)
来把宽和高改成 320×240
import numpy as np
import cv2 as cv
cap = cv.VideoCapture('vtest.avi')
# 使用XVID编码器
fourcc = cv.VideoWriter_fourcc(*'XVID')
# 保存文件名 编码器 帧率 视频宽高
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,480))
while cap.isOpened():
# 逐帧捕获
ret, frame = cap.read()
# 如果正确读取帧, ret为True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 0)
out.imshow('frame', frame)
# gray = cv.cvtColor(frame, cv_COLOR_BGR2GRAY)
# 显示结果帧
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# 完成所有操作后,释放捕获器
cap.release()
out.release()
cv.destroyAllWindows()
获取视频、帧率、分辨率等属性
参数 | propld | 功能 |
---|---|---|
cv2.CAP_PROP_POS_MSEC | 0 | 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳 |
cv2.CAP_PROP_POS_FRAMES | 1 | 基于0的索引将被解码/捕获下一帧 |
cv2.CAP_PROP_POS_AVI_RATIO | 2 | 视频文件的相对位置:0 - 视频的开始,1 - 视频的结束 |
cv2.CAP_PROP_FRAME_WIDTH | 3 | 帧的宽度 |
cv2.CAP_PROP_FRAME_HEIGHT | 4 | 帧的高度 |
cv2.CAP_PROP_FPS | 5 | 帧速 |
cv2.CAP_PROP_FOURCC | 6 | 4个字符表示的视频编码器格式 |
cv2.CAP_PROP_FRAME_COUNT | 7 | 帧数 |
cv2.CAP_PROP_FORMAT | 8 | byretrieve()返回的Mat对象的格式 |
cv2.CAP_PROP_MODE | 9 | 指示当前捕获模式的后端特定值 |
cv2.CAP_PROP_BRIGHTNESS | 10 | 图像的亮度(仅适用于相机) |
cv2.CAP_PROP_CONTRAST | 11 | 图像对比度(仅适用于相机) |
cv2.CAP_PROP_SATURATION | 12 | 图像的饱和度(仅适用于相机) |
cv2.CAP_PROP_HUE | 13 | 图像的色相(仅适用于相机) |
cv2.CAP_PROP_GAIN | 14 | 图像的增益(仅适用于相机) |
cv2.CAP_PROP_EXPOSURE | 15 | 曝光(仅适用于相机) |
cv2.CAP_PROP_CONVERT_RGB | 16 | 表示图像是否应转换为RGB的布尔标志 |
cv2.CAP_PROP_WHITE_BALANCE | 17 | 目前不支持 |
cv2.CAP_PROP_RECTIFICATION | 18 | 立体摄像机的整流标志 |
cap = cv2.VideoCapture(video_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
frame_all = cap.get(cv2.CAP_PROP_FRAME_COUNT)