OpenCV库的学习笔记(一)Gui Features in OpenCV

学习链接如下:

OpenCV库的学习

在复现David P.Williams论文时,用到了OpenCV的两个函数,这两个函数是用来遍历图像的所有连通域,并用椭圆拟合的,所以我感觉很神奇,竟然可以一键操作,我觉得OpenCV库很厉害,借此想系统学习一下OpenCV的库操作。

cv2.findContours()
cv2.fitEllipse()

OpenCV读取图片时,可以直接将图片存为矩阵,这样就很好操作。

这里一些基本的操作我就不写了,只写需要详细记的,用的。

Image操作

cv.imshow("Display window", img)
k = cv.waitKey(0)

这里的cv.waitKey()是图片框展示的d时间,参数为0时,意味着是无穷大,你要自己关才行。

cv.imread(par1,par2)

对于imread函数,第一个参数指定的文件路径加载图像。第二个参数是可选的,它指定我们想要图像的格式。这可能是:

  • IMREAD_COLOR:加载BGR 8位格式的图像。这是这里使用的默认值。(注意这里加载的是BGR格式,然而我们通常使用的都是RGB形式,这里会导致你plt.show()的图像有色差)可以用下述方法转过来。
cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
  • IMREAD_UNCHANGED:按原样加载图像(包括alpha通道),alpha通道指的是一张图片的透明度和半透明度。
  • IMREAD_GRAYSCALE:将图片加载为灰度图片,或者将par2换成0也可以。

Video操作

目标:

  • 学习读取video,展示video,和存储video。
  • 学习从相机捕捉视频并显示它。
  • 您将学习以下函数:cv.VideoCapture(),cv.VideoWriter()

OpenCV为此提供了一个非常简单的接口。让我们从相机(我正在使用笔记本电脑上的内置摄像头)捕捉一个视频,将其转换为灰度视频并显示出来。只是一个简单的开始任务。

要捕获视频,您需要创建一个videcapture对象。它的参数可以是设备索引或视频文件的名称。设备索引只是指定哪个相机的数字。通常会连接一个摄像头(就像我的情况一样)。所以我简单地传递0(或-1)。你可以通过传递1来选择第二个相机,以此类推。之后,就可以逐帧捕获了。但最后,不要忘记释放捕获。

import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)#0是第一个摄像头,1是第二个摄像头
if not cap.isOpened():#检查是否有摄像头,这里是一个初始化操作,也可以用cap.open()打开
    print("Cannot open camera")
    exit()
while True:
    # Capture frame-by-frame#frame是帧数的意思,是一帧帧播放
    ret, frame = cap.read()#这里的ret是返回True还是False,可以通过该值来检查是否结束
    # 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'):#这里是你要按q就可以停止录像
        break
# When everything done, release the capture
cap.release()#释放
cv.destroyAllWindows()

您还可以使用cap.get(propId)方法访问本视频的一些功能,其中propId是一个从0到18的数字。每个数字表示视频的一个属性(如果它适用于该视频)。完整的细节可以在这里看到:cv:: videcapture::get() 。其中一些值可以使用cap.set(propId, value)进行修改。Value是您想要的新值。

例如,我可以通过cap.get(cv.CAP_PROP_FRAME_WIDTH)和cap.get(cv.CAP_PROP_FRAME_HEIGHT)检查帧的宽度和高度。默认是640x480。但是我想把它修改成320x240。只需使用ret = cap.set(cv.CAP_PROP_FRAME_WIDTH,320)和ret = cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)即可。

从文件中播放视频与从摄像机中捕获视频是相同的,只需将摄像机索引更改为视频文件名。同样,在显示帧时,为cv.waitKey()使用适当的时间。如果它太低,视频会非常快,如果太高,视频会很慢(好吧,这就是你如何以慢动作显示视频)。正常情况下25毫秒就可以了。

所以我们捕捉一个视频,逐帧处理它,我们想要保存这个视频。对于图像,它非常简单:只需使用cv.imwrite()。这里,还需要做一些工作。

这次我们创建了一个VideoWriter对象。我们应该指定输出文件名(例如:output.avi)。然后我们应该指定FourCC代码(详见下一段)。然后每秒帧数(fps)帧大小应该被传递。最后一个是isColor标志。如果为True,则编码器期望彩色帧,否则将使用灰度帧

FourCC是一个4字节的代码,用于指定视频编解码器。可用代码的列表可以在fourcc.org上找到。它是平台相关的。下面的编解码器对我来说工作正常:

  • In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID更可取。MJPG产生高尺寸的视频。X264提供非常小尺寸的视频);
  • In Windows: DIVX(更多有待测试和添加);
  • In OSX: MJPG (.mp4), DIVX (.avi), X264 (.mkv)。

FourCC代码传递为' cv.VideoWriter_fourcc('M','J','P','G')或为MJPG传递为' 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')#这里是fourcc上文讲过的编码对象
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,  480))#这是20帧,(640*480)的大小帧
while cap.isOpened():
    ret, frame = cap.read()#ret之前讲过
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    frame = cv.flip(frame, 0)#这里0是翻转的意思,0是垂直翻转,1是水平翻转
    # write the flipped frame
    out.write(frame)
    cv.imshow('frame', frame)
    if cv.waitKey(1) == ord('q'):#按q停止
        break
# Release everything if job is finished
cap.release()
out.release()
cv.destroyAllWindows()

画画操作

目标:

  • 学习用OpenCV绘制不同的几何形状;
  • 你将学习这些函数:cv.line(), cv.circle(), cv.rectangle(), cv.ellipse(), cv.putText()等。

在上述所有函数中,你将看到一些常见的参数,如下所示:

  • img:你想要绘制图形的图像;
  • color:形状的颜色。对于BGR,将其作为元组传递,例如:(255,0,0)对于blue。对于灰度,只传递标量值;
  • thickness:线或圆等的厚度。如果将-1传递给像圆这样的闭合数字,它将填充形状。默认厚度= ;
  • lineType:线的类型,是否8连接,抗锯齿线等。缺省情况下,是8连的。简历。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)

上面(255,0,0)为什么是蓝色呢?因为OpenCV正常读取的图片是BGR,第一个是B,所以是蓝色。

画矩形框:

cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
#画布,左上角,右下角,绿色,3号

画圆:

cv.circle(img,(447,63), 63, (0,0,255), -1)
#画布,圆心,半径,红色,实心 大于1为空心

画椭圆:

cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)

画多边形:

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

如果第三个参数为False,你将得到一个连接所有点的折线,而不是一个封闭的形状。Cv.polylines()可用于绘制多条线。只需创建一个您想要绘制的所有线的列表,并将其传递给函数。所有的线都将单独绘制。这是一种比为每一行调用cv.line()更好、更快地绘制一组线的方法。

在图片中添加文字:

  • 输入要写入的数据。
  • 你想要放置它的位置坐标(即数据开始的左下角)。
  • 字体类型(查看cv.putText()文档以获得支持的字体)。
  • 字体大小(指定字体大小)。
  • 有规律的东西,如颜色、厚度、线条等。为了更好看,推荐使用lineType = cv.LINE_AA。
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)

作业:

要求绘制一个OpenCV的logo:

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,255,0),3)
cv.circle(img,(256,256), 200, (100,100,0), -1)
#画布,圆心,半径,红色,实心
cv.ellipse(img,(256,256),(50,100),0,0,360,[0,0,100],-1)
#画布,圆心,长短轴,角度,起始角度,终止角度,颜色,实心
pts = np.array([[256,0],[0,256],[256,511],[511,256]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255),10)
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(20,300), font, 4,(255,255,255),2,cv.LINE_AA)
cv.imshow('img',img)
cv.waitKey(0)

用鼠标当画笔:

目标:

  • 学习在OpenCV中处理鼠标事件;
  • You will learn these functions:cv.setMouseCallback()。

简易的Demo:

在这里,我们创建了一个简单的应用程序,它在双击图像的任何位置绘制一个圆。

首先,我们创建一个鼠标回调函数,该函数在发生鼠标事件时执行。鼠标事件可以是任何与鼠标相关的事件,如左键向下、左键向上、左键双击等。它给出了每个鼠标事件的坐标(x,y)。有了这个活动和地点,我们可以做任何想做的事。要列出所有可用的事件,请在Python终端中运行以下代码:

import cv2 as cv
events = [i for i in dir(cv) if 'EVENT' in i]
print( events )

创建鼠标回调函数有一个特定的格式,在任何地方都是一样的。它的区别仅仅在于函数的功能。我们的鼠标回调函数做了一件事,它在我们双击的地方画了一个圆。请参阅下面的代码。代码从注释中是自解释的:

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(1) == ord('q'):#按q停止
        break
cv.destroyAllWindows()

更加先进的Demo:

现在我们来看一个更好的应用程序。在这里,我们像在Paint应用程序中一样,通过拖动鼠标绘制矩形或圆形(取决于我们选择的模式)。所以我们的鼠标回调函数有两个部分,一个用来画矩形,另一个用来画圆。这个具体的例子将对创建和理解一些交互式应用程序,如对象跟踪,图像分割等非常有帮助。

import numpy as np
import cv2 as cv
drawing = False # 鼠标按压时画画
mode = True # if True, draw rectangle. Press 'm' to toggle to curve
#为True画矩形为False画圆
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)
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()

接下来,我们必须将这个鼠标回调函数绑定到OpenCV窗口。在主循环中,我们应该为键“m”设置一个键盘绑定,以便在矩形和圆形之间切换。

作业:

在上一个例子中,我们画了一个填充矩形。修改代码以绘制一个未填充的矩形。

这个作业很简单,把-1改成你想要的边界宽度就可以了。

用Trackbar作为调色板

目标:

  • 学习将跟踪栏绑定到OpenCV窗口;
  • 你将学习这些函数:cv.getTrackbarPos(),cv.createTrackbar()。

在这里,我们将创建一个简单的应用程序来显示您指定的颜色。您有一个显示颜色的窗口和三个用于指定B、G、R颜色的跟踪条。滑动跟踪条,相应的窗口颜色也会发生变化。默认情况下,初始颜色将设置为黑色。

对于cv.createTrackbar()函数,第一个参数是trackbar名称,第二个参数是它所附加的窗口名称,第三个参数是默认值,第四个参数是最大值,第五个参数是每次trackbar值改变时执行的回调函数。回调函数总是有一个默认参数,即trackbar的位置。在我们的例子中,函数什么也不做,所以我们简单地传递。

Trackbar的另一个重要应用是将其用作按钮或开关。默认情况下,OpenCV没有按钮功能。因此,您可以使用Trackbar来获得这样的功能。在我们的应用程序中,我们已经创建了一个开关,其中应用程序只有在开关是ON时才能工作,否则屏幕总是黑色的。

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)