OpenCV的GUI特性

OpenCV的GUI特性

源网页

  • 开始学习图片
  • 开始学习视频
  • OpenCV的绘图方法
  • 鼠标作为画笔
  • 滚动栏作为调色板

文章目录

  • OpenCV的GUI特性
    • [开始学习图片]()
      • 目标
      • 使用OpenCV
        • 读取一个图像
        • 总结
      • 使用Matplotlib
      • 拓展资源
    • 学习视频
    • OpenCV的绘图方法
      • 目标
      • 代码
      • 画一条线
      • 画一个长方形
      • 画圆
      • 画一个椭圆形
      • 绘制多边形
      • 添加文字
    • 鼠标作为画笔
      • 目标
      • 简单案例
      • 更多高级案例
      • 额外资源
      • 练习题
    • 轨迹栏作为调色盘
      • 目标
      • 代码案例
      • 练习题

开始学习图片

目标

  • 这里,你会学习如何读取一张图片,如何展示以及如何保存它
  • 你会学习到这些方法: cv.imread(),cv.imshow(),cv.imwrite()
  • 另外,你会学习到如何在matplotlib中展示图片

使用OpenCV

读取一个图像

使用 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中不会正确的显示

拓展资源

  1. 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和每帧需要压缩的大小。最后是isColoreflag,如果她是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).

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()

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。

我们会用白色的 opencv来写在图片

font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500),font,4,(255,255,255),2,cv.LINE_AA)

###结果

是时候查看画出来的结果,使用你在上一节学习到的来展示他们。

OpenCV的GUI特性_第1张图片

鼠标作为画笔

目标

  • 学习抓取鼠标事件
  • 你会学到这些方法: 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()

额外资源

练习题

  1. 在我们上一个案例中,我们画了一个填充的矩形。请更待代码来画一个非填充的矩形
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特性_第2张图片

练习题

  1. 创建一个画图程序可以调整颜色和刷子大小通过滚动条。为了画图,参考上一节教程关于鼠标的句柄

    v1.3
    code/trackbar_test.py
    

你可能感兴趣的:(OpenCV)