OpenCV学习笔记(更新中...)

OpenCV-Python😀

CSDN:OpenCV学习_笨小古的博客-CSDN博客

1.OpenCV常用的Python内置函数

1.1 ord 函数

​ 在计算机视觉中,使用者时常需要与计算机本身进行交互。比如打开摄像头进行拍照时,机器本身可能很难知道使用者想要它在什么时刻进行拍照动作,但是我们可以通过手动操作来实现。而我们与系统的交互一般传递的是 ASCII (American Standard Code for Information Interchange, 美国信息交换标准码),为此我们需要将键盘输入的字符转为 ASCII 来让计算机明白我们想要它去做什么操作。

​ 那么首先要学习的便是实现使用者与计算机之间交互的基础——将键盘输入的字符转换为 ASCII 数值或 Unicode(统一码)数值。

​ ord 函数的语法如下。

ord(char)

​ 其中char为一个字符类型的参数,它的返回值是char所对应的十进制整数 ASCII 数值,如 ord(‘a’) 返回97, ord(‘A’)返回65.

​ **注意:**如果所给的Unicode字符超出了Python的定义范围,则会引发一个名为"TypeError"的异常。

1.2 max 函数和 min 函数

​ 如果将图片看成一种输入信号,那么其中难免会有噪声干扰计算机本身进行兴趣数据(即使用者想要的数据)的提取。为了尽可能减少干扰,我们常常会使用 max 函数和 min 函数来对含有噪声的图像进行去噪操作。

(在计算机视觉处理中,我们一般认为图像指的是“数字图像”,是一种原始连续信号经过抽样、量化后的结果状态:而图片则更多蕴含的是一种“初始”的概念,定义的范围比图像更加广泛。可以说,图像是图片的一种表达形式)

​ max 函数和 min 函数分别返回给定参数的最大值与最小值。

​ max 函数的语法如下,[符号后表示的是参数可选项,可以不使用。

max(iterable, *[, key, default])

​ max 函数的参数解释如下:

- iterable: 一个可迭代对象。
- key: 可以理解为一个排列的方法。

​ 示例代码如下。

b = ['a', 'B']

print(max(b))

print(max(b,key=str.upper))

​ 第二行代码的运行结果为a,因为此时 max 函数会按照全体 ASCII 的顺序去比较数值大小,a–97,B–66,所以最大值为a。但是如果我们加入key的参数,如上面第三行:

key=str.upper

​ max 函数的排列顺序就按照字符的大写的 ASCII 数值去比较,此时a的大写字符A的 ASCII 数值为65,而B的 ASCII 数值为66,所以第三行代码的运行结果为B。

​ min 函数的语法和max 函数一致,只是返回值为给定参数的最小值。

​ **注意:**key 后面可以跟对象参数的方法。

1.3 sorted 函数

​ 与 max 函数和 min 函数相同,sorted 函数也可以用来提高程序抗图片噪声干扰的能力。 sorted 函数的作用是对所有可迭代的对象进行排序。

​ 该函数的语法如下。

sorted(iterable, cmp=None, key=None, reverse=False)

​ sorted 函数的参数解释如下。

- iterable: 一个可迭代对象。
- cmp: 一个比较函数,其具有两个参数,参数的值都是从可迭代对象中取出的;此函数必须满足一个条件,即大于则返回1,小于则返回-1,等于则返回0.
- key: 和 max 函数、min 函数中的 key 一样,主要是用来进行计较的元素,只有一个参数,具体的函数取自可迭代对象,指定可迭代对象中的一个元素来进行排序。
- reverse: 控制排序规则,如果 reverse=True,则为从大到小;如果 reverse=False,则为从小到大(默认为False)。

​ 返回值为经过处理的列表。

​ 示例代码如下。

a=[1,2,3,4,5]

b=sorted(a,reverse=True)

print(b)

​ 其运行结果如下:

[5,4,3,2,1]

2.常见的错误

2.1 未知&0xff产生的错误

​ &0xff是用户在调用 cv2.waitKey 的时候经常会加在后面的代码,但是它的意义到底是什么呢?如果你的计算机操作系统是64位的,在使用 cv2.waitKey 这个函数时就需要在其后加上&0xff,形式如下。

cv2.waitKey(0)&0xff

​ 因为系统中的各个按键(例如键盘上的q键)都在 ASCII 表中有一个对应的值,但是系统中各个按键对应的 ASCII 码值并不一定只有8位(即不同系统中对应的 ASCII 码值不一定相同),但最后8位一定相同,所以此处加上&0xff是为了排除不同系统对判断按键的干扰。

3.图片与初用 OpenCV

主要内容:

  • 图片在计算机中的几种存储形式。
  • 图片的读取与延时操作。
  • 图片的各种输出形式。

3.1 图片在计算机中的存储形式

​ 一张 1024 x 960 像素的图片,如果我们在程序里使用它或者对它进行一些操作,那么它就是一个 960 行、1024 列的二维矩阵。矩阵的每一个元素存储的都是一个列表,而列表里面存在的则是各个通道的值,那什么是通道呢?

​ 在学习通道之前,先了解一下图片的几种存储形式。

3.1.1 BGR图

​ 我们平常在生活里拍摄的图片一般是 RGB (R:红色, G:绿色, B:蓝色)格式的图片,而在OpenCV里,图片使用的格式是 BGR,两者本质上没有区别,只是使用的习惯不同。调节3种颜色的值可以构成不同颜色的像素点,但是我们在处理图片的时候,一般都不直接采用 BGR 图进行操作,而是需要进行图片颜色格式的转换。

​ 我们称B、G、R为图片上每个像素点构成的通道,所以BGR图是一个三通道(蓝、绿、红3种通道)图片。在OpenCV里,每个通道的取值范围均为0~255,我们可以通过Python中的元组的形式进行颜色的合成,如(255, 255, 255)为白色,(0, 0, 0)为黑色。

3.1.2 灰度图

​ 相比于 BGR 图,灰度图的每个像素点不再由 B、G、R这3个通道构成,它只由一个通道来控制,即灰度值,所以灰度图是由灰度值来控制的单通道图。灰度图的取值范围为0~255;如果取0表示黑色;如果取255表示白色。

3.1.3 HSV图

​ HSV图显示出来也是彩色的,且HSV图也是由3个通道构成的,只不过HSV图里的3个通道和BGR图中的不同,它的3个通道的介绍分别如下。

  • H:色彩或者色度,它的取值范围是0~179;
  • S:饱和度,它的取值范围是0~255;
  • V:亮度,它的取值范围是0~255。

​ HSV图也可以理解为BGR图的另一种表达方式,这种表达方式更有助于我们对指定颜色的物体进行追踪和提取。

3.1.4 二值图

​ 二值图可以理解为一种很特殊的灰度图,它不具有通道,并且图中的每个像素点的取值只有0或255两个值,换句话说,即非黑即白。而灰度图与二值图不同的地方就在于,灰度图可以取0~255的任何一个值。

​ 二值图的意义在于它可以帮助用户去除图片噪点,使得图片内只存在我们想要的那个物体的二值化表示部分。

3.2 图片的读取与写出

3.2.1 图片读取

进行图片的读取需要调用函数cv2.imread(),它的语法如下。

cv2.imread(filename, flag=1)

  • filename:所要读取的图片的位置(可以是相对位置,也可以是绝对位置)。
  • flag:设置读取的格式,默认为1,表示为按照BGR三通道的方式进行读取;如果选择0,则以灰度图单通道的方式进行读取。

示例代码可以如下:

import cv2

import numpy as np

img = cv2.imread('1.jpg')

​ 经此读取,img这个变量就已经是矩阵形式的"1.jpg"图片,并且它的每个像素点都是以BGR三通道的方式存储的。

​ 如果我们想要以灰度图的方式读取图片,只需要将flag参数设置为0即可,代码如下:

import cv2

import numpy as np

img = cv2.imread('1.jpg', 0)

​ 此时,img变量中保存的就是单通道的"1.jpg"图片的矩阵形式,矩阵的每个元素列表中只有一个灰度值。

3.2.2 图片的保存

​ 进行图片的保存需要调用函数cv2.imwrite(),它的语法如下。

cv2.imwrite(filename, img)

- filename:要保存的图片的名字,并且需要包含在图片的存储位置中(可以是相对位置,也可以是绝对位置)。
- img:要保存的图片的矩阵形式。

​ 示例代码如下:

import cv2

import numpy as np

img = cv2.imread('1.jpg', 0)

cv2.imwrite('1.png', img)

​ 上述代码就是将py文件夹中的图片"1.jpg"以矩阵方式读取到程序中,然后将它以"1.png"为名保存到.py文件所在的文件夹中(如果是相对位置的话;如果是绝对位置也可以存储到其他位置)。

3.2.3 BGR 图的读取与写出

img = cv2.imread(in_finename)

cv2.imwrite(out_finename, img)

​ 在有些地方可能会看到的图片显示方式与本处有所出入,尽管调用的是cv2.imread()函数,但是它后面的参数并不是1,而是cv2.IMREAD_COLOR,代码如下:

cv2.imread(filename, cv2.IMREAD_COLOR)

​ 它是与下列代码等价的。

cv2.imread(filename)

cv2.imread(filename, 1)

3.2.4 灰度图的读取与写出

​ 以灰度图的方式打开图片然后再保存:

img = cv2.imread(in_filename, 0)

cv2.imwrite(out_filename, img)

**注意:**这里保存的图片只是看起来像灰度图,如果再加载此图片,它还是以 BGR 的方式加载。

​ 当然,灰度图也有另一种读取方法,调用的依旧是cv2.imread()函数,但是后面的参数并不是0.而是cv2.IMREAD_GRAYSCALE,代码如下:

cv2.imread(filename, cv2.IMREAD_GRAYSCALE)

​ 等价于以下代码:

img = cv2.imread(filename, 0)

3.2.5 图片展示

​ 如果要在程序运行的时候观察图片的当前状态,就需要使用cv2.imshow()函数来进行图片展示,它的语法如下:

cv2.imshow(name, img)

  • name:展示窗口的名字;
  • img:图片的矩阵形式(即加载并处理后的图片)。

​ 示例代码如下:

import cv2

import numpy as np

img = cv2.imread('1.jpg', cv2.IMREAD_COLOR)

cv2.imshow('image', img)

cv2.imwrite('1_out.png', img)

# 如果使用了cv2.imshow()函数,下面一定要跟着一个摧毁窗口的函数

cv2.destroyAllWindows()

这时还会出现一个问题,就是图片弹出来一瞬间便就关闭了,这是因为 cv2.imshow() 函数并没有延时的作用,这个函数起着显示图片的作用,可是计算机的运行速度比计算机窗口的弹出速度要快,所以窗口只显示了极短的时间,代码已经执行到下一行了,图片就自动关闭了。那么,要使图片停留足够的时间以达到可以观察清楚的效果,我们需要在使用函数的这行代码和下一行代码之间加一个延时函数就可以了。

3.2.6 图片延时

​ 现在我们在 cv2.imshow() 所在行和下一行的代码之间加上一个延时函数来确保人眼能够观察清楚窗口。我们需要 cv2.waitKey 函数来做到这一点,语法如下:

cv2.waitKey(time)

​ 其中,time表示等待的时间,单位为毫秒。

​ 这个函数可以这样理解,在 time 时间内,计算机会等待我们键盘上的命令,如果在 time 时间内程序没有等待到按键指令,它就会自动进入到下一帧。因为这里是图片,没有下一帧,所以就会关闭窗口。如果将 time 设置为0,并不是表示等待0毫秒然后进入下一帧,而是停止在当前帧,有按键指令它才会进入下一帧。所以在显示单张图片的时候大多数情况都写的是cv2.waitKey(0)

3.2.7 图片读取演示

​ 直接使用cv2.waitKey(0)进行延时时,按键盘上的任何键,此程序过程都将关闭。如果想要按某个特定的键程序才会关闭,可以通过添加一个 if 语句来进行判定。如果按的键不为指定的键,就会一直处于 while 循环中,直到我们按下指定的键后才会通过 break 语句结束循环,之后才能调用 cv2.destroyAllWindows()函数来摧毁窗口。

​ 例如指定按键 q 键来退出窗口,这时 while 循环可以这样写:

while 1:

if cv2.waitKey(0) == ord('q'):

break

else:

pass

cv2.destroyAllWindows()

关于如何控制图片窗口显示的大小

​ 通过实例演示可以了解到窗口的大小取决于图片尺寸的大小,一张图片的尺寸越大,它所对应的窗口就越大,这是因为我们没有控制窗口尺寸的大小。控制窗口大小的函数为 cv2.namedWindow,其初始设定的标签为 cv2.WINDOW_AUTOSIZE,将其改为cv2.WINDOW_NORMAL 后就可以控制窗口的大小了。代码如下:

cv2.namedWindow('image', cv2.WINDOW_NORMAL)

cv2.imshow('image', img)

注意:

1.创建的窗口名字要与图片展示的窗口名字一致。

2. cv2.namedWindow 函数需要放在 cv2.imshow 函数的前面。

3.3 计算机视觉中常用的图片属性

​ 图片的行数是一张图片竖直方向上像素的个数,如一张 1024 x 960 像素的图片,它的行数就是960,列数就是1024.

import cv2

img = cv2.imread('1.jpg')

print(img.shape[0]) # 行数

print(img.shape[1]) # 列数

print(img.shope[2]) # 通道数

​ 图片的行数、列数以及通道数都保存在 img.shape 的成员里面,因此我们可以输出整个成员。

print(img.shape)

BGR图的通道数为3,如果将BGR图换成灰度图,img.shape输出的元组结果只有两个元素,即没有通道数,只有图片的行数和列数。

**注意:**二值图可以理解为一种特殊的灰度图,所以在处理二值图的时候,我们也不能调用一张二值图的通道数。

4.OpenCV的基础函数

4.1 OpenCV的绘图函数

4.1.1 画直线:cv2.line()

cv2.line(img, start_point, end_point, color, thickness=0)

- img:需要画的图像。
- start_point:直线的开头,必须是一个元组类型。
- end_point:直线的结尾,必须是一个元组类型。
- color:直线的颜色,必须是一个元组类型。
- thickness:直线的宽度。
4.1.2 画矩形:cv2.rectangle()

cv2.rectangle(img, point1, point2, color, thickness=0)

- img:需要处理的图像。
- point1:矩形左上角的点的坐标,必须是一个元组类型。
- point2:矩形右下角的点的坐标,必须是一个元组类型。
- color:线的颜色,必须是一个元组类型。
- thickness:线的宽度。
4.1.3 画圆:cv2.circle()

cv2.circle(img, center, R, color, thickness=0)

- img:要画的图像。
- center:圆心坐标,必须是一个元组类型。
- R:圆的半径。
- color:线的颜色,必须是一个元组类型。
- thickness:线的宽度,如果是-1,会变成向内填充。
4.1.4 画椭圆:cv2.ellipse()

cv2.ellipse(img, center, (a,b), direction, angle_start, angle_end, color, thickness=0)

- img:要画的图像。
- center:椭圆中心的位置。
- (a,b):椭圆的长轴和短轴。
- direction:按照顺时针方向旋转椭圆的角度。
- angle_start:画椭圆开始的角度。
- angle_end:画椭圆结束的角度。
- color:线的颜色。
- thickness:线的宽度,如果为-1,表示向内填充。
4.1.5 画多边形:cv2.polylines()

cv2.polylines(img, pts, isClosed, color, thickness=0)

- img:要画的图像。
- pts:点的集合,以列表的形式填入。
- isClosed:多边形是否闭合,如果为False则为一个不闭合的图形,如果为True则为一个闭合的图形。
- color:线的颜色。
- thickness:线的宽度。

**注意:**点的格式必须是 np.int32。

4.1.6 添加文字:cv2.putText()

cv2.putText(img, text, org, fontFace, fontScale, color, thickness=0, lineType=0)

- img:要添加文字的图像。
- text:添加的文字。
- org:添加文字的位置。
- fontFace:字体。
- fontScale:字号大小。
- color:字体颜色。
- thickness:线条的宽度。
- lineType:线条的种类。

4.1 节 OpenCV学习——绘图函数案例_笨小古的博客-CSDN博客

4.2 OpenCV 的处理鼠标事件函数

4.2.1调用回调函数

​ 关于处理鼠标事件,整个过程大致:程序一边执行下面的代码,一边等待鼠标的动作;当鼠标产生了动作(如单击屏幕),代码就去回调那个你打算在鼠标产生相应动作时运行的函数。

​ 这个过程里调用回调函数的方法:使用cv2.setMouseCallback函数。它的作用是将画面和想要回调的函数进行绑定,其语法如下:

cv2.setMouseCallback(img, onMouse)

其参数分别解释如下:

- img:要绑定的画面的名字。
- onMouse:响应函数,即当鼠标事件触发时调用的函数。
4.2.2鼠标事件

​ 可以使用如下代码查看所有被支持的鼠标事件。

# 查看所有被支持的鼠标事件
import cv2
events = [i for i in dir(cv2) if 'EVENT' in i]
print(events)

此处列举一些常用的鼠标事件:

序号参数对应的鼠标事件
1cv2.EVENT_MOUSEMOVE滑动
2cv2.EVENT_LBUTTONDOWN左键单击
3cv2.EVENT_RBUTTONDOWN右键单击
4cv2.EVENT_MBUTTONDOWN中键单击
5cv2.EVENT_LBUTTONUP左键释放
6cv2.EVENT_RBUTTONUP右键释放
7cv2.EVENT_MBUTTONUP中键释放
8cv2.EVENT_LBUTTONBLCLK左键双击
9cv2.EVENT_RBUTTONBLCLK右键双击
10cv2.EVENT_MBUTTONBLCLK中键双击
11cv2.EVENT_FLAG_LBUTTON左键拖曳
12cv2.EVENT_FLAG_RBUTTON右键拖曳
13cv2.EVENT_FLAG_MBUTTON中键拖曳
14cv2.EVENT_FLAG_CTRLKEY按Ctrl键不放
15cv2.EVENT_FLAG_SHIFTKEY按Shift键不放
16cv2.EVENT_FLAG_ALTKEY按Alt键不放
4.2.3回调函数

​ 回调函数的作用是在事件触发时,程序能够去调用它,编写回调函数时有一定的格式规范。不能随意设置参数,如下:

def callback(event, x, y, flags, param):
	if event == cv2.EVENT_LBUTTONDBLCLK:
		cv2.circle(img, (x,y), 100, (255, 0, 0), -1)

第一个参数event表示鼠标事件,x,y 可以理解为图像中鼠标指针所在的像素点的坐标值。

创建图像与窗口并将窗口与回调函数进行绑定

img = np.zeros((500,500,3), np.uint8)  # 尺寸是500x500,图像是3通道
cv2.namedWindow('image')
cv2.setMouseCallback('image', callback)
4.2.4OpenCV实现滑动式调色板

​ 通过滑动条来控制R、G、B这3个颜色的值,从而调配出各种颜色。滑动条式调色板的目标有以下两个:

  • 窗口显示颜色,3个滑动条来设置R、G、B的值;
  • 当滑动滑动条时,窗口颜色实时发生改变,默认窗口为黑色。

​ 这个过程涉及两个函数:cv2.createTrackbar 函数和 cv2.getTrackbarPos 函数。 cv2.createTrackbar 函数的作用是创建一个滑动条, cv2.getTrackbarPos 函数的作用是调用回调函数去接收指定滑动条的值。

​ cv2.createTrackbar 函数的语法如下:

cv2.createTrackbar(Track_name, img, min, max, TrackbarCallback)

- Track_name:滑动条的名字。
- img:滑动条所在画布。
- min:滑动条的最小值。
- max:滑动条的最大值。
- TrackbarCallback:滑动条的回调函数。

​ cv2.getTrackbarPos 函数的语法如下:

cv2.getTrackbarPos(Track_name, img)

- Track_name:滑动条的名字。
- img:滑动条所在画布。
函数返回值是滑动条当前所在的位置。

​ 示例:滑动条控制的不只有R、G、B的值,还有一个使能端用于控制是否需要改变值。OpenCV中没有按钮,所以需要设置一个滑动条,它的值是0或1,当使能端值为1时,画布才会发生变化。

import cv2
import numpy as np


def nothing(x):
    # 回调函数
    pass


img = np.zeros((300, 512, 3), np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('R', 'image', 0, 255, nothing)
cv2.createTrackbar('G', 'image', 0, 255, nothing)
cv2.createTrackbar('B', 'image', 0, 255, nothing)
switch = '0:OFF\n1:ON'
cv2.createTrackbar(switch, 'image', 0, 1, nothing)
while (1):
    cv2.imshow('image', img)
    k = cv2.waitKey(1)
    if k == ord('q'):
        break
    r = cv2.getTrackbarPos('R', 'image')
    g = cv2.getTrackbarPos('G', 'image')
    b = cv2.getTrackbarPos('B', 'image')
    s = cv2.getTrackbarPos(switch, 'image')
    if s == 0:
        img[:] = 0
    else:
        img[:] = [b, g, r]
cv2.destroyAllWindows()

在这里插入图片描述

将最后一个滑动条的值滑到1值,就可以通过滑动上面的3个控制条来控制画布颜色在实时变化。

5.OpenCV的基础图像操作

主要内容:

​ 1.图像上某像素点的像素点的捕获。

​ 2.对图像进行简单的算术操作。

​ 3.图像逻辑运算。

​ 注意:图像的运算在获取图像掩膜后进行图像捕捉时几乎是必须要用到的。

5.1 图像的基础操作

5.1.1 获取像素值

更新中…

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

笨小古

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

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

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

打赏作者

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

抵扣说明:

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

余额充值