原标题:【OpenCV+Python】图像与视频处理入门
图像处理入门
之前我们已经讲过了OpenCV在各个平台上安装的方法了,从今天开始,正式进入实战部分。首先我们需要做的就是如何读取图像并显示出来,这是图像处理的最基本的部分。
首先我们来了解几个函数。
▼cv2.imread
我们看一下函数的原型:
retval=cv.imread(filename[, flags])
retval为自定义名称,filename指代需要加载的文件名,一般情况下,大多数时候,我们是直接加载文件的,所以大多时候我们直接读入图像就可以,但是在一些时候,我们想直接将原图转化为灰度图,从而方便后期的形态学处理操作,那么这个时候第二个参数的意义就表现出来了,第二个参数属于一个标志,它用于指定读取图像的方式。
总共有三种方式:
cv.IMREAD_COLOR:加载彩色图像。图像的任何透明度都将被忽略。这是默认标志。
cv.IMREAD_GRAYSCALE:以灰度模式加载图像。
cv.IMREAD_UNCHANGED:加载图像,包括alpha通道。
当然了,为了方便起见,它们也可以分别用1,0,-1进行表示。1指代原图也就是第一个函数;0指代第二个函数代表转为灰度图;-1则为第三个函数。
▼cv2.imshow
该函数用于在窗口中显示图像,窗口自动适合当前输入的图像尺寸,该函数与imread函数是相辅相成的,该函数原型为:
None=cv.imshow(winname, mat)
None为不需要填写,不用管它,我们直接用imshow就可以,winname是指你输出的图像的名称,可以自定义,但不要用中文名称,否则会乱码;mat则为你需要显示的图像。
此函数之后应是cv2.waitKey函数,该函数显示指定毫秒的图像。如果不使用waitkey函数,它将不会显示图像。例如,waitKey(0)将无限期显示窗口,直到任何按键为止(适用于图像显示)。waitKey(25)将显示25毫秒的帧,此后将自动关闭显示。
另一个函数cv2.destroyAllWindows会销毁我们创建的所有窗口。 如果要销毁任何特定的窗口,请使用函数 cv.destroyWindow在其中传递确切的窗口名称作为参数。
我们现在来做一个实验,先显示最基本的图像(代码图中都有):
现在我们改变读入的图像为灰度,mread函数的最后一个参数可以进行相关方面的操作,当为0时:
当为1时:
若为-1时:
现在输出的图像的窗口大小是固定的,那么加入我们想要调整窗口的大小,那就需要使用另一个函数,在特殊情况下,我们可以创建一个空窗口,然后再将图像加载到该窗口。在这种情况下,可以指定窗口是否可调整大小。
这是通过功能cv.namedWindow完成的,现在我们实验一下:
当我们在函数后加一个0,则可以用鼠标手动调整输出图像的大小,这将非常方便。事实上,0对应的参数为cv2.WINDOW_NORMAL,即为自动调整图像,我们大致了解一下相关的参数:
WINDOW_NORMAL 或WINDOW_AUTOSIZE: WINDOW_NORMAL可以调整窗口大小,而WINDOW_AUTOSIZE会自动调整窗口大小以适合显示的图像(请参见imshow),并且不能手动更改窗口大小。
WINDOW_FREERATIO 或WINDOW_KEEPRATIO: WINDOW_FREERATIO调整图像时不考虑其比例,而WINDOW_KEEPRATIO则保持图像比例。
WINDOW_GUI_NORMAL 或WINDOW_GUI_EXPANDED: WINDOW_GUI_NORMAL是绘制没有状态栏和工具栏的窗口的旧方法,而WINDOW_GUI_EXPANDED是新的增强型GUI。 默认标 志 = = WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | WINDOW_GUI_E XPANDED
假若我们想将处理之后的图像保存起来,保存到文件夹中,那么就需要用到cv2.imwrite函数。
▼cv2.imwrite
imwrite函数将图像保存到指定文件。图像格式是根据文件扩展名选择的(扩展名列表请参见cv :: imread)。通常,使用此功能只能保存8位单通道或3通道(具有“ BGR”通道顺序)图像,但以下情况除外:
对于PNG,JPEG 2000和TIFF格式,可以保存16位无符号(CV_16U)图像。
可以以PFM,TIFF,OpenEXR和Radiance HDR格式保存32位浮点(CV_32F)图像;使用LogLuv高动态范围编码(每像素4个字节)将保存3通道(CV_32FC3)TIFF图像。
使用此功能可以保存带有Alpha通道的PNG图像。为此,创建8位(或16位)4通道图像BGRA,其中alpha通道位于最后。完全透明的像素应将alpha设置为0,完全不透明的像素应将alpha设置为255/65535。
该函数原型为:
retval=cv.imwrite(filename, img[, params])
第一个参数是文件名,第二个参数是要保存的图像。现在我们写个综合代码:
import numpy as np
import cv2 as cv
img = cv.imread('cat.jpg', 0)
cv.imshow('image', img)
k = cv.waitKey(0) & 0xff
if k == 27: # wait for ESC key to exit
cv.destroyAllWindows
elif k == ord('s'): # wait for 's' key to save and exit
cv.imwrite('cat.png', img)
cv.destroyAllWindows
在上面的程序中,以灰度加载图像,显示图像,按下键盘的“ s”键保存图像并退出,或者按ESC键直接退出而不保存。我们按下s实验:
图像保存完毕。
那么图像处理的入门部分算是正式结束了,这也是基础中的基础,后续都将非常有用。
视频处理入门
视频处理在OpenCV中处于极为重要的地位,目标实时跟踪等各种实时图像处理算法都是以视频为基础。
01
从相机捕获视频
首先我们来了解一下使用电脑自带的相机来进行捕获视频。通常,我们必须使用摄像机捕获实时流。OpenCV提供了一个非常简单的界面来执行此操作。让我们从相机捕获视频(我使用笔记本电脑上的内置网络摄像头),我们需要了解几个函数:
▼cap = cv2.VideoCapture(0)
VideoCapture中参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频,如cap = cv2.VideoCapture("../test.avi"),当然了,如果你外接的有其他的摄像头,那就可以选用其他的参数例如1从而调用它。
▼ret,frame = cap.read
cap.read按帧读取视频,ret,frame是获取cap.read方法的两个返回值。其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵,我们都知道视频是由一帧一帧的图像连续组成的,OpenCV在对图像处理时就是对每一帧的图像进行快速处理。
▼cv2.waitkey
waitKey方法本身表示等待键盘输入,参数是1,表示延时1ms切换到下一帧图像,对于视频而言;参数为0,如cv2.waitKey(0)只显示当前帧图像,相当于视频暂停,;参数过大如cv2.waitKey(1000),会因为延时过久而卡顿感觉到卡顿。
c得到的是键盘输入的ASCII码,esc键对应的ASCII码是27,即当按esc键是if条件句成立。
▼ release
调用release释放摄像头,调用destroyAllWindows关闭所有图像窗口。
现在我们首先进行代码实验,之后会进行一些说明:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened:
print("Cannot open camera")
exit
while True:
# Capture frame-by-frame
ret, frame = cap.read
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
# gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release
cv.destroyAllWindows
isOpened可以确定摄像头是否被打开,如果打开则继续,如果未成功打开则自动退出。前面的时候我们已经讲过,frame所指代的,就是摄像头视频的每一帧图像,所以在显示时,我们也是显示每一帧。如果对每一帧图像都进行灰度化处理,那么所显示的视频就是灰度化视频,当然,关于灰度化现在还没有讲到,但是可以先做个小实验,我们来看代码:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened:
print("Cannot open camera")
exit
while True:
# Capture frame-by-frame
ret, frame = cap.read
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release
cv.destroyAllWindows
大家自己实验,体验一下效果。或许有的人已经发现了,我们的视频跟实际中好像是相反的,属于镜像效果,我们可以取消这种效果,在这里需要介绍一个函数,后面在图像增强部分也会介绍到:
▼cv2.flip
函数原型:flip(src, flipCode[, dst])
src代表输入的图像,我们来看一下flipCode的参数表:
现在我们加入这行代码:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened:
print("Cannot open camera")
exit
while True:
# Capture frame-by-frame
ret, frame = cap.read
frame = cv.flip(frame, 1)
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release
cv.destroyAllWindows
再实验会发现图像已经没有那种镜像效果了。
02
从文件播放视频
从文件播放视频与从摄像机捕获视频相同,只是将摄像机索引更改为视频文件名。另外,在显示框架时,请使用适当的时间cv.waitKey。如果太少,则视频将非常快,而如果太高,则视频将变得很慢(嗯,这就是显示慢动作的方式)。正常情况下25毫秒就可以了。
给出实例代码:
import cv2 as cv
cap = cv.VideoCapture('test.avi')
while cap.isOpened:
ret, frame = cap.read
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
cv.imshow('frame', frame)
if cv.waitKey(25) == ord('q'):
break
cap.release
cv.destroyAllWindows
03
保存视频
当我们想要保存图像的时候,这非常简单:只需使用cv2.imwrite。而当我们想要保存视频的时候,需要做更多的工作。
这次我们创建一个VideoWriter对象。我们应该指定输出文件名(例如:output.avi)。然后,我们应指定FourCC代码(下一段中的详细信息)。然后应传递每秒的帧数(fps)和帧大小。最后一个是isColor标志。如果为True,则编码器需要彩色框,否则将与灰度框一起使用。
FourCC是一个4字节的代码,用于指定视频编码器以及****。可用代码列表可在fourcc.org中找到,它取决于平台。
在Fedora中:DIVX,XVID,MJPG,X264,WMV1,WMV2。(最好使用XVID。MJPG可以生成大尺寸的视频。X264提供非常小的尺寸的视频)
在Windows中: DIVX(尚待测试和添加)。
在OSX中: MJPG(.mp4),DIVX(.avi),X264(.mkv)。
FourCC代码作为MJPG的`cv.VideoWriter_fourcc('M','J','P','G')or cv.VideoWriter_fourcc(*'MJPG')`传递。
以下代码从摄像机捕获,在垂直方向上翻转每一帧,然后保存视频:
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened:
ret, frame = cap.read
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 1)
# write the flipped frame
out.write(frame)
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
# Release everything if job is finished
cap.release
out.release
cv.destroyAllWindows
大家可以自己尝试演示效果。
视频处理的部分基本上就结束了,以上介绍到的将是以后学习中非常重要的基础。而事实上,OpenCV中对于视频的处理也有更多的操作,现在介绍最后一个函数:
▼VideoCapture.get
由于前面我们已经指定cap = cv.VideoCapture(0),所以调用此函数只需用cap.get,get中将传入参数,给出参数表:
共有18个参数,而至于相关的代码,请大家自己实验,可以使用print函数输出视频的详细信息。返回搜狐,查看更多
责任编辑: