图像入门

学习目标:

  • 图像的读取、显示、保存
  • 学习三个函数:cv2.imread(), cv2.imshow() , cv2.imwrite()
  • 使用 Matplotlib 来显示图像
  1. # 导入常用包
  2. #%matplotlib notebook
  3. import numpy as np
  4. import cv2
  5. import matplotlib.pyplot as plt

读取显示图像

  1. img = cv2.imread("img.jpg", 0) # 1: 显示原始图, 0:灰度图 -1:加载图像包括 alpha 通道
  2. cv2.imshow("image", img) # 第一个参数为显示窗口的名称,第二个参数是要显示的图像
  3. k = cv2.waitKey(0) & 0xFF # cv2.waitKey() 键盘绑定函数,等待键盘按下,以毫秒为计数单位,也可以设定特定按键点击。64 bit 的机器要 cv2.waitKey(0) & 0xFF
  4. if k == 27: # 等待按下 ESC 键退出,
  5. cv2.destroyAllWindows() # 销毁所有窗口,也可以用 cv2.destroyWindow() 销毁特定的窗口。
  6. elif k == ord('s'): # 指定某个按键按下后指定某种操作,如这里是保存
  7. cv2.imwrite('image_write.png',img)
  8. cv2.destroyAllWindows()

结果:OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图1

  1. cv2.namedWindow("image_new", cv2.WINDOW_NORMAL) # 创建一个新的窗口,这个窗口大小可以进行调节的
  2. cv2.imshow("image_new", img)
  3. cv2.waitKey(0)
  4. cv2.destroyWindow("image_new")

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图2

写图像(保存图像)

  1. cv2.imwrite("image_write.png", img) # 保存图像,可以指定保存图像的格式
  1. True

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图3

使用 matplotlib 显示图像

Matplotlib是一个用于Python的绘图库,它提供了多种绘图方法。在这里,将学习如何使用 Matplotlib 显示图像。可以使用 Matplotlib 放大图片,保存图片等。

  1. img = cv2.imread("img.jpg", 0)
  2. plt.imshow(img, cmap = 'gray', interpolation = 'bicubic') # interpolation 插值
  3. plt.xticks([])
  4. plt.yticks([]) # 隐藏 X、Y 坐标的刻度值
  5. plt.show()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图4

OpenCV 加载的彩色图像为 BGR 模式。但是 Matplotlib 以 RGB 模式显示。因此,如果使用 OpenCV 读取图像,Matplotlib 中的彩色图像将不能正确显示。

以下是解决办法:对图像的模式进行转换,使之与 Matplotlib 或 OpenCV 匹配

  1. img_cv = cv2.imread("img.jpg") # OpenCV 读取图像
  2. b, g, r = cv2.split(img_cv) # OpenCV 中图像显示是 BGR 模式,提取
  3. img_matplot = cv2.merge([r, g, b])
  4. plt.subplot(121)
  5. plt.imshow(img_cv) # 预计图像会是异常的
  6. plt.subplot(122)
  7. plt.imshow(img_matplot) # 预计是真实的图像
  8. plt.show()
  9. cv2.imshow('bgr image',img_cv) # 预计图像会是异常的
  10. cv2.imshow('rgb image',img_matplot) # 预计是真实的图像
  11. cv2.waitKey(0)
  12. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图5

更多资料

matplotlib 详细 API

视频入门

学习目标:

  • 显示视频、保存视频
  • 从相机进行捕获
  • cv2.VideoCapture(), cv2.VideoWriter() 函数使用

从相机捕获视频

笔记本自带摄像头

  1. import cv2
  2. # 创建一个 VideoCapture 对象,参数是设备的索引即摄像机的编号或者 Video 的文件名
  3. # 这里的 0 是指第一台摄像机,以此类推
  4. cap = cv2.VideoCapture(0)
  5. while (True):
  6. # while cap.isOpened():
  7. # 一帧一帧的捕获
  8. ret, frame = cap.read()
  9. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  10. # 显示
  11. cv2.imshow("frame", gray) # 窗口名为 frame
  12. if cv2.waitKey(1) & 0xFF == ord('q'):
  13. break
  14. cap.release() # 关闭视频文件或设备
  15. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图6
cap.read() 返回一个bool (True/False)。如果帧被正确读取,它将为真。通过检查这个返回值来检查视频的结尾。

有时,cap 可能没有初始化捕获。在这种情况下,这段代码显示错误。可以通过方法 cap.isOpened() 检查它是否初始化。如果为真,则 ok。否则使用 cap.open() 打开它。

可以通过 cap.get(propId) 获取视频的一些属性,propId 值为:0 to 18。每个值代表视频的一个属性,详见 Property Identifier 也可以通过 cap.set(propId, value) 设置视频的属性。
例如:可以通过 cap.get(3)cap.get(4) 检查帧的宽和高,默认是 640x480。通过 ret = cap.set(3,320)ret = cap.set(4,240) 将宽和高重新设定。

  1. # 创建一个 VideoCapture 对象,参数是设备的索引即摄像机的编号或者 Video 的文件名
  2. # 这里的 0 是指第一台摄像机,以此类推
  3. cap = cv2.VideoCapture(0)
  4. while (True):
  5. # while cap.isOpened():
  6. # 一帧一帧的捕获
  7. ret, frame = cap.read()
  8. ret = cap.set(3, 320)
  9. ret = cap.set(4, 240)
  10. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  11. cv2.imshow("frame", gray)
  12. if cv2.waitKey(1) & 0xFF == ord('q'):
  13. break
  14. cap.release()
  15. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图7

从文件进行播放

  1. cap = cv2.VideoCapture('vtest.avi')
  2. while(cap.isOpened()):
  3. ret, frame = cap.read()
  4. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  5. cv2.imshow('frame', gray)
  6. if cv2.waitKey(1) & 0xFF == ord('q'):
  7. break
  8. cap.release()
  9. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图8

如果视频播放结束,还没按键按下,会出现错误。 改进如下:

  1. import cv2
  2. cap = cv2.VideoCapture('vtest.avi')
  3. while(cap.isOpened()):
  4. ret, frame = cap.read()
  5. if ret == True:
  6. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  7. cv2.imshow('frame', gray)
  8. if ret == False:
  9. # cap.release() # 释放掉开启的视频
  10. # print("1") # 测试
  11. cv2.waitKey(0) # 暂停在最后一帧
  12. break # 关闭窗口后退出
  13. if cv2.waitKey(1) & 0xFF == ord('q'):
  14. break
  15. cap.release()
  16. cv2.destroyAllWindows()

改进以后,程序会一直监测视频是否到最后一帧,若是最后一帧,则 ret 为 False ,暂停在最后一帧并且在关闭窗口后退出

保存视频

  1. cap = cv2.VideoCapture(0)
  2. # Define the codec and create VideoWriter object
  3. # cv2.VideoWriter_fourcc('X','V','I','D') 功能一样
  4. fourcc = cv2.VideoWriter_fourcc(*'XVID')
  5. # 创建 VideoWriter 对象,指定输出文件名 output.avi, FourCC 代码,传递每秒帧数和帧大小
  6. out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
  7. while(cap.isOpened()):
  8. ret, frame = cap.read()
  9. if ret == True:
  10. # 对每一帧进行翻转
  11. frame = cv2.flip(frame, 0) # 注释见下
  12. # write the flipped frame
  13. out.write(frame)
  14. cv2.imshow('frame', frame)
  15. if cv2.waitKey(1) & 0xFF == ord('q'):
  16. break
  17. else:
  18. break
  19. # Release everything if job is finished
  20. cap.release()
  21. out.release()
  22. cv2.destroyAllWindows()

FourCC 是一个 4 字节的代码,用于指定视频编解码器,依赖于平台,到时看具体平台进行选择。更多 FourCC 代码见 官网

cv2.flip(src, flipCode[, dst]) → dst: flipCode: 0表示绕 x 轴翻转,正值(例如,1)表示绕 y 轴翻转。负值(例如 -1)表示在两个轴上翻转。

更多资料

opencv documentation

OpenCV 绘图功能

学习目标:

  • 使用 OpenCV 绘制不同几何形状
  • cv2.line(), cv2.circle() , cv2.rectangle(), cv2.ellipse(), cv2.putText()

以下图像都用 matplotlib 绘制

函数共有参数说明

  • img: 要操作的图像
  • color:绘制形状的颜色, RGB 传入元组如(255, 255, 255), 灰度值只需传入标量
  • thickness:线或圆等的厚度。如果对圆形等闭合图形传递 -1 ,则填充形状。默认为 1
  • lineType:线的类型

绘制各种形状

  1. # 需要给定直线的起始和结束坐标
  2. # 创建一个黑色的画布
  3. img = np.zeros((512, 512, 3), np.uint8)
  4. # 绘制坐标 (0, 0) -> (510, 128) 直线 蓝色,厚度为 5px
  5. img = cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5) # OpenCV 为 BGR 模式
  6. # 绘制长方形,起始和终点坐标,颜色,厚度
  7. img = cv2.rectangle(img, (384, 10), (505, 120), (0, 255, 0), 3)
  8. # 绘制圆形,给定圆心,半径,最后 -1 为图形填充
  9. img = cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
  10. # 绘制椭圆,椭圆心,长轴,短轴,角度,起始结束角,填充
  11. img = cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1)
  12. # 绘制多边形,给定多边形的顶点坐标
  13. pts = np.array([[50, 50], [40, 40], [60, 40], [60, 100]], np.int32)
  14. pts = pts.reshape((-1, 1, 2))
  15. # 若第三个参数为 False,则得到连接所有点的折线,而不是一个闭合的形状。该函数可以用来绘制多条直线
  16. img = cv2.polylines(img, [pts], True, (0, 255, 255))
  17. # 添加文字到图形中
  18. font = cv2.FONT_HERSHEY_SIMPLEX # 指定字体
  19. cv2.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255),
  20. 2, cv2.LINE_AA) # 绘制的图像,文字,文字左下角的坐标,字体,字体颜色,厚度等
  21. cv2.imshow("diff type", img)
  22. k = cv2.waitKey(0) & 0xFF
  23. if k == 27:
  24. cv2.destroyAllWindows()
  25. b, g, r = cv2.split(img)
  26. img = cv2.merge([r, g, b])
  27. plt.subplot(121)
  28. plt.xticks([])
  29. plt.yticks([])
  30. plt.imshow(img)
  1. <matplotlib.image.AxesImage at 0x1d119e3b668>

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图9

作业:绘制 OpenCV 图标 OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图10

更多资料

鼠标作为画笔

学习目标:

  • 处理鼠标事件
  • cv2.setMouseCallback()

简单 Demo

首先,创建一个鼠标回调函数,该函数在鼠标事件发生时执行。鼠标事件可以是任何与鼠标相关的东西,如左键向下、左键向上、左键双击等。它为每个鼠标事件提供坐标 (x,y)。有了这个事件和位置,我们可以做任何我们想做的事情。

  1. # 列出鼠标处理的事件
  2. events = [i for i in dir(cv2) if 'EVENT' in i]
  3. events
  1. ['EVENT_FLAG_ALTKEY',
  2. 'EVENT_FLAG_CTRLKEY',
  3. 'EVENT_FLAG_LBUTTON',
  4. 'EVENT_FLAG_MBUTTON',
  5. 'EVENT_FLAG_RBUTTON',
  6. 'EVENT_FLAG_SHIFTKEY',
  7. 'EVENT_LBUTTONDBLCLK',
  8. 'EVENT_LBUTTONDOWN',
  9. 'EVENT_LBUTTONUP',
  10. 'EVENT_MBUTTONDBLCLK',
  11. 'EVENT_MBUTTONDOWN',
  12. 'EVENT_MBUTTONUP',
  13. 'EVENT_MOUSEHWHEEL',
  14. 'EVENT_MOUSEMOVE',
  15. 'EVENT_MOUSEWHEEL',
  16. 'EVENT_RBUTTONDBLCLK',
  17. 'EVENT_RBUTTONDOWN',
  18. 'EVENT_RBUTTONUP']
  1. import cv2
  2. import numpy as np
  3. # 功能函数,在鼠标处左键双击,绘制白色填充的圆
  4. def draw_circle(event, x, y, flags, param):
  5. if event == cv2.EVENT_LBUTTONDBLCLK:
  6. cv2.circle(img, (x, y), 100, (255, 255, 255), -1)
  7. # 创建一个黑色画布
  8. img = np.zeros((512, 512, 3), np.uint8)
  9. cv2.namedWindow("image")
  10. # 创建鼠标回调函数,绑定功能函数
  11. cv2.setMouseCallback("image", draw_circle)
  12. while(1):
  13. cv2.imshow("image", img)
  14. if cv2.waitKey(20) & 0xFF == 27:
  15. break
  16. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图11

高级 Demo

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

  1. import cv2
  2. import numpy as np
  3. drawing = False # 鼠标按下为 True
  4. mode = True # 按键 'm' 切换模式
  5. ix, iy = -1, -1
  6. def draw(event, x, y, flags, param):
  7. global ix, iy, drawing, mode
  8. if event == cv2.EVENT_LBUTTONDOWN: # 鼠标放下
  9. drawing = True
  10. ix, iy = x, y # 鼠标放下时的坐标
  11. elif event == cv2.EVENT_MOUSEMOVE: # 鼠标移动
  12. if drawing == True:
  13. if mode == True:
  14. cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
  15. else:
  16. cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
  17. elif event == cv2.EVENT_LBUTTONUP: # 鼠标提起,结束绘制
  18. drawing = False
  19. # ------------- 中间这一段要不要?
  20. if mode == True:
  21. cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), -1)
  22. else:
  23. cv2.circle(img, (x, y), 5, (0, 0, 255), -1)
  24. # -------------
  25. img = np.zeros((512, 512, 3), np.uint8)
  26. cv2.namedWindow("image")
  27. cv2.setMouseCallback("image", draw) # 功能绑定
  28. while(1):
  29. cv2.imshow("image", img)
  30. k = cv2.waitKey(1) & 0xFF
  31. if k == ord('m'): # 按键 'm' 切换模式
  32. mode = not mode
  33. elif k == 27:
  34. break
  35. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图12

轨迹栏作为调色板

学习目标:

  • 将轨迹栏绑定到 OpenCV 窗口
  • cv2.getTrackbarPos(), cv2.createTrackbar()

Demo

创建简单的应用程序,通过滑动轨迹条调节 BGR 的值从而改变画布颜色,初始颜色为黑色。

cv2.createTrackbar() 函数,第一个参数是 trackbar 名称,第二个参数是将用作创建的 trackbar 的父窗口的名称,第三个参数是默认值,第四个参数是最大值,第五个参数是回调函数,每次 trackbar 值发生变化时都会执行回调函数。回调函数总是有一个默认参数,即 trackbar 位置。在我们的例子中,函数什么也不做,所以我们只是传递。

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

  1. import cv2
  2. import numpy as np
  3. def nothing(x):
  4. pass
  5. img = np.zeros((300, 512, 3), np.uint8)
  6. cv2.namedWindow("image")
  7. cv2.createTrackbar('R', 'image', 0, 255, nothing)
  8. cv2.createTrackbar('G', 'image', 0, 255, nothing)
  9. cv2.createTrackbar('B', 'image', 0, 255, nothing)
  10. switch = '0 : OFF \n1 : ON'
  11. cv2.createTrackbar(switch, 'image', 0, 1, nothing)
  12. while(1):
  13. cv2.imshow('image', img)
  14. k = cv2.waitKey(1) & 0xFF
  15. if k == 27:
  16. break
  17. r = cv2.getTrackbarPos('R', 'image')
  18. g = cv2.getTrackbarPos('G', 'image')
  19. b = cv2.getTrackbarPos('B', 'image')
  20. s = cv2.getTrackbarPos(switch, 'image')
  21. if s == 0:
  22. img[:] = 0
  23. else:
  24. img[:] = [b, g, r]
  25. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图13

练习

创建一个画笔颜色和笔刷半径可调的滑动轨迹条

  1. import cv2
  2. import numpy as np
  3. def nothing(x):
  4. pass
  5. radius_t = 1
  6. bt, gt, rt = 255, 255, 255
  7. def draw_circle(event, x, y, radius, b=255, g=255, r=255):
  8. global radius_t, bt, gt, rt
  9. radius = radius_t
  10. b, g, r = bt, gt, rt
  11. if event == cv2.EVENT_LBUTTONDBLCLK:
  12. cv2.circle(img, (x, y), radius, (b, g, r), -1)
  13. img = np.zeros((1366, 768, 3), np.uint8)
  14. cv2.namedWindow("image")
  15. # --------- 画笔颜色
  16. cv2.createTrackbar('brush_radius', 'image', 1, 10, nothing)
  17. cv2.createTrackbar('pen_B', 'image', 0, 255, nothing)
  18. cv2.createTrackbar('pen_G', 'image', 0, 255, nothing)
  19. cv2.createTrackbar('pen_R', 'image', 0, 255, nothing)
  20. # 创建鼠标回调函数,绑定功能函数
  21. cv2.setMouseCallback("image", draw_circle)
  22. while(1):
  23. cv2.imshow('image', img)
  24. k = cv2.waitKey(1) & 0xFF
  25. if k == 27:
  26. break
  27. brush_radius = cv2.getTrackbarPos('brush_radius', 'image')
  28. pen_B = cv2.getTrackbarPos('pen_B', 'image')
  29. pen_G = cv2.getTrackbarPos('pen_G', 'image')
  30. pen_R = cv2.getTrackbarPos('pen_R', 'image')
  31. # 对鼠标函数参数进行赋值
  32. radius_t = brush_radius
  33. bt, gt, rt = pen_B, pen_G, pen_R
  34. cv2.destroyAllWindows()

OpenCV Python 系列教程2 - OpenCV 的 GUI 特性 - 图14

更多资料

createtrackbar API