2.1 基本IO脚本
2.1.1 读/写图像文件
主要关注颜色空间变换
def convertColorSpace():
""""
图像颜色空间转换
"""
# 创建3*3大小的黑色正方形图像
img = np.zeros((3, 3), dtype=np.uint8)
print('Black Image\n', img)
# 将灰度图转化为BGR颜色空间的彩色图,输出为三通道
img = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
print('BGR Image\n', img)
- 读写图片:OpenCV中的imread()函数和imwrite()函数(支持静态图像文件格式,不同系统支持的文件格式不一样,但都支持BMP格式,通常还支持PNG\JPEG和TIEF格式)
- 主要关注读取图片时,原图片和读取后数据的变化,及写入图片时位深和透明通道的处理
def readWriteImage():
""" 读写图片
imread()函数,默认情况下,即使图片为灰度图,依旧返回BGR格式的图片
(除IMREAD_UNCHANGED,IMREAD_LOAD_GDAL情况下,会删除alpha通道信息)
其可选参数flags:
IMREAD_UNCHANGED = -1 用图片的原来格式打开, 位深不变, 通道数不变
IMREAD_GRAYSCALE = 0 用灰度图像的方式打开图片, 位深8bit, 通道数1
IMREAD_COLOR = 1 用彩色图像打开图片, 位深8bit, 通道数3
IMREAD_ANYDEPTH = 2 用灰度图像的方式打开图片, 位深不变, 通道数1
IMREAD_ANYCOLOR = 4 用图片的原来格式打开, 位深8bit, 通道数不变但<=3
IMREAD_LOAD_GDAL = 8 使用GDAL驱动读取文件, 位深不变, 通道数不变
"""
# 图片原始位深位16位,4通道数
imgPath = './images/img1.png'
# 默认情况
img = cv.imread(imgPath)
print('默认情况:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_UNCHANGED
img = cv.imread(imgPath, cv.IMREAD_UNCHANGED)
print('IMREAD_UNCHANGED:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_GRAYSCALE
img = cv.imread(imgPath, cv.IMREAD_GRAYSCALE)
print('IMREAD_GRAYSCALE:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_COLOR
img = cv.imread(imgPath, cv.IMREAD_COLOR)
print('IMREAD_COLOR:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_ANYDEPTH
img = cv.imread(imgPath, cv.IMREAD_ANYDEPTH)
print('IMREAD_ANYDEPTH:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_ANYCOLOR
img = cv.imread(imgPath, cv.IMREAD_ANYCOLOR)
print('IMREAD_ANYCOLOR:', '位深', img.dtype, ',通道数', img.shape)
# IMREAD_LOAD_GDAL
img = cv.imread(imgPath, cv.IMREAD_LOAD_GDAL)
print('IMREAD_LOAD_GDAL:', '位深', img.dtype, ',通道数', img.shape)
# print(img[:, : 3])
# 写入16位深,通道数4的图像数据,返回bool值
# JPG、BMP存储的视频是unit8位深 RGB编码的,写入时将RGB三通道都用depth填充
# PNG允许每个通道8位位深或16位位深
cv.imwrite('./images/MyErrorJPGImg1.jpg', img)
cv.imwrite('./images/MySucceedPNGImg1.png', img)
# 位深分离,16位->8位
cv.imwrite('./images/MySucceedJPGImg1.jpg', img // 255)
2.1.2 图像与原始字节之间的转换
主要就是形状的变化,reshape
def rawBytesImage():
# 返回随机字节
randomByteArray = bytearray(os.urandom(120000))
flatNumpyArray = np.array(randomByteArray)
# 将字节数组转换为400*300的灰度图片
grayImg = flatNumpyArray.reshape((300, 400))
cv.imwrite('./images/RandomGray.png', grayImg)
# 将字节数组转换为400*100*3的彩色图片
colorImg = flatNumpyArray.reshape((100, 400, 3))
cv.imwrite('./images/RandomColor.png', colorImg)
2.1.3 使用numpy.array访问图像数据
以前没注意item用法,但索引用法更方便和趁手,切片对区域的操作也更友好,时间无差
def acccessImageData():
# 使用item的方式
img = cv.imread('./images/img1.png')
print(img.item(150, 120, 0))
itemStart = time.time()
img.itemset((150, 120, 0), 255)
itemEnd = time.time()
print(img.item(150, 120, 0), 'itme time is', itemEnd - itemStart)
# 使用索引和切片的方式
sliceStart = time.time()
img[150,120, 0] = 254
sliceEnd = time.time()
print(img.item(150, 120, 0), 'itme time is', sliceEnd - sliceStart)
2.1.4 视频文件的读/写
OpenCV提供VideoCapture类和VideoWriter类支持各种格式的视频文件,
文件指针到达文件末尾前,VideroCapture的read()函数获取新帧
主要关注读写函数,视频帧率、尺寸的获取与设置,及视频编码操作
def videoReadWrite():
"""
cv.VideoWriter_fourcc('I','4','2','0') = 未压缩YUV颜色编码,4:2:0色度子采样
cv.VideoWriter_fourcc('M','J','P','G') = motion-jpeg 编码
cv.VideoWriter_fourcc('P','I','M','1') = MPEG-1 编码
cv.VideoWriter_fourcc('M', 'P', '4', '2') = MPEG-4.2 编码
cv.VideoWriter_fourcc('D', 'I', 'V', '3') = MPEG-4.3 编码
cv.VideoWriter_fourcc('D', 'I', 'V', 'X') = MPEG-4 编码
cv.VideoWriter_fourcc('U', '2', '6', '3') = H263 编码
cv.VideoWriter_fourcc('I', '2', '6', '3') = H263I 编码
cv.VideoWriter_fourcc('F', 'L', 'V', '1') = FLV1 编码
"""
# 参数为0时,表示摄像头设备0
videoFile = cv.VideoCapture('./videos/test.mp4')
success, frame = videoFile.read()
# 获取视频帧率
fps = videoFile.get(cv.CAP_PROP_FPS)
# 获取视频尺寸
size = (int(videoFile.get(cv.CAP_PROP_FRAME_WIDTH)), int(videoFile.get(cv.CAP_PROP_FRAME_HEIGHT)))
# 写入新视频文件中,cv.VideoWriter_fourcc('F', 'L', 'V', '1')指定视频编码
videoWriter = cv.VideoWriter('./videos/ccNew.flv', cv.VideoWriter_fourcc('F', 'L', 'V', '1'), fps, size)
while success:
videoWriter.write(frame)
success, frame = videoFile.read()
2.1.5 捕获摄像头的帧
def capFromCam():
cap = cv.VideoCapture(0)
# 假设帧率为30
fps = 25
# 获取视频尺寸
size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
# 写入新视频文件中,cv.VideoWriter_fourcc('F', 'L', 'V', '1')指定视频编码
videoWriter = cv.VideoWriter('./videos/capFromCam.flv', cv.VideoWriter_fourcc('F', 'L', 'V', '1'), fps, size)
success, frame = cap.read()
# 存储10秒的摄像头图像
numFramRema = 10 * fps - 1
while success and numFramRema > 0:
videoWriter.write(frame)
success, frame = cap.read()
numFramRema -= 1
cap.release()
# 两个摄像头
def multiCam():
cap0 = cv.VideoCapture(0)
cap1 = cv.VideoCapture(1)
success0 = cap0.grab()
success1 = cap1.grab()
if success0 and success1:
print("没有两个摄像头")
frame0 = cap0.retrieve()
frame1 = cap1.retrieve()
if success0:
print('捕捉到摄像头0')
su, frame0 = cap0.retrieve()
cap0.release()
cv.imshow('cam1', np.asarray(frame0))
cv.waitKey()
# cv2.destroyAllWindows()
2.1.7 在窗口显示摄像头帧
def showCamFrame():
clicked = False
# 鼠标点击事件回调
def onMouse(event, x, y, flags, param):
global clicked
if event == cv.EVENT_LBUTTONUP:
clicked = True
print(clicked)
cap = cv.VideoCapture(0)
cv.namedWindow('Myself')
cv.setMouseCallback('Myself', onMouse)
print('点击窗口或按任意键退出')
sucess, frame = cap.read()
while sucess and cv.waitKey(1) == -1 and not clicked:
cv.imshow('Myself', frame)
sucess, frame = cap.read()
cv.destroyAllWindows()
cap.release()
参考自《OpenCV3计算机视觉 Python语言实现》