opencv保存视频格式(opencv视频图像识别方法)
opencv 是计算机视觉中经典的专用库,其支持多语言、跨平台,功能强大。opencv-python为opencv提供了python接口,使得使用者在python中能够调用c/c++,在保证易读性和运行效率的前提下,实现所需的功能。
一、安装
安装方法有多种,老猿机器上无c++环境,因此直接使用pip安装,opencv-python模块名为opencv-python(在windows下大小写不敏感,其他操作系统没验证),具体安装命令如下:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
二、加载opencv
导入opencv 模块指令很简单:
import cv2 as cv
大多数opencv 的函数都在cv2模块内,cv2并不是版本2.x的意思,而是因为这个版本是在原cv版本的基础上采用了面向对象编程的方式重新实现,提供了更好的api接口。
三、读取图像文件
3.1、语法:imread(filename,mode)
3.2、参数说明
- filename:图像文件名,不同操作系统支撑的文件类型不一样,但都支持bmp图像文件,另外可能还包括jpeg、png、tiff等格式文件
- mode:文件读入模式,常用有三种取值
- cv.imread_color: 对应值为1,加载彩色图像。任何图像的透明度都会被忽视。它是默认标志。
- cv.imread_grayscale:对应值为0,以灰度模式加载图
- cv.imread_unchanged:对应值为-1,加载图像,包括alpha通道;
注意:除了这三个常用取值,还可以有多个取值,相关取值及含义如下:
3.3 返回值说明
imread返回一个bgr格式的图像对象,其类型为一个numpy数组。
3.4、案例
img = cv2.imread(r’f:screenpicredflower.jpg’)
注意:
- 图片文件名不能是中文名,否则识别会报错或不能读入;
- imread会去除图像的alpha通道信息
四、显示图像
4.1、调用语法:imshow(title,img)
4.2、参数说明:
- title:图像显示窗窗口标题和名字
- img:opencv图像对象
imread读入的函数使用imshow即可显示,显示可以给显示窗设定标题,这个标题也是显示窗口的名字,标题不同的imshow会显示不同窗口。标题为一个英文字符串,相同标题的窗口就是同一个窗口。对于窗口,opencv提供鼠标及键盘事件处理机制。
imshow的窗口可以通过destroywindow和destroyallwindows进行关闭,前者要带窗口的标题,后者是关闭所有由当前程序创建的窗口。
4.3、案例
img = cv2.imread(r’f:screenpicredflower.jpg’)
cv2.imshow(‘img’,img)
五、videocapture读取摄像头、图像文件、或视频流
videocapture既支持从视频文件(.avi , .mpg格式)读取,也支持直接从摄像机(比如电脑自带摄像头)中读取。要想获取视频需要先创建一个videocapture对象,videocapture对象的创建方式有以下三种:
调用语法:
videocapture(int deviceindex,int apipreference = cap_any ):打开摄像头捕获视频。deviceindex为摄像头序列号,打开缺省摄像头传0,apipreference 为videocapture api后端标识符,老猿没有仔细研究,用缺省值即可
videocapture(filename,int apipreference = cap_any):打开filename指定的文件
更多videocapture的内容请参考《opencv学习—videocapture 类基础知识》。
下面的代码打开缺省摄像头捕获视频,并将捕获内容显示为窗口视频,并写入视频文件中保存,按q终止退出:
import cv2
def capturevideofromcamera():
cap = cv2.videocapture(0,cv2.cap_dshow)
width = 1920
height = 1920
filename = r’f:videomyvideo.avi’
fps = 24
cap.set(cv2.cap_prop_fps, 24)
# 建议使用xvid编码,图像质量和文件大小比较都兼顾的方案
fourcc = cv2.videowriter_fourcc(*’xvid’)
out = cv2.videowriter(filename, fourcc=fourcc, fps=fps,framesize=(width,height))
if not cap.isopened():
print(“cannot open camera”)
exit()
while true:
# 逐帧捕获
ret, frame = cap.read()
# 如果正确读取帧,ret为true
if not ret:
print(“can’t receive frame (stream end?). exiting …”)
break
frame = cv2.flip(frame, 1) # 水平翻转
ret = out.write(frame)
gray = cv2.cvtcolor(frame, cv2.color_bgr2gray)
# 显示结果帧e
cv2.imshow(‘frame’, frame)
if cv2.waitkey(1) == ord(‘q’): break
# 完成所有操作后,释放捕获器
out.release()
cap.release()
cv2.destroyallwindows()
capturevideofromcamera()
六、opencv-python的鼠标事件捕获
opencv提供了设置鼠标事件回调函数来提供鼠标事件处理的机制,设置回调函数的方法如下:
cv2.setmousecallback(winname, onmousefunction, param)
其中winname为要设置鼠标回调处理的窗口名,onmousefunction为回调函数,用于处理鼠标响应,param为设置回调函数时传入的应用相关特定参数,可以不设置,但需要在回调函数访问设置回调函数对象属性时非常有用。
示例:
cv2.namedwindow(‘image’)
cv2.setmousecallback(‘image’, draw_circle)
七、waitkey键盘事件处理
opencv提供了快速的键盘处理支持函数waitkey,调用语法:
retval = cv.waitkey( [, delay] )
其中:
- delay:等待键盘响应的时间,单位是毫秒,如果为0,则是一直等待到有键盘输入,否则就是等待对应时间还没有输入就超时返回
- retval:如果是超时返回-1,否则返回对应键盘按键的ascii码,但注意对于部分功能键如f1–f10返回值为0,其他功能键老猿未一一测试,可以确认esc键值可以正常返回(返回值27),ctrl+c返回3
八、opencv的矩形绘制
opencv提供了在图像中绘制几何图形的方法,绘制的图像包括矩形、椭圆、扇形、弧等。本文主要介绍矩形的绘制,具体调用语法如下:
rectangle(img, pt1, pt2, color, thickness=none, linetype=none, shift=none)
其中参数:
- img:要显示的图像,为numpy数组,格式为bgr格式
- pt1:左上角点的坐标
- pt2:右下角点的坐标
- color:绘制的颜色,为bgr格式的三元组,如(255,0,0)表示蓝色
- thickness:边框的厚度,如果为负数,则该矩形为实心矩形,否则为空心矩形
- linetype:线型,包括4连通、8连通以及抗锯齿线型,使用缺省值即可
- shift:坐标值的精度,为2就表示精确到小数点后2位
另外该方法还有个变种调用方式:
rectangle(img, rec, color[, thickness[, linetype[, shift]]]),其中的rec为上面pt1和pt2构建的矩形。
除了矩形,opencv还支持绘制点、直线、圆、椭圆、文本(不支持中文)等,具体可参考《使用python opencv处理图像之详解直线、圆、矩形及文字的绘制》,老猿就不展开介绍了。
下面的示例代码是打开视频播放,鼠标点击后暂停播放并在点击位置画圆,再次点击恢复播放:
import cv2
def mouseevent( event, x, y, flags, param):
if event == cv2.event_lbuttondown:
param[0] = not param[0]
param[1] = (x,y)
def playvideofile():
cap = cv2.videocapture(r’f:videozbl1.mp4′)
fps = 1
eventinf = [false,none]
frame = none
if not cap.isopened():
print(“cannot open camera”)
exit()
cv2.namedwindow(‘image’)
cv2.setmousecallback(‘image’, mouseevent,eventinf)
while true:
# 逐帧捕获
pause,mousepos = eventinf
if not pause:
ret, frame = cap.read()
if not ret:
if frame is none :
print(“the video has end.”)
else:
print(“read video error!”)
break
else:
if mousepos:
cv2.circle(frame, mousepos,60, (255,0,0),2)
cv2.imshow(‘image’, frame)
ch = cv2.waitkey(int(1000/fps))
if ch == ord(‘q’): break
cap.release()
cv2.destroyallwindows()
playvideofile()
九、opencv的颜色空间转换方法
cv2.cvtcolor是opencv提供的颜色空间转换函数,调用语法如下:
cvtcolor(src, code, dstcn=none)
其中:
- src:要转换的图像
- code:转换代码,表示从何种类型的图像转换为何种类型,如下面需要使用的cv2.color_bgr2gray就是将bgr格式彩色图像转换成灰度图片,具体转换代码请参考官网文档
- dstcn:目标图像的通道数,如果为0表示根据源图像通道数以及转换代码自动确认
更多内容请参考《学习opencv之cvtcolor》,示例请参考下面图像阈值处理部分的案例。
十、图像阈值处理
opencv图像的阈值处理又称为二值化,之所以称为二值化,是它可以将一幅图转换为感兴趣的部分(前景)和不感兴趣的部分(背景)。转换时,通常将某个值(即阈值)当作区分处理的标准,通常将超过阈值的像素作为前景。
阈值处理有2种方式,一种是固定阈值方式,又包括多种处理模式,另一种是非固定阈值,由程序根据算法以及给出的最大阈值计算图像合适的阈值,再用这个阈值进行二值化处理,非固定阈值处理时需要在固定阈值处理基础上叠加组合标记。
调用语法:
retval, dst = cv2.threshold (src, thresh, maxval, type)
其中:
- src:源图像,8位或32位图像的numpy数组
- thresh:阈值,0-255之间的数字,在进行处理时以阈值为边界来设不同的输出
- maxval:最大阈值,当使用固定阈值方法时为指定阈值,当叠加标记时为允许最大的阈值,算法必须在小于该值范围内计算合适的阈值
- type:处理方式,具体取值及含义如下:
- dst:阈值化处理后的结果图像numpy数组,其大小和通道数与源图像相同
- retval:叠加cv2.thresh_otsu或cv2.thresh_triangle标记后返回真正使用的阈值
案例:
ret, mask = cv2.threshold(img, 35, 255, cv2.thresh_binary|cv2.thresh_otsu)
补充说明:
- 阈值判断时,是以小于等于阈值和大于阈值作为分界条件
- 如果是32位彩色图像,则是以rgb每个通道的值单独与阈值进行比较,按每个通道进行阈值处理,返回的是一个阈值处理后的rgb各自的值。请参考《opencv阈值处理函数threshold处理32位彩色图像的案例》。
下面的代码生成一个图像的掩码图像:
def createimgmask(img):
# 创建img的掩码
if img is none:return none
if len(img.shape)>=3:
img2gray = cv2.cvtcolor(img, cv2.color_bgr2gray)
else:img2gray = img
ret, mask = cv2.threshold(img2gray, 35, 255, cv2.thresh_binary)
return mask
十一、adaptivethreshold自适应阈值化图像处理
上面介绍的threshold 函数的图像阈值处理对于某些光照不均的图像,这种全局阈值分割的方法会显得苍白无力。图像阈值化操作中,我们更关心的是从二值化图像中分离目标区域和背景区域,仅仅通过固定阈值很难达到理想的分割效果。在图片中的灰度是不均匀的,所以通常情况下图片中不同区域的阈值是不一样的。这样就需要一种方法根据图像不同区域亮度或灰度分布,计算其局部阈值来进行阈值处理。这种方法就是自适应阈值化图像处理,实际上这可以称为局部阈值法,在opencv中的adaptivethreshold就是这种方法。
调用语法:
adaptivethreshold(src, maxvalue, adaptivemethod, thresholdtype, blocksize, c, dst=none)
说明:
- src:源图像,必须是8位的灰度图
- dst:处理后的目标图像,大小和类型与源图像相同
- maxvalue:用于指定满足条件的像素设定的灰度值
- adaptivemethod:使用的自适应阈值算法,有2种类型adaptive_thresh_mean_c算法(局部邻域块均值)或adaptive_thresh_gaussian_c(局部邻域块高斯加权和),adaptive_thresh_mean_c的计算方法是计算出邻域的平均值再减去第六个参数c的值,adaptive_thresh_gaussian_c的计算方法是计算出邻域的高斯均匀值再减去第六个参数c的值。处理边界时使用border_replicate | border_isolated模式
- thresholdtype:阈值类型,只能是thresh_binary或thresh_binary_inv二者之一,具体参考上面“图像阈值处理”的表格
- blocksize:表示邻域块大小,用来计算区域阈值,一般选择3、5、7……
- c:表示常数,它是一个从均匀或加权均值提取的常数,通常为正数,但也可以是负数或零
- 返回值:处理后的图像
补充说明:
- 亮度较高的图像区域的二值化阈值通常会较高,而亮度较低的图像区域的二值化阈值则会相适应地变小
- 在灰度图像中,灰度值变化明显的区域往往是物体的轮廓,所以将图像分成一小块一小块的去计算阈值往往会得出图像的轮廓。因此函数adaptivethreshold除了将灰度图像二值化,也可以进行边缘提取
- 之所以能进行边缘提取,是因为当block很小时,如block_size=3 or 5 or 7时,“自适应”的程度很高,即容易出现block里面的像素值都差不多,这样便无法二值化,而只能在边缘等梯度大的地方实现二值化,结果显得它是边缘提取函数
- 当把blocksize设为比较大的值时,如blocksize=21 or 31 or 41时,adaptivethreshold便是二值化函数
- blocksize必须为大于1的奇数(原理老猿还没弄清楚) ,
- 如果使用平均值方法,平均值mean为180,差值delta为10,maxvalue设为255。那么灰度小于170的像素为0,大于等于170的像素为255,如果是反向二值化,灰度小于170的像素为255,大于等于170的像素为0
案例:
import cv2
img = cv2.imread(r’f:screenpic1.jpg’,cv2.imread_grayscale)
newimg = cv2.adaptivethreshold(img, 255, cv2.adaptive_thresh_mean_c, cv2.thresh_binary_inv, 3, 5)
cv2.imshow(‘img’,img)
cv2.imshow(‘newimg’,newimg)
cv2.waitkey(60000)
运行效果:
源图:
下面是分别设置不同块大小的结果图,左图块大小为31,右图为3:
可以看到blocksize小时,轮廓识别效果明显,而大时,就是一个二值化图像。
十二、opencv的图像修复方法
opencv中的cv2.inpaint()函数使用插值方法修复图像,调用语法如下:
dst = cv2.inpaint(src,mask, inpaintradius,flags)
参数含义如下:
- src:输入8位1通道或3通道图像
- inpaintmask:修复掩码,8位1通道图像。非零像素表示需要修复的区域
- dst:输出与src具有相同大小和类型的图像
- inpaintradius:算法考虑的每个点的圆形邻域的半径
- flags:修复算法标记,其中inpaint_ns表示基于navier-stokes方法,inpaint_telea表示alexandru telea方法。具体方法在此不展开介绍
下面的代码对一个包含亮色logo的图片进行去logo处理:
import cv2
def createimgmask(img):
# 创建img的掩码
if img is none:return none
if len(img.shape)>=3:
img2gray = cv2.cvtcolor(img, cv2.color_bgr2gray)
else:
img2gray = img
ret, mask = cv2.threshold(img2gray, 35, 255, cv2.thresh_binary)
return mask
def dellogfromimg(img):
imgmask = createimgmask(img)
imgmask = cv2.inpaint(img, imgmask , 3, cv2.inpaint_telea)
return imgmask
img1 = cv2.imread(r’f:templogo.jpg’)
img2 = cv2.imread(r’f:templogo.jpg’,cv2.imread_grayscale)
newimg1 = dellogfromimg(img1)
newimg2 = dellogfromimg(img2)
cv2.imshow(‘img1’,img1)
cv2.imshow(‘newimg1’,newimg1)
cv2.imshow(‘img2’,img2)
cv2.imshow(‘newimg2’,newimg2)
cv2.waitkey(60000)
执行截图1:
小结
本文详细介绍了opencv-python的安装、加载图像文件、捕获摄像头、显示图像、鼠标事件捕获、键盘事件处理、几何图像绘制、颜色空间转换、图像阈值处理、图像修复等基础知识,适合开始学习opencv-python的初学者。
推荐阅读