【CV】OpenCV(基于Python)学习笔记

以下内容中的页码均来自《OpenCV 4详解 : 基于Python》

目录

第2章 载入、显示与保存数据

2.2 图像的读取与显示

2.2.1 图像读取函数 cv.imread()

函数原型:img = cv.imread(filename [, flags])

  • filename:需要读取的图像的路径,包含图像名称和图像文件扩展名
  • flags:读取图像的形式,默认按照彩色图像格式读取(可选择的标志见P27表2-2)

如果无法正确读取图像,返回None,可通过print(img)查看得到的结果是否为None来判断是否成功读取了图像。

2.2.2 图像窗口函数 cv.namedWindow()

函数原型:None = cv.namedWindow(winname [, flags])

  • winname:窗口名称,用作窗口的标识符,用于识别此窗口
  • flags:窗口属性设置标志(可选择的标志见P28表2-3)

flags标志可以设置多个,不同参数之间用“|”分隔,默认为根据图像大小显示窗口、保持图像比例、创建的窗口允许添加工具栏和状态栏

2.2.3 图像显示函数 cv.imshow()

函数原型:None = cv.imshow(winname, img)

  • winname:要显示图像的窗口的名称
  • img:要显示的图像

为了让图像不是一闪而过的,需要在本函数后加上cv.waitKey()函数,来将程序暂停一段时间,暂停时间可以以参数的形式赋值,单位为毫秒;参数默认值为0,表示等待用户按键结束该函数。

2.2.4 关闭窗口函数 cv.destroyWindow()/cv.destroyAllWindows()

函数原型:
None = cv.destroyWindow(winname)
None = cv.destroyAllWindows()

  • winname:要关闭的窗口的名称

2.3 视频的加载与摄像头的调用

2.3.1 读取视频数据 cv.VideoCapture()

函数原型:
<VideoCapture object> = cv.VideoCapture()
<VideoCapture object> = cv.VideoCapture(filename [, apiPreference])

  • filename:读取的视频文件的名称
  • apiPreference:读取数据时设置的属性

第一行中的VideoCapture函数需要在使用时通过open()函数指出,如对象名为video,则用video.open("testvideo.mov")来打开视频文件。
第二行中的VideoCapture函数在默认情况下自动搜索合适的视频属性标志,在使用时一般可以省略属性标志。

  • 创建视频对象后,用isOpened()函数判断是否创建成功,成功返回True,失败返回False。如video.isOpened()
  • 判断已经成功创建视频对象后,用read()函数读取一帧图像,如通过ret, img = viedo.read()从video对象中读取一帧图像存放在img中,ret变量存储是否成功读取对象,成功为True,失败为False。也可以通过ret变量判断读取视频文件时是否已经到了结尾。
  • 另外,可以通过get(propId)函数获取视频属性,如video.get(0)propId的可选标志见P30表2-4

示例代码(来自书本,略有改动,后同):

import cv2 as cv

if __name__ == '__main__':
    video = cv.VideoCapture('./videos/road.mp4')

    # 判断是否成功创建视频流
    while video.isOpened(): # video.isOpened()成功读取返回true,读取失败返回false
        ret, frame = video.read() # frame中存储一帧的图像;ret读取成功为true,读取失败为false
        if ret is True:
            cv.imshow('Video', frame)
            # 设置视频播放速度,设置值等于1000为原速度,高于1000会减慢,低于1000加快
            # 此代码为按视频原速度播放,cv.CAP_PROP_FPS表示原视频的帧率
            cv.waitKey(int(1000 / video.get(cv.CAP_PROP_FPS)))
            # 按下q退出
            if cv.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break

    # 输出相关信息
    print('视频中图像的宽度为:{}'.format(video.get(cv.CAP_PROP_FRAME_WIDTH)))
    print('视频中图像的高度为:{}'.format(video.get(cv.CAP_PROP_FRAME_HEIGHT)))
    print('视频帧率为:{}'.format(video.get(cv.CAP_PROP_FPS)))
    print('视频总帧数为:{}'.format(video.get(cv.CAP_PROP_FRAME_COUNT)))
    # 释放并关闭窗口
    video.release()
    cv.destroyAllWindows()
    

关于if __name__ == '__main__'的解释点此查看

2.3.2 摄像头的直接调用 cv.VideoCapture()

函数原型:<VideoCapture object> = cv.VideoCapture(index [, apiPreference])

  • index:摄像头的索引号,0表示使用计算机的默认摄像头
  • apiPreference:读取数据时设置的属性

示例代码与2.3.1基本相同,另可以在cv.imshow('Video', frame)前添加frame = cv.flip(frame, 1)对摄像头拍摄的图像进行水平翻转,翻转后的视频为镜像,若不添加上述代码也可,视频为非镜像状态。

2.4 数据的保存

2.4.1 保存图像 cv.imwrite()

函数原型:retval = cv.imwrite(filename, img [, params])

  • filename:图像保存的路径和文件名,包含图像格式
  • img:将要保存的图像(Array类型的数组)
  • params:保存图片格式时的属性设置标志

如果成功保存,返回True,失败返回False

函数第三个参数一般不需要填写,第三个参数的设置方式如下:

# 将img以等级为95的图像质量保存
cv.imwrite(filename, img, [int(cv.IMWRITE_JPEG_QUALITY), 95])
# 将img以值为6的压缩级别进行保存
cv.imwrite(filename, img, [int(cv.IMWRITE_PNG_COMPRESSION), 6])

第三个参数的可选择标志见P33表2-5

2.4.2 保存视频 cv.VideoWriter()

函数原型:
<VideoWriter object> = cv.VideoWriter()
<VideoWriter object> = cv.VideoWriter(filename, fourcc, fps, frameSize [, isColor])

  • filename:保存视频的路径和文件名
  • fourcc:压缩帧的4字符编/解码器选项
  • fps:保存视频的帧率,即每秒多少张图像
  • frameSize:视频帧的大小
  • isColor:表示是否以彩色形式保存视频,默认为彩色

第一行的VideoWriter函数与VideoCapture函数相同,后续需要通过open()函数设置保存的文件名称等参数。

fourcc参数可以设置的编解码器选项见P35表2-6,如果赋值为“-1”则会自动搜索合适的编解码器。

frameSize参数一定要与图像的尺寸相同。

示例代码如下:

import cv2 as cv

if __name__ == '__main__':
    # 设置编/解码方式
    fourcc = cv.VideoWriter_fourcc(*'DIVX')

    #  采用默认摄像头获取图像
    video = cv.VideoCapture(0)
    # cv.VideoWriter()第一种构造函数(两种方法效果相同)
    # result = cv.VideoWriter()
    # result.open('./videos/Save_video.avi', fourcc, 20.0, (640, 480))
    # cv.VideoWriter()第二种构造函数
    result = cv.VideoWriter('./videos/Save_video.avi', fourcc, 20.0, (640, 480))

    # 判断是否成功创建视频流
    while video.isOpened():
        ret, frame = video.read()
        if ret is True:
            # 将每一帧图像进行水平翻转
            frame = cv.flip(frame, 1)

            # 将一帧一帧图像写入视频
            result.write(frame)
            cv.imshow('Video', frame)
            cv.waitKey(25)

            # 键盘按下q退出
            if cv.waitKey(1) & 0xFF == ord('q'):
                break
        else:
            break

    # 释放并关闭窗口
    video.release()
    result.release()
    cv.destroyAllWindows()

2.4.3 保存和读取XML和YMAL文件 cv.FileStorage()

2.4.3.1 保存

首先进行初始化
函数原型:<FileStorage object> = cv.FileStorage(filename, flags [, encoding])

  • filename:打开的文件名称
  • flags:对文件执行的操作类型标志(详见P37表2-7)
  • encoding:编码格式

该函数用于声明打开的文件名称和操作的类型。
filename为字符串类型,文件的扩展名可以是“.xml”“.ymal”“.yml”。
flags参数表示对文件执行读取操作、写入操作等。

打开文件后,可以使用isOpened()来判断是否成功打开文件,成功打开返回True,打开失败返回False。

cv.FileStorage()函数中没有声明参数,可通过open()函数单独声明,函数原型如下:
retval = cv.FileStorage.open(filename, flags [, encoding])

  • filename:打开的文件名称
  • flags:对文件执行的操作类型标志(详见P37表2-7)
  • encoding:编码格式

成功打开文件后,使用cv.FileStorage.write()函数将数据写入文件中,函数原型如下:
None = cv.FileStorage.write(name, val)

  • name:写入文件中的变量名称
  • val:变量值(目前支持实数、字符串和矩阵)
2.4.3.2 读取
  • 读取实数型
    file.getNode('x').real()
  • 读取字符串型
    file.getNode('x').string()
  • 读取矩阵型
    file.getNode('x').mat()

对2.4.3的示例代码:

import cv2 as cv
import numpy as np

if __name__ == '__main__':
    # 创建FileStorage对象file,用于写入数据
    # 读者可以尝试将文件后缀名改为.yml或.yaml
    # file = cv.FileStorage('./data/MyFile.yml', cv.FileStorage_WRITE)
    # file = cv.FileStorage('./data/MyFile.yaml', cv.FileStorage_WRITE)
    file = cv.FileStorage('./data/MyFile.xml', cv.FileStorage_WRITE)

    # 写入数据
    file.write('name', '张三')
    file.write('age', 16)
    file.write('date', '2019-01-01')
    scores = np.array([[98, 99], [96, 97], [95, 98]])
    file.write('scores', scores)

    # 释放对象
    file.release()

    # 创建FileStorage对象file1,用于读取数据
    file1 = cv.FileStorage('./data/MyFile.xml', cv.FileStorage_READ)

    # 判断MyFile.xml文件是否成功打开
    if file1.isOpened():
        # 读取数据
        name1 = file1.getNode('name').string()
        age1 = file1.getNode('age').real()
        date1 = file1.getNode('date').string()
        scores1 = file1.getNode('scores').mat()

        # 展示读取结果
        print('姓名:{}'.format(name1))
        print('年龄:{}'.format(age1))
        print('记录日期:{}'.format(date1))
        print('成绩单:{}'.format(scores1))
    else:
        print('Can\'t open MyFile.xml.')

    # 释放对象
    file1.release()

第3章 图像基本操作

3.1 颜色空间

3.1.1.6 不同颜色空间之间的互相转换 cv.cvtColor()

函数原型:dst = cv.cvtColor(src, code, [, dst [, dstCn]])

  • src:待转换颜色空间的原始图像
  • code:颜色空间转换的标志(详见P44表3-1)
  • dst:颜色空间转换后的目标图像
  • dstCn:目标图像中的通道数,默认为0

3.1.2 多通道分离与合并 cv.split()/cv.merge()

3.1.2.1 分离 cv.split()

函数原型:mv = cv.split(m [, mv])

  • m:待分离的多通道图像
  • mv:分离后的单通道图像
3.1.2.2 合并 cv.merge()

函数原型:dst = cv.merge(mv [, dst])

  • mv:需要合并的图像
  • dst:合并后输出的图像

3.2 图像像素的操作

3.2.1 图像像素统计

3.2.1.1 寻找图像像素的最大值与最小值 cv.minMaxLoc()

函数原型:
minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(src [, mask])

  • src:需要寻找最大值和最小值的图像(图像可表示为矩阵)
  • mask:图像掩模(用于在图像的指定区域内寻找最值,默认值为None,表示寻找范围为整个图像)
  • minVal:图像中的最小值
  • maxVal:图像中的最大值
  • minLoc:图像中的最小值在矩阵中的坐标
  • maxLoc:图像中的最大值在矩阵中的坐标

若图像中存在多个最值,则输出的最值位置为按行扫描从左至右第1次检测到的最值位置

3.2.1.1.1 图像矩阵形状调整函数 np.reshape()

函数原型:dst = np.reshape(array, shape [, order])

  • array:需要调整尺寸和通道数的图像
  • shape:重塑后的矩阵的维度
  • order:读取/写入元素时的顺序
3.2.1.2 计算图像的均值和标准差 cv.mean()/cv.meanStdDev()

求均值函数原型:retal = cv.mean(src [, mask])

  • src:待求均值的图像(其通道数为1~4的整数)
  • mask:图像掩模(不输出此参数时,表示取所有像素的均值)

同时求均值和标准差函数原型:
mean, stddev = cv.meanStdDev(src [, mean [, stddev [, mask]]])

  • src:待求均值和标准差的图像
  • mean:图像每个通道的均值
  • stddev:图像每个通道的标准差
  • mask:图像掩模

3.2.2 两图像间的像素操作

3.2.2.1 两幅图像的比较运算 cv.max()/cv.min()

函数原型:
dst = cv.max(src1, src2 [, dst])
dst = cv.min(src1, src2 [, dst])

  • src1:第1幅图像,可以是任意通道数的矩阵
  • src2:第2幅图像,尺寸、通道数及数据类型与第1个参数一致
  • dst:保留对应位置较大(较小)灰度值后的图像

判断每一个像素点,保留两幅图像中灰度值较大(较小)的像素点

3.2.2.2 两幅图像的逻辑运算 cv.bitwise_?()

函数原型:
与运算:dst = cv.bitwise_and(src1, src2 [, dst [, mask]])
或运算:dst = cv.bitwise_or(src1, src2 [, dst [, mask]])
异或运算:dst = cv.bitwise_xor(src1, src2 [, dst [, mask]])
非运算:dst = cv.bitwise_not(src [, dst [, mask]])

  • src1:第1幅图像,可以是多通道图像数据
  • src2:第2幅图像,尺寸、通道数及数据类型与第1个参数一致
  • dst:逻辑运算输出结果
  • mask:掩模矩阵,用于设置图像或矩阵中逻辑运算的范围
  • src:输入的图像矩阵

ps:异或运算:相同为0,不相同为1

3.2.3 图像二值化

函数原型:retval, dst = cv.threshold(src, thresh, maxval, type [, dst])

  • src:待二值化的图像,图像的数据类型只能是uint8或float32
  • thresh:二值化的阈值
  • maxval:二值化过程中的最大值。此参数只在两种二值化方法中发挥作用,但使用其他方法也需要输入此参数
  • type:选择图像的二值化方法的标志(可选择的标志见P57表3-2)
  • dst:二值化后的图像

局部自适应阈值的二值化函数原型:
dst = cv.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C [, dst])

  • src:待二值化的图像,只能是8位单通道类型的图像
  • maxValue:二值化后的最大值,要求为非零数
  • adaptiveMethod:自适应确定阈值的方法,分为均值法(cv.ADAPTIVE_THRESH_MEAN_C)和高斯法(cv.ADAPTIVE_THRESH_GAUSSIAN_C
  • thresholdType:选择图像二值化方法的标志,只能是cv.THRESH_BINARYcv.THRESH_BINARY_INV
  • blockSize:自适应确定阈值的像素领域大小,一般取值为3、5、7
  • C:从平均值或者加权平均值中减去的常数,可正可负
  • dst:二值化后的图像,与输入图像具有相同的尺寸、数据类型

3.2.4 LUT cv.LUT()

函数原型:dst = cv.LUT(src, lut [, dst])

  • src:输入的图像,仅支持8位
  • lut:256个灰度值的查找表
  • dst:输出图像

3.3 图像连接和图像变换

3.3.1 图像连接 cv.vconcat()/cv.hconcat()

图像垂直连接函数原型:dst = cv.vconcat(src [, dst])

  • src:需要连接的图像(可以用矩阵表示)(要求均具有相同的长度、数据类型和通道数)
  • dst:连接后的图像(可以用矩阵表示)

图像水平连接函数原型:dst = cv.hconcat(src [, dst])

  • src:需要连接的图像(可以用矩阵表示)(要求均具有相同的高度、数据类型和通道数)
  • dst:连接后的图像(可以用矩阵表示)

示例:img = cv.hconcat((img0, img1))

3.3.2 图像尺寸变换 cv.resize()

函数原型:dst = cv.resize(src, dsize [, dst [, fx [,fy [, interpolation]]]])

  • src:输入的图像
  • dsize:输出图像的尺寸
  • dst:输出图像
  • fx:水平轴的比例因子,如果沿水平轴将图像放大为原来的2倍,则指定为2
  • fy:垂直轴的比例因子,如果沿垂直轴将图像放大为原来的2倍,则指定为2
  • interpolation:插值方法的标志(可以选择的标志见P66表3-3)

3.3.3 图像翻转变换 cv.flip()

函数原型:dst = cv.flip(src, flipCode [, dst])

  • src:输入的图像
  • flipCode:翻转方式标志。数值大于0,绕y轴翻转;数值等于0,绕x轴翻转;数值小于0,绕两条轴翻转
  • dst:输出的图像

3.3.4 图像仿射变换(三点变换) cv.getRotationMatrix2D()/cv.warpAffine()/cv.getAffineTransform()

计算旋转矩阵的函数原型:retal = cv.getRotationMatrix2D(center, angle, scale)

  • center:图像旋转的中心
  • angle:图像旋转的角度,正值代表逆时针旋转
  • scale:沿两条轴的缩放比例,可以实现旋转过程中的图像缩放。不需要缩放输入1

确定旋转矩阵后,进行仿射变换后实现图像的旋转。
仿射变换函数原型:
dst = cv.warpAffine(src, M, dsize [, dst [, flags [, borderMode [, borderValue]]]])

  • src:输入的图像
  • M:2×3的变换矩阵(之前求得的旋转矩阵)
  • dsize:输出图像的尺寸
  • dst:放射变换后的输出图像,尺寸与dsize相同
  • flags:插值方法的标志(详见P69表3-4)
  • borderMode:像素边界外推方法的标志
  • borderValue:填充边界使用的数值,默认为0

利用三点求变换矩阵函数原型:retval = cv.getAffineTransform(src, dst)

  • src:原图像中3个像素的坐标
  • dst:目标图像中对应的3个像素的坐标

3.3.5 图像透视变换(四点变换) cv.getPerspectiveTransform()/cv.wrapPerspective()

利用四点求变换矩阵函数原型:retval = cv.getPerspectiveTransform(src, dst [, solveMethod)

  • src:原图像中4个像素的坐标
  • dst:目标图像中对应的4个像素的坐标
  • solveMethod:选择计算透视变换矩阵方法的标志(详见P72表3-6),默认为最佳主轴元素的高斯消元法

透视变换矩阵函数原型dst = cv.wrapPerspective(src, M, dsize [, dst [, flags [, borderMode [, borderValue]]]])

  • src:输入的图像
  • M:3×3的变换矩阵(之前求得的旋转矩阵)
  • dsize:输出图像的尺寸
  • dst:放射变换后的输出图像,尺寸与dsize相同
  • flags:插值方法的标志(详见P69表3-4)
  • borderMode:像素边界外推方法的标志
  • borderValue:填充边界使用的数值,默认为0

3.3.6 极坐标变换

函数原型:dst = cv.warpPolar(src, dsize, center, maxRadius, flags [, dst])

  • src:原图像
  • dsize:目标图像的大小
  • center:极坐标变换时极坐标在原图像中的原点
  • maxRadius:变换时边界圆的半径
  • flags:插值方法与极坐标映射方法的标志(插值方法见P66表3-3,极坐标映射方法见P74表3-7)
  • dst:极坐标变换后的输出图像
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fannnnf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值