OpenCV

opencv-python

一般性说明

安装

详细可以参考 opencv-python 仓库的 README 文档

pip install opencv-python  # 无需另外编译安装opencv

注意,存在四种使用 pip 的方式进行安装,但只能选择其中的一种,若已经安装了其中的一个,想要安装另一个,则必须将之前的使用 pip uninstall 卸载掉。

pip install opencv-python  # 只包含主要的模块
pip install opencv-contrib-python  # 完整安装:包含主要模块及contrib/extra模块
pip install opencv-python-headless # 包含主要模块,但去除了cv2.imshow这种输出的功能,适用于无图形界面的服务器,体积比opencv-python要小
pip install opencv-contrib-python-headless

导入

import cv2

注意点

  • cv2 包里函数的参数 size 一般为 (width, height),表示宽与高。

  • cv2 使用使用 numpy 数组来表示图像,数组的数据类型必须为 uint8,即 dtype=np.uint8。并且数组的形状为 channel_last 的方式,例如:

    • RGB 图像的表示形式是形状为 (H, W, 3) 的数组,其中通道的存储顺序为 BGR,许多函数例如 cv2.putText 拥有参数 color 表示颜色,其取值必须为一个整数的三元组,且取值为 [0, 255] 区间内的整数,同样遵循 BGR 的顺序,例如:color=(255, 0, 0) 表示蓝色。

    • 灰度图像的表示形式是形状为 (H, W) 的数组

  • cv2 中的函数对 numpy数组进行操作时往往需要 numpy 数组的内部存储是 C 连续的,numpy 中对数组的某些操作会使得数组变的不是 C 连续的,例如:

    • np.transpose

    • 负间隔的切片操作:arr = arr[::-1,:,:]

    这种情况下需要首先使用如下方法将 numpy 数组转换,再利用 cv2 的相关函数对转换后的数组进行操作

    arr = np.ascontiguousarray(arr)
  • cv2 的许多函数是 inplace 的,例如一些绘制图像的函数。例如:

    import numpy as np
    import cv2
    image = np.zeros((224, 224, 3), dtype=np.uint8)
    print(image.any())  # False
    # 通常的写法是不需要接收返回值的,此处是为了说明问题
    x = cv2.putText(image, "mark", (100, 200), cv2.FONT_HERSHEY_COMPLEX, 5, (0, 0, 255))
    print(x.any(), image.any(), x is image)  # True, True, True

    如果不想对原图进行修改,需要首先调用 numpy 数组的 copy 方法再进行处理,例如:

    image = np.zeros((224, 224, 3), dtype=np.uint8)
    print(image.any())  # False
    x = cv2.putText(image.copy(), "mark", (100, 200), cv2.FONT_HERSHEY_COMPLEX, 5, (0, 0, 255))
    print(x.any(), image.any(), x is image)  # True, False, False
  • cv2 里许多函数的参数的取值会是“标志位”,例如:cv2.COLOR_BGR2RGBcv2.LINE_8,其来源于 opencv 的 C++ 源码中所定义的宏,一般用于控制同一接口下的不同算法,这些标志位实际上是一些整数,例如:cv2.COLOR_BGR2RGB==4cv2.LINE_8==8。通常情况下推荐使用宏名而不要直接使用它所代表的整数。

图像读写操作

详细可参考官方文档

imreadimwrite

cv2.imread

  • cv2.IMREAD_COLOR:得到的图像为 BGR 格式的 numpy 数组

  • cv2.IMREAD_UNCHANGED:原样解码,例如:若图像原本存储了 RGBA 格式的数据,则读出来也会是四通道的 numpy 数组

  • cv2.IMREAD_GRAYSCALE:得到的图像是形状为 (H, W) 的灰度图像

  • ...

备注:需要格外注意,若读入不成功,比如文件路径不存在,image 将会是 None,但该条读入语句并不会报错引起程序中断。

cv2.imwrite

第三个参数可选,含义如下:

  • cv2.IMWRITE_JPEG_QUALITY=1:JPEG 格式,0-100 的整数,表示图像质量,默认为 95。

  • cv2.IMWRITE_PNG_COMPRESSION=16:PNG 格式,0-9表示压缩级别,级别越高图像越小,默认值为 3。

备注:JPEG 格式为有损压缩;而 PNG 格式为无损压缩,PNG 的压缩级别会影响编码解码时间。

备注:imread 与 imwrite 的返回值若为 True,则表示读入或写入成功,否则表示失败。

imencodeimdecode

(可跳到最后直接看总结😄

imreadimwrite 是高级接口,当路径中存在中文字符时,imreadimwrite 会无法读写文件,这种时候可以结合 numpy 进行处理:

  • 利用低级接口 imencodeimdecode 对数据进行编码与解码

  • 文件 IO 操作使用 numpy 的相关方法例如 fromfiletofile 等方法进行

首先介绍 imencodeimdecode 方法

cv2.imencode

cv2.imdecode

注:此处似乎无需指定按什么方式解码,有些可疑。

接下来介绍 numpy 的相关方法,注意这些方法是与 cv2 无关的一套 numpy 存储文件的做法。

np.ndarray.tofile、np.ndarray.tobytes

np.ndarray.tofile 用于将数组存入文件

更细致的写入方式是,先将数组用 np.tobytes 转换为字节,再将的得到的字节以二进制形式写入文件

np.fromfile 用于读取用 np.ndarray.tofile 存入的文件

更细致的读取方式是,先将要读取的文件以二进制形式读取,再将得到的字节用 np.frombuffer 得到

总结(太长不看的直接看这里)

RGB 与 BGR 转换(cv2 默认使用 BGR 格式)

备注:可以调整 cv2.cvtColor 函数的第二个参数的取值进行许多其他的转换,例如:

  • cv2.COLOR_BGR2GRAY:表示将 BGR 图片转换为灰度图片

在图像上绘制

详细可参考官方文档

画点(实际上是在画圈)

备注:

  • lineType

添加文字(非英文会乱码)

关于bottomLeftOrigin的有错,待补充

获取字体大小

添加线、矩形、多边形

画线段

画矩形

画多边形

方法一:使用 cv2.polylines

方法二:使用 cv2.drawContours

图像变换

变换公式为(tform.estimate 实际上就是在估计 M):

dstx=a0srcxb0srcy+a1=s[srcxcos(θ)srcysin(θ)]+a1dsty=b0srcx+a0srcy+b1=s[srcxsin(θ)+srcycos(θ)]+b1\begin{align} dst_x &= a_0*src_x-b_0*src_y+a_1\\ &=s*[src_x*cos(\theta)-src_y*sin(\theta)]+a_1\\ dst_y &= b_0*src_x+a_0*src_y+b_1\\ &=s*[src_x*sin(\theta)+src_y*cos(\theta)]+b_1 \end{align}

即:

[dstxdsty0]=[a0b0a1b0a0b1001][srcxsrcy0]\begin{bmatrix} dst_x\\dst_y\\0 \end{bmatrix} = \begin{bmatrix} a_0&-b_0&a_1\\ b_0&a_0&b_1\\ 0&0&1 \end{bmatrix} \begin{bmatrix} src_x\\src_y\\0 \end{bmatrix}

cv2.minAreaRect

cv2.getRotationMatrix2D

此函数用于获取绕某一中心点旋转后的变换矩阵

[dstx1dsty1]==α[cosθsinθsinθcosθ][x1x0y1y0]+[x0y0]\begin{bmatrix} dstx_1\\dsty_1 \end{bmatrix}=\cdots=\alpha \begin{bmatrix} cos\theta&sin\theta\\ -sin\theta&cos\theta \end{bmatrix} \begin{bmatrix} x_1-x_0\\ y_1-y_0 \end{bmatrix}+ \begin{bmatrix} x_0\\ y_0 \end{bmatrix}

故变换矩阵为:

M=[αM0,(IαM0)[x0y0]]R2×3M=[\alpha M_0,(I-\alpha M_0)\begin{bmatrix}x_0\\y_0\end{bmatrix}]\in\mathbb{R}^{2\times3}

cv2.warpAffine

[dstx,dsty]T=M[:,:1][x,y]T+M[:,:1][dst_x,dst_y]^T=M[:,:-1][x,y]^T+M[:,:-1]

逆变换方式可以推算为

(x,y)=M[:,:1]1(dstx,dsty)M[:,:1]1M[:,1](x,y)=M[:,:-1]^{-1}(dst_x,dst_y)-M[:,:-1]^{-1}M[:,-1]

cv2.getPespectiveTransform(待补充)

与findHomography, warpPerspective, perspectiveTransform相关

求解如下方程

[tixitiyiti]=M[xiyi1]i=0,1,2,3\begin{bmatrix} t_ix_i'\\t_iy_i'\\t_i \end{bmatrix}=M \begin{bmatrix} x_i\\y_i\\1 \end{bmatrix} \quad i=0,1,2,3

opencv 处理视频

图像修复

cv2.inpaint

OpenCV C++ API

安装:windows VS2017 + OpenCV C++

https://sevenold.github.io/2019/01/opencv-setup/

Tricks and Discussion and Have Fun

找不到关于 opencv-python 的准确接口文档

似乎的确是没有😢,目前能找到的只是官方的python-tutorial,以及 C++ 接口文档里附上的关于python接口的简要说明。

Last updated

Was this helpful?