Python OpenCV 上手

为了从dan哥获取答案,在答题卡中找到答案的位置,所以有了本篇openCV的学习笔记。记录遇到的坑和解决方法。

前置

目前openCV已经到了2.0版本,据说语法简单了很多,所以我们就用这个版本。

import cv2


因为图片是由一个个像素点组成,而像素点又是rgb值来表示,所以图片在python中就是一堆rgb值。
恰好Numpy可以很好的处理这堆像素点,所以还要

import numpy as np

打开图像

打开图片一句话搞定:

1
img = cv2.imread(r'img\\img.png')

显示图像需要几个步骤▼

1
2
3
4
5
def display_im(img): 
cv2.namedWindow("Image", cv2.WINDOW_NORMAL) # 创建图像窗口,默认cv2.WINDOW_AUTOSIZE,不可调窗口大小。cv2.WINDOW_NORMAL可调节大小。
cv2.imshow("Image", img) # 显示指定图像
cv2.waitKey (0) # 暂停并等待键盘输入;0表示你不输入它就一直等。不等的话图片一闪就过去了,啥都看不到)
cv2.destroyAllWindows() # #释放窗口,简单暴力释放掉所有的窗口

查看图像大小

一句话~

1
print(img.shape[:2])

输出结果是(38, 80),记好了一会还会提到这个数。

保存图像

同样是一句话搞定

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

处理图像(基础版)

python中的图像

比如这张简单的图像

用cv2打开,然后直接打印出来▼

1
2
img = cv2.imread(r'img.png')
print(img)

结果是这样的一坨数组,为了方便观察,我这里手动转换一下。

  • 数据量比较大,只显示了首尾的内容
  • 图片四角都是白色的,所以这里只能看到255
  • 通过np.set_printoptions(threshold=np.inf)可以打印所有值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[[[255 255 255]
[255 255 255]
[255 255 255]
...,
[255 255 255]
[255 255 255]
[255 255 255]]

[[255 255 255]
[255 255 255]
[255 255 255]
...,
[255 255 255]
[255 255 255]
[255 255 255]]

这样看起来好多了▼

1
2
3
4
5
6
7
[
[[255 255 255] [255 255 255] [255 255 255] ..., [255 255 255] [255 255 255] [255 255 255]]
[[255 255 255] [255 255 255] [255 255 255] ..., [255 255 255] [255 255 255] [255 255 255]]
...,
[[255 255 255] [255 255 255] [255 255 255] ..., [255 255 255] [255 255 255] [255 255 255]]
[[255 255 255] [255 255 255] [255 255 255] ..., [255 255 255] [255 255 255] [255 255 255]]
]

让洒家来简单分析一下这个数组吧▼

1
2
3
4
print(len(img)) #告诉洒家你这个数组一共有几行?
print(len(img[0])) # 第一行有几列?
print(len(img[0][0])) # 第一列有几个元素?
print(len(img[0][0][0]))# 第一个元素里有几个东西?

结果如下▼

1
2
3
4
5
38
80
3
---------------------------------------------------------------------------
TypeError

数组有38行80列,眼不眼熟?和上面的(38, 80)对上了!所以▼

  • 3是什么?是[255 255 255],熟悉RGB的都知道是红绿蓝3种颜色的值。然而CV里是BGR,不要搞混哟。图片是由一行一行的彩色像素点组成的,所以我们可以用一个三维数组来表示图片中的每一个点。
  • 最里面的数组[255 255 255]是一个BGR表示的像素点颜色
  • 一行[[255 255 255] ..., [255 255 255]]就表示图片的一行像素点,一行有80个这样的点
  • 所有行放在一起一共38行,就是一副完整的图片了。这也是为什么我们可以用numpy来处理图片了。
    最后的TypeError是什么鬼?
  • 图片的最小单位就是像素里的三个颜色。颜色是个数值而不是数组,对数值用len()就报错了。

转换成灰度图像

灰度图像有助提升复杂操作的速度哦~
还是一句话:

1
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

来看一下结果,红字变成灰字了。

1
2
3
4
5
6
7
[[255 255 255 ..., 255 255 255]
[255 255 255 ..., 255 255 255]
[255 255 255 ..., 255 255 255]
...,
[255 255 255 ..., 255 255 255]
[255 255 255 ..., 255 255 255]
[255 255 255 ..., 255 255 255]]

  • 可以看到由3维数组变成了2位数组(啊,受到了降维攻击!)。
  • 这是因为灰度图像的像素点只有一种颜色,用0到255的值就能表示了。
  • uint8(无符号整形变量)的范围正好是0-255,所以numpy处理图像通常都用这个格式。
  • 这里打印依然是图像的四个角,所以还是255.。。。

截取图像

借助python的切片器可以很优雅的截取像素,洒家截一块不是纯白的给你们看看▼

1
img_cut = img[10:30, 30:40]  # 截取high,width

截取第11到29行,30到40列。总算有些不一样值出现了▼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[[255 255 255 255 255 250 234 255 255 255]
[255 255 255 255 255 184 128 223 255 255]
[255 255 255 255 255 239 147 128 231 255]
[255 255 255 255 255 255 243 144 223 255]
[255 255 255 255 255 255 255 250 255 250]
[255 255 255 255 255 255 255 255 255 250]
[255 255 255 255 252 221 221 221 240 213]
[255 255 255 255 246 120 120 120 205 200]
[255 255 255 255 255 252 252 126 205 255]
[255 255 255 255 255 255 255 126 205 255]
[255 255 255 255 255 255 255 126 205 255]
[255 255 255 255 255 255 255 126 205 255]
[255 255 255 255 255 255 255 126 205 208]
[255 255 255 255 255 255 253 125 186 242]
[255 255 255 255 252 200 140 174 166 128]
[255 255 255 255 255 172 179 254 255 226]
[255 255 255 255 255 248 254 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255 255 255]]

处理图像(高级版)

给你们来点高级货~

搜索图像

先上代码▼

1
res = cv2.matchTemplate(target, img, cv2.TM_CCOEFF_NORMED)

意思就是从target图片中找到img图片,找到后给出一个。。。。
偶,时间不早了,下次接着写吧~

-------------本文结束,感谢您的阅读。如有疑问请及时提出-------------