OpenCV的GUI特性 源网页
- 开始学习图片
- 开始学习视频
- OpenCV的绘图方法
- 鼠标作为画笔
- 滚动栏作为调色板
文章目录
- OpenCV的GUI特性
-
- [开始学习图片]()
-
- 目标
- 使用OpenCV
-
- 读取一个图像
- 总结
- 使用Matplotlib
- 拓展资源
- 学习视频
- OpenCV的绘图方法
-
- 目标
- 代码
- 画一条线
- 画一个长方形
- 画圆
- 画一个椭圆形
- 绘制多边形
- 添加文字
- 鼠标作为画笔
-
- 目标
- 简单案例
- 更多高级案例
- 额外资源
- 练习题
- 轨迹栏作为调色盘
-
- 目标
- 代码案例
- 练习题
开始学习图片 目标
- 这里,你会学习如何读取一张图片,如何展示以及如何保存它
- 你会学习到这些方法: cv.imread(),cv.imshow(),cv.imwrite()
- 另外,你会学习到如何在matplotlib中展示图片
读取一个图像 使用 cv.imread() 来读取一张图片。这个图片给予的路径应该是在工作目录中或者使用完整路径
第二个参数是一个flasg来指定图片的读取方式
- cv.IMREAD_COLOR:导入一个彩色图片。图片的所有透明度将会被忽略。这是默认的flag
- cv.IMREAD_GRAYSCALE:导入一个灰度图片
- cv.IMREAD_UNCHANGED:导入图片,包括alpha通道
注意:
你可以用简单的证书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
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中不会正确的显示
拓展资源
- Matplotlib Plotting Styles and Features
- 学习读取视频,展示和保存
- 学习抓取摄像机和展示
- 你会用到以下方法:cv.VideoCapture(),cv.VideoWriter()
经常,我们从摄像头中获取视频流。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,她依赖于平台。下面这些解码器对我来说,工作非常好
- In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high size video. X264 gives very small size video)
- In Windows: DIVX (More to be tested and added)
- In OSX: MJPG (.mp4), DIVX (.avi), X264 (.mkv).
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()
OpenCV的绘图方法 目标
- 学习用Opencv 绘制不同的几何图形
- 你会学到以下方法:cv.line(),cv.cricle(),cv.rectangle(),cv.ellipse(),cv.putText()etc
在上方所有的方法,你可以看到一些通用的参数:
- img: 画图所在的图像
- colore: 图形的颜色。对于BGR,需要给予一个元祖,如蓝色(255,0,0),对于灰度,只需要给予标量值
- thickness:行或者圆等的厚度,如果 给予了 -1 参数给了闭环图像像是圆形,他会被填充。默认是1
- lineType:线条的类型,是否八连,抗锯齿线等等。默认,他是八连的。cv.LINE_AA提供了反锯齿线,看起来很适合曲线
为了画一条线,你需要给予起点和重点。我们会创建一个黑色的图片然后画一条蓝色的线在上面,线从左上到右下。
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()相比,它是一种更好更快的绘制一组线的方法。
添加文字
为了添加文字,你需要指定以下参数
- Text data:你想要添加的文字
- position:你想放置的位置的坐标(左下角 是0点)
- font type:格式(参考 cv.putText()文档来支持更多)
- font scale:文字大小(指定文字的大小)
- 规则的东西,如颜色、厚度、线条类型等。为了更好看,推荐线条类型= cv。LINE_A。
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500),font,4,(255,255,255),2,cv.LINE_AA)
###结果
是时候查看画出来的结果,使用你在上一节学习到的来展示他们。
文章图片
鼠标作为画笔 目标
- 学习抓取鼠标事件
- 你会学到这些方法: cv.setMouseCallback()
在这里,我们创建了一个简单的应用程序,它在双击图像的任何地方绘制一个圆。
首先,我们创建一个鼠标回调方法 用来在鼠标事件发生的时候执行。鼠标事件可以是任何和鼠标有关系的时间,例如按下左键,抬起左键,双击左键等等。每一个鼠标事件都返回一个坐标(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
轨迹栏作为调色盘 目标
- 学习绑定轨迹栏到opencv的窗口
- 你会学习到一下方法: cv.getTrackbarPos(),cv.createTrackbar()etc
这里我们会创建一个简单的应用,用来展示你指定的颜色。你需要有一个窗口来展现颜色,和三个滚动条来指定 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()
应用的截图看起来如下:
文章图片
练习题
- 【OpenCV的GUI特性】创建一个画图程序可以调整颜色和刷子大小通过滚动条。为了画图,参考上一节教程关于鼠标的句柄
v1.3 code/trackbar_test.py
推荐阅读
- OpenCV|OpenCV图像处理和应用—色彩空间与几何变换(一)
- OpenCV从入门到精通|OpenCV的核心操作 —— 图像的基本操作+图像上的算术运算
- 激光条纹中心提取|opencv二值图像分割——python
- keras|OpenCV-Python实战(22)——使用Keras和Flask在Web端部署图像识别应用
- 深度学习|opencv基本操作
- OpenCV转换成灰度图像
- 深度图像转换为灰度图
- 图像处理中滤波与卷积的区别
- Python|【AI出牌器】第一次见这么“刺激”的斗地主,胜率高的关键因素竟是......