OpenCV-py学习笔记(一)—— 基本图像/视频输入输出

Posted by 刘知安 on 2019-10-26
文章目录
  1. 图像的相关操作
    1. 1.读取图片代码
  • 视频的相关操作
    1. 1.读取播放视频代码
    2. 2.打开摄像头并保存视频代码
  • 画图的相关操作
    1. 1.画图函数测试
    2. 2.画OpenCV-LOGO
  • @[TOC]

    图像的相关操作

    需要注意的是,OpenCV读入图像的顺序是g、b、r的顺序,而像matplotlib这样的图像库读入图像的顺序是正常的r、g、b,所以如果想要用opencv读取图像而用matplotlib.plotlib显示时,就需要考虑一个通道翻转的问题。详情参见Stack Overflow上的讨论

    1.读取图片代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def openCV_image_ops():
    img = cv2.imread("bear.jpg")
    # print(img.shape) # (301, 400, 3)

    b, g, r = cv2.split(img)
    # print(b.shape) #(301, 400)
    # 重组后的图片
    img2 = cv2.merge([r, g, b])
    plt.subplot(121)
    plt.xticks([]) # 隐藏x、y轴
    plt.yticks([])
    plt.imshow(img)

    plt.subplot(122)
    plt.xticks([]) # 隐藏x、y轴
    plt.yticks([])
    plt.imshow(img2)

    plt.show()

    遇到的问题

    • b, g, r = cv2.split(img) ValueError: not enough values to unpack (expected 3, got 0)
      出现这个问题我后,我查看了一下split相关代码,我寻思img的确是个3维的序列呀?但是报错说里面是空的,原来是读取的图片文件名写错了。。。 cv2.imread(“bear.jpg”)之前写成了 cv2.imread(“bear.png”),OpenCV在读取不到指定的文件时是不会报错的!!!

    视频的相关操作

    视频就是一系列的连续帧(frame by frame),OpenCV中视频的操作有2种,①获取摄像头的实时操作 ②直接操作视频。以上两种操作都通过一个VideoCapture对象来管理,传入摄像头设备索引/视频文件名作为该对象的构造函数参数即可。

    1.读取播放视频代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    def openCV_video_ops():
    # 新建一个视频捕捉对象,可以通过摄像头设备索引/视频文件名
    cap = cv2.VideoCapture("video.avi")
    while True:
    # 逐帧读取
    ret, frame = cap.read()
    if ret:
    # 转为灰度图
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # 显示
    cv2.imshow("video-frame", gray)
    # 64位系统需要追加& 0xff
    if cv2.waitKey(50) & 0xff == ord('q'):
    break
    else:
    break

    cap.release()
    cv2.destroyAllWindows()

    如果想要用摄像头记录视频并保存,需要多做一些额外的工作,具体来说,需要考虑视频的FourCC编码,这个可以百度一下,还有就是要指定保存视频的fps、每帧的宽度和高度、以及是否保存成彩色。

    2.打开摄像头并保存视频代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    def openCV_camera_save():
    # 新建一个视频捕捉对象,可以通过摄像头设备索引/视频文件名
    cap = cv2.VideoCapture(0)
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    # 参数依次为保存视频名称、fourcc编码、fps、尺寸、是否彩色图(默认为true)
    out = cv2.VideoWriter("video.avi", fourcc, 20.0, (640, 480))

    while cap.isOpened():
    # 逐帧读取
    ret, frame = cap.read()
    if ret == True:
    # write the frame
    out.write(frame)
    cv2.imshow('frame', frame)

    # 64位系统需要追加& 0xff
    if cv2.waitKey(1) & 0xff == ord('q'):
    break
    else:
    break

    cap.release()
    out.release()
    cv2.destroyAllWindows()

    画图的相关操作

    画图的机制是,先设置一个底板,然后在底板上画出响应的图形,具体的参加>>官方文档<<,总体来说,和其他语言中的绘图部分差不多,下面我测试了几个画图函数,并且我用OpenCV中提供的椭圆、圆、文字绘制函数画出了OpenCV的logo。

    1.画图函数测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    def openCV_drawing_ops():
    # 画图的黑色底板
    img = np.zeros((512, 512, 3), np.uint8)
    # 从点(10,10)到点(110,110)画一条蓝色的线,thickness 5 px
    cv2.line(img, (10, 10), (110, 110), (255, 0, 0), 5)
    # 从点(120, 120)到点(220, 220)画一个绿色的矩形,thickness 3 px
    cv2.rectangle(img, (120, 120), (220, 220), (0, 255, 0), 3)
    # 以(260, 260)为中心,半径为30,画一个红色的圆,-1表示填充
    cv2.circle(img, (260, 260), 30, (0, 0, 255), -1)
    # 在图片上写字
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(img, 'OpenCV', (10, 500), font, 4, (255, 255, 255), 2, cv2.LINE_AA)

    cv2.imshow("OpenCV drawing ops", img)
    cv2.waitKey()

    在这里插入图片描述

    就是3个同心圆环,再加上字体,注意,三个圈中间是个等边三角形

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    def draw_openCV_logo():
    # 画图的黑色底板
    img = np.zeros((500, 500, 3), np.uint8)

    min_circle = 20
    max_circle = 50
    gap = 20

    green_circle_center_x = 180
    green_circle_center_y = 200
    green_blue_distance = int(2 * max_circle + gap)
    green_red_distance_x = int(green_blue_distance / 2)
    green_red_distance_y = int(green_red_distance_x * 1.732)

    # 绿色圈
    cv2.ellipse(img, (green_circle_center_x, green_circle_center_y), (max_circle, max_circle), 0, 0, 300, (0, 255, 0),
    -1, cv2.LINE_AA)
    cv2.circle(img, (green_circle_center_x, green_circle_center_y), min_circle, (0, 0, 0), -1, cv2.LINE_AA)

    # 蓝色圈
    cv2.ellipse(img, (green_circle_center_x + green_blue_distance, green_circle_center_y), (max_circle, max_circle),
    0, -60, 240, (255, 0, 0), -1, cv2.LINE_AA)
    cv2.circle(img, (green_circle_center_x + green_blue_distance, green_circle_center_y), min_circle, (0, 0, 0), -1,
    cv2.LINE_AA)

    # 红色圈
    cv2.ellipse(img, (green_circle_center_x + green_red_distance_x, green_circle_center_y - green_red_distance_y),
    (max_circle, max_circle), 0, -240, 60, (0, 0, 255), -1, cv2.LINE_AA)
    cv2.circle(img, (green_circle_center_x + green_red_distance_x, green_circle_center_y - green_red_distance_y),
    min_circle, (0, 0, 0), -1, cv2.LINE_AA)

    # 在图片上写字
    font = cv2.FONT_ITALIC
    cv2.putText(img, 'OpenCV', (65, 350), font, 3, (255, 255, 255), 2, cv2.LINE_AA)

    cv2.imshow("OpenCV logo", img)
    cv2.waitKey()

    在这里插入图片描述

    遇到的问题

    • OpenCV窗口的标题栏,如果用中文会乱码,因为OpenCV中用的是gbk,python中是utf-8,目前好像还没有好的解决办法,改成英文吧。。。