目录:
3.1 numpy数组中一些矩阵知识理论回顾:
一维数组:[0, 0], 就算写多个[ ], [ ], [ ] 也还是一维数组,就算他们几个竖着写也还是一维,因为只有一对括号!
二维数组: [ [0, 0], [0, 0] ], 这种不管横着还是竖着都是二维
[[0 0]
[0 0]]
三维数组[2,2,2]:[ [ [0 0],[0 0] ] [ [0 0] [0 0] ] ]
同理推倒这个:[[[0 0] [0 0]]
所以最后肯定只有三维,就是最大多括号2,肯定只有2, 但是第二个2, 就有4个了, 第一个2, 就有8个了
3.2 RGB通道和数组的理解:
所以要是RGB一一对应的话,那么就是行,就是列,第三维就意味着有三个通道,RGB,所以第三个一般都为3,就是整个RGB的通道数目。
重点~~!!!!三个大通道:那么第三维的取值就只能是0, 1, 2. 那么012分别代表着RGB中的某个通道。然后剩下二维就是对应多R G B中数组取值!!
[
[ []
]
] 这就代表了一个通道!!,三个通道,分别代表了RGB。所以
所以:(?,?,0)= R; (?,?,1)= G; (?,?,2)= B
但是因为Opencv 默认通道是BGR 所以调换一下顺序就行。
比如纯蓝色:R0 G0 B255 , 所以(255, 255, 0)(0,0,1)(0,0,2)
1. 创建方法可以直接创建一个全零 img = np.zeros([400,400,3], int)
2. 然后再修改通道: img[:, :, 0] = np.ones([400, 400])*255
3.3 图像通过数组创建,修改,灰度图的创建:
最笨的方式:m = np.array([]) # 一个一个写。 一般自定义filter的时候再用到
通过全零或者全一来创建:np.zeros([?, ?], type), np.ones([?, ?], type)。 img = np.zeros([400,400,3], np.uint8)
通过 ones 初始化图像操作性更好,因为可以 image * 0 = 黑色,image * 255 = 白色,但是 zeros 的话就比较难,因为它是0!
修改图像(只能特定修改某个通道):
img[:, :, 0] = np.ones([?, ?]) * ? 这只是单独修改0通道(理论上是R通道,但是opencv里面是B通道)
已知某图大小,想创造一个一样大的新图:
3.4 获取图像的RGB值并输出
当然我们知道可以直接 image.shape, image.width, image.height, image.channels
我们还可以通过单个储存然后输出:
height = image.shape[0]
width = image.shape[1]
channels = image.shape[2]
下面是通过数组数据来输出一个图像。
for row in range(height):
for col in range(width):
for c in range(channels):
pv = image[row, col, c]
image[row, col, c] = 255-pv
cv.imshow(“ ”, image)
注意上面直接输出pv也是可以的,但是会镜像反过来,所以我们通过255-pv的操作来将镜头反过来。
这里还有一个大问题:时间浪费
可见上面的方法是将图像反过来,通过python语句执行,需要7秒左右,这里有一个更好更快的方法,就是opencv自带的API,只需要20ms左右,因为python是解释型语言,opencv的API都是C来写的,执行起来快!
def inverse(image):
dat = cv.bitwise_not(image)
cv.imshow("inverse demo", dat)
3.5 计算时间消耗和waitKey():
cv.getTickCount() 获得当前滴答数
滴答数之差 不能代表 时间差
要知道滴答频率,比如 1秒滴答10次。cv.getTickFrequency()
比如滴答差1000次,1秒10,那就是1000/10=100s
所以公式是:cv.getTickCount()(差值!) / cv.getTickFrequency()
waitKey()函数:
这个函数后面应该是cv::waitKey函数,它显示指定的图像。毫秒。否则,它就不会显示图像。例如,waitKey(0)将无限地显示窗口,直到任何按键按下(它适合于图像显示)。waitKey(25)将显示一个框架。25毫秒后,显示将自动关闭。(如果你把它放到一个循环中去读。视频,它将显示视频帧逐帧。
1.waitKey()与waitKey(0),都代表无限等待,waitKey函数的默认参数就是int delay = 0,故这俩形式本质是一样的。
2.waitKey(n),等待n毫秒后,关闭显示的窗口。
3.6 重构图像 reshape 和注意参数类型
m2 =m1.reshape(1,9)
print(m2) 通过这个respae方法可以强行降维或者改变图像
参数类型不注意的话会引起:精度丢失或者高位低位截断,比如你定义的uint8, 但是给了一个12222 很大的数,他到不了,就会高为截断。比如整数,小数同理。
总共有78万多个像素点。处理完这些像素点需要7秒多。
通过numpy我们可以操作:
通过下面遮盖方法我们可以很快速的创建一个图,最简单的就是一个黑色图。
图像的RGB对应数组来理解:
比如一个 image.shape() = [287, 496, 3],其中287表示列,496表示行,3表示分量
首先我们应该按 列 来看,可以看到有3列 (即190 48 64对应往下的3列),这便是RGB对应的 3 个通道,从头到尾的一列数据构成了一个通道分量,共三个:
这里就是一个现象:不管多少维度,在程序里面最高纬度输出来的列表中,最高维N维就代表着有多少列。然后才是从低维向高维度数。比如:(2,3),那就是[ [1, 1 ,1], [1, 1, 1] ], 所以最高纬度3, 肯定是三列,再从最低维2, 看有几个第二大括号就是几。
也可以这么看,(a,b,c,d)四维度,[[[][][][]]] , 抽丝剥茧,最外面一个括号是默认套上去多,所以有几对[] 就是a的值, 然后又往下一层,有几对[](小于a的括号,也就是在a括号里面最大多括号)就是b,所以很自然到了最后一个d,就没有了括号,就是最小括号里面数字个数,那么就是列!!
然后再来理解287,从上图中可以看到有很多的 [ 符号,其实按层次来分也就三层,这里的287表示共有287个中间层的矩阵:
最后再来看496,这个数字从哪来?上面的287个矩阵中每一个矩阵的每一列都有496个元素(数字),虽然这些数字是按照行来分块,但实际上列之间的元素才有关联,每一列的元素组合成行,构成了该通道矩阵的一行数据:
下面来看看将上面的整体矩阵分解为三个通道后的模样,做个对比是不是清楚很多了。
上面的三个通道为相同的矩阵大小,而后将三者按照通道顺序排列重叠后构成了RGB彩色图片,当然顺序有可能不是RBG,例如opencv转换后为BGR。
灰度图就是一个但通道图!!!!
# 尝试多通道一起操作,要一起操作就意味着只有一个通道,那么就是灰度图
img = np.zeros([400, 400, 1], np.uint8)
img[:, :, 0] = np.ones([400, 400]) * 127
cv.imshow("new image", img)
这里就发生了截断。参数类型的选择很重要。
3.7 视频的读入和操作
视频输入读取:
capture = cv.VideoCapture(“ ”)
ret, frame = capture.read()
第一个参数ret 为True 或者False,代表有没有读取到图片, ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。
第二个参数frame表示截取到一帧的图片,frame就是每一帧的图像,是个三维矩阵.