源网页
使用 cv.imread() 来读取一张图片。这个图片给予的路径应该是在工作目录中或者使用完整路径
第二个参数是一个flasg来指定图片的读取方式
注意:
你可以用简单的证书 1,0,-1来代替这些flag
示例:
import numpy as np
import cv2 as cv
# Load an color image in grayscale
img = cv.imread('messi5.jpg',0)
warning
即使图片路径是错误的,它也不会引发异常,但是 print img 会返回 None
展示一个图片
使用方法 cv.imshow()会在一个窗口里面显示一张图片。窗口会自动适应图片的大小。
第一个参数:字符串,是窗口的名字。
第二个参数是我们的图片。你可以创建多个不同名字的窗口展示同一个图片
cv.imshow('image',img)
cv.waitKey()
cv.destoryAllWindows()
图片的截图看起来将会是这个样子
cv.waitKey()是一个键盘绑定函数。他的参数是时间单位是毫秒。这个函数等待指定的时间来等待任何键盘事件。如果你在这段时间内,输入了任何键,这个程序会继续。如果参数是0,他将会无限制的等待按键。他也可以设置成检测指定的按键,如按下按键a等,我们将会在下面讨论
注意
除了绑定案件事件,这个函数韩处理很多其他GUI事件,所以你必须将它用于实际的显示图片上
cv.destoryAllWindows()简单的摧毁所有我们建立的窗口。如果你想关闭指定的窗口,使用方法cv.destoryWindow() ,并传入参数:窗口的名称
注意
这里有一个特殊的案例,你可以在一个一创建的窗口中载入图像。在这种情况下,你可以指定窗口是否可以重新变更大小,它使用 cv.namedWindow().默认,他的flag是 cv.WINDOW_AUTOSIZE.但是如果你指定flag为 cv.WINDOW_NORMAL,你可以重新变更窗口。当图片太大的时候,这将会非常有帮助
代码如下:
cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()
写一个图片
使用方法 cv.imwrite()来保存一张图片。
第一个参数是文件名
第二个参数是你想要保存的image实例
cv.imwrite('messigravy.png',img)
这会将图片已png的格式保存在工作目录中
在下面的程序中,导入了一张灰度图并且展现,保存了他。如果你按下了 s 会退出,或者按下esc 取消保存并退出
import numpy as np
import cv2 as cv
img=cv.imread('messi5.jpg',0)
cv.imshow('image',img)
k=cv.waitKey(0)
if k==27:
cv.destoryAlWindows()
elfi k==ord('s'):
cv.imwrite('messigray.png',img)
cv.destoryAllWindows()
警告
如果你使用一个64位的机器,你需要改变
k=cv.waitKey(0)
为
k=cv.waitKey(0) &0xFF
Matplotlib是一个python的绘图程序库,它提供了大量的绘图方法。你会再即将到来的文章中见到他们,你会学习到如何在matplotlib中展现image。你可以用matplotlib来进行缩放图片,保存等操作
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.show()
窗口的截图如下:
同看到
大量的绘图选项可以在Matplotlib中使用,请参考Matplotlib文档获得更多的细节。有时候,我们会在路上看到她。
注意
由OpenCV导入的彩色图片是BGR模式的,但是Matplotlib是用RGB模式占线的,所以由opencv读取的彩色图片在matplotlib中不会正确的显示
###目标
###从摄像投抓取片段
经常,我们从摄像头中获取视频流。OpenCV提供了一个非常简单的接口来完成。让我们从摄像头抓取一段视频(我使用了笔记本内置的网络摄像头),转换成灰度视频,然后展示他。这只是一个简单的任务,让我们开始吧
为了抓取一段录像,我们需要创建一个VideoCapture对象。他的参数可以是设备,也可以是录像的名称。设备目录仅仅只是一个数字来指定哪个摄像头。通常一个摄像头是可用的(在我的例子中)。所以我简单的输入了0(或者-1)。你输入1来选择第二个摄像头或者其他的。之后,你可以逐帧来抓去。但是最后,不要忘记释放这次抓取。
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# 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) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
cap.read()
返回一个bool (True/False),如果帧是正确的,她会是True,
所以你可以检查这个值来确保录像的结尾。
有时候,cap
也许没有初始化抓取。在这个案例中,这段命令也许会报错,你可以通过 cap.isOpened()
来检查这个方法是否成功。如果返回了True
,好的,那么。否则通过cap.open()
来打开它。
您还可以使用cap.get(propId)
方法访问本视频的一些特性,其中propId是从0到18的数字。每个数字表示该视频的一个属性(如果适用于该视频),完整的细节可以在这里看到:cv::VideoCapture::get()
。其中一些值可以使用cap.set(propId, value)
进行修改。价值是你想要的新价值。
举个例子,我可以检查这个帧的宽度和长度通过 cap.get(cv.CAP_PROP_FRAME_WIDTH)
和cap.get(cv.getCAP_PROP_FRAME_HEIGHT)
,它默认会返回640*480。但是如果我想要更改成320*240,只需要 ret=cap.set(cv.CAP_PROP_FRAME_WIDTH,320)
,ret=cap.set(cv.CAP_PROP_FRAME_HEIGHT)
注意
如果你发现了异常,确保摄像机通过其他软件也能正常运行
### 从文件中播放视频
和从摄像头中抓取一样,只是更改了摄像头目录 为 视频文件的文件名。同样的当播放帧的时候,使用cv.waitKey()
来占用。如果他太少了,视频会播放的非常快。如果太高了,视频会非常慢(好的,这就是如何以慢动作展现视频)。正常情况下,25毫秒会运作正常。
import numpy as np
import cv2 as cv
cap = cv.VideoCapture('vtest.avi')
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
cv.imshow('frame',gray)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()
注意
确保安装了正确版本的ffmpeg或gstreamer。有时,由于ffmpeg/gstreamer的错误安装,使用视频捕获是一个令人头痛的问题。
###保存视频
所以我们抓取了一段视频,逐帧处理他然后我们想要保存它。对于图片,非常简单,只需要使用cv.imwrite()
。这里 需要一段稍多的工作
这次,我们创建了一个VidowWriter实例,我们需要指定输出文件名。然后我们指定FourCC代码(细节在下一章)。然后指定FPS和每帧需要压缩的大小。最后是isColore
flag,如果她是True
,压缩成指定颜色的帧,否则以灰度帧压缩。
FourCC
是一个4位代码,经常用于指定视频解码器。可用的解码器列表可以在 fourcc.org,她依赖于平台。
下面这些解码器对我来说,工作非常好
Fourcc代码对于MJPG格式,可以如下输入 cv.VideoWriter_fourcc('M'.'J','P','G')
或者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 ret==True:
frame = cv.flip(frame,0)
# write the flipped frame
out.write(frame)
cv.imshow('frame',frame)
if cv.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()
在上方所有的方法,你可以看到一些通用的参数:
为了画一条线,你需要给予起点和重点。我们会创建一个黑色的图片然后画一条蓝色的线在上面,线从左上到右下。
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512,512,3), np.uint8)
# Draw a diagonal blue line with thickness of 5 px
cv.line(img,(0,0),(511,511),(255,0,0),5)
来画一个矩形,你需要提供矩形的左上角和右下角。这次我们来画一个绿色的矩形在画面的最左边
cv.rectangle(img,(384,0),(510,128),(0,0,255),-1))
想要画圆,你需要提供中心点和半径。我们会在矩形的中间画一个园
cv.circle(img,(447,63), 63, (0,0,255), -1)
画一个椭圆,需要输入一些参数。一个参数是中心点(x,y),另一个参数是轴线的长度(主要是轴线长度,次轴长度)。角度是椭圆逆时针旋转的角度。startAngle和endAngle表示从主轴顺时针方向测量的椭圆圆弧的起始和结束。也就是说,给出的值是0,而360给出的是完整的椭圆。要了解更多细节,请参阅cv.ellipse()的文档。下面的例子在图像中心绘制了半个椭圆。
cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
要画一个多边形,首先你需要顶点的坐标。将这些点设置为形状行x1x2数组,其中行是顶点数,类型为int32。这里我们用黄色画一个有四个顶点的小多边形。
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))
请注意
如果第三个参数为假,您将得到连接所有点的折线,而不是一个封闭的形状。
polylines()可以绘制多条线。只需要创建一个您想要绘制的所有行列表,并将其传递给函数。所有的线将单独画。与为每一行调用cv.line()相比,它是一种更好更快的绘制一组线的方法。
为了添加文字,你需要指定以下参数
我们会用白色的 opencv来写在图片
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500),font,4,(255,255,255),2,cv.LINE_AA)
###结果
是时候查看画出来的结果,使用你在上一节学习到的来展示他们。
在这里,我们创建了一个简单的应用程序,它在双击图像的任何地方绘制一个圆。
首先,我们创建一个鼠标回调方法 用来在鼠标事件发生的时候执行。鼠标事件可以是任何和鼠标有关系的时间,例如按下左键,抬起左键,双击左键等等。每一个鼠标事件都返回一个坐标(X,Y),使用鼠标事件和定位,我们可以做任何我们喜欢的事情。为了列出所有可用的鼠标事件,在python终端运行一下代码
import cv2 as cv
events = [i for i in dir(cv) if 'EVENT' in i]
print( events )
创建鼠标回调方法有一个在任何地方都相同的特殊格式。。它只在函数的作用上有所不同。我们的鼠标回调函数只做一件事,他在双击的地方画出一个圆形。查看以下的代码。代码的内容中有注释:
git checkout v1.0
file code/mouse_paint_brush.py
import numpy as np
import cv2 as cv
# mouse callback function
def draw_circle(event,x,y,flags,param):
if event == cv.EVENT_LBUTTONDBLCLK:
cv.circle(img,(x,y),100,(255,0,0),-1)
# Create a black image, a window and bind the function to window
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
cv.imshow('image',img)
if cv.waitKey(20) & 0xFF == 27:
break
cv.destroyAllWindows()
现在来完成一个更好的应用。这次,我们通过拖拽鼠标画一个矩形或者圆形(根据鼠标的选择)像是我们在画图应用里面做的一样。所以我们的鼠标回调函数有两个部分,一是画矩形另一个是画圆形。这个特殊的案例对于创造和理解一些交互式应用相当的有用,例如 物体追踪,图片分割等等
git checkout v1.1
code/mouse_paint_brush.py
import numpy as np
import cv2 as cv
drawing = False # true if mouse is pressed
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
ix,iy = -1,-1
# mouse callback function
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv.circle(img,(x,y),5,(0,0,255),-1)
elif event == cv.EVENT_LBUTTONUP:
drawing = False
if mode == True:
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv.circle(img,(x,y),5,(0,0,255),-1)
下一步我们需要绑定这个鼠标回调方法到Opencv窗口。在主循环中,我们需要设置一个键M 来区分矩形和圆形
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == ord('m'):
mode = not mode
elif k == 27:
break
cv.destroyAllWindows()
git checkout v1.2
code/mouse_patin_brush.py
这里我们会创建一个简单的应用,用来展示你指定的颜色。你需要有一个窗口来展现颜色,和三个滚动条来指定 B,G,R的颜色。滑动滚动条并且相应的窗口的颜色改变。默认的初始颜色是黑色。
对于 cv.getTrackbarPost()函数,第一个参数是滚动条的名字,第二个是窗口的名字,第三个是默认的值,第四个是最大值,第五个是回调参数在每次滚动条的值改变的时候执行。回调函数总是有一个默认的参数是滚动条的位置。在我们的案例中,方法总是不做任何事情,所以我们直接跳过就行。
另一个重要的滚动条应用是像按钮或者开关一样来使用。Opencv,默认的,没有任何按钮的功能。所以你可以用滚动条来实现类似的功能。在我们的应用中,我们已经创建了一个开关,应用程序只有在开关打开时才工作,否则屏幕总是黑色的。
git checkout v1.0
code/trackbar_test.py
import numpy as np
import cv2 as cv
def nothing(x):
pass
# Create a black image, a window
img = np.zeros((300,512,3), np.uint8)
cv.namedWindow('image')
# create trackbars for color change
cv.createTrackbar('R','image',0,255,nothing)
cv.createTrackbar('G','image',0,255,nothing)
cv.createTrackbar('B','image',0,255,nothing)
# create switch for ON/OFF functionality
switch = '0 : OFF \n1 : ON'
cv.createTrackbar(switch, 'image',0,1,nothing)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
# get current positions of four trackbars
r = cv.getTrackbarPos('R','image')
g = cv.getTrackbarPos('G','image')
b = cv.getTrackbarPos('B','image')
s = cv.getTrackbarPos(switch,'image')
if s == 0:
img[:] = 0
else:
img[:] = [b,g,r]
cv.destroyAllWindows()
应用的截图看起来如下:
创建一个画图程序可以调整颜色和刷子大小通过滚动条。为了画图,参考上一节教程关于鼠标的句柄
v1.3
code/trackbar_test.py