OpenCV实战第二篇:用代码给照片做一场精细的“像素级整容”
本系列为超级适合新手入门的opencv教程
上一篇:OpenCV实战第一篇:计算机的眼里,你的自拍只是一堆破烂Mat数组
本篇内容:
- 访问与修改图片像素内容
- ROI(感兴趣)区域
目录
- 本系列为超级适合新手入门的opencv教程
- 本篇内容:
- 1.获得图片的大小与类型
- 函数(实际上是属性,不过我们可以当作函数使用他们)语法
- 翻译代码
- 函数讲解
- 函数的结果
- 如何修改图片的内容呢?
- 3.ROI感兴趣区域
- 4. 图像通道的分割
- 4.1.split函数
- 函数语法
- 翻译代码
- 函数讲解
- 函数举例
- 函数结果
- merge函数
- 函数语法
- 翻译代码
- 函数讲解
- 函数结果
- 4.2 直接分离(使用数组)
- **原理**
- 4.3进阶方法:numpy
- 原理:
在上一篇我们知道,每一个图片在opencv程序之中是以一个mat数组或者ndarray数组进行存储的,所以我们可以以操作每一个像素的方法,以一个极其细致的方法对这个图片进行操作
首先,我们先读取一个图片
importcv2#导入opencvtore_path="./resources/image/tore.png"#读取图片的路径tore=cv2.imread(tore_path)#获取图片数组1.获得图片的大小与类型
print(tore.shape)#获得图片的大小和类型函数(实际上是属性,不过我们可以当作函数使用他们)语法
defshape(self)->tuple[int,...]翻译代码
函数 shape(自身)->元组[整形]函数讲解
在源代码之中,对shape函数的描述如下:Anything that can be coerced to a shape tuple,翻译出来就是任何可被强制转换为形状元组的对象。那么在这里,这个可以被转换成形状元组的对象就是一张图片。
那么什么是形状元组呢?
形状元组分为两种,一种是对于拥有三通道图片的,另一种是对于灰度图的。第一种为:(高,宽,通道数),第二种为:(高,宽),这样我们就能获得这个图片的大小和类型。
函数的结果
(1000,1000,3)如何修改图片的内容呢?
我们使用的是类似于直接修改图片数组里面的元素的方法。
tore[100,100]=[255,255,255]我们可以把图片的左上角看作原点,这个坐标就是以这样的方法来设定坐标的。
我们把[100,100]这个地方的像素变成白色。虽然可能有些看不太清楚,但是在这个部分能看到一个白色的小点
我们还有别的需求,如果我们需要一条白线呢?
tore[100:120]=[255,255,255]我们把纵坐标的100到120这一段设定为白色,而不设定横坐标,那么就会默认是把所有满足这一点的变成白色。
那么大家可以去试试,如果把再把横坐标设定为100:200,我们该怎么做呢?
3.ROI感兴趣区域
什么是感兴趣区域?就是在这个图像之中我们需要重点关注的区域。
tore_interest=tore.copy()# 复制一个这样的图片tore_interest_set=tore[250:850,250:850]# 提取这个图片的一个部分,可以看作是切割这个图像4. 图像通道的分割
对于分离图片的颜色通道,我们有很多种办法
4.1.split函数
函数语法
defsplit(m:Mat|ndarray[Any,dtype]|ndarray,mv:Sequence[Mat|ndarray[Any,dtype]|ndarray]|None=...)->Sequence[Mat|ndarray[Any,dtype]|ndarray]翻译代码
函数 split(输入矩阵:Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组, 输出向量序列:序列[Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组] [或] None空值 = ...) -> 输出:序列[Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组]函数讲解
在这里,我们以三个变量作为蓝色、 绿色、红色三个通道,但注意,这里输出的是一个灰度图,所以我们不能输出一个彩色的图片。
函数举例
tore_color=tore.copy()b,g,r=cv2.split(tore_color)# 分离通道merged=cv2.merge((b,g,r))# 合并通道函数结果
这是函数的结果(b)
merge函数
函数语法
defmerge(mv:Sequence[Mat|ndarray[Any,dtype]|ndarray],dst:Mat|ndarray[Any,dtype]|ndarray|None=...)->Mat|ndarray[Any,dtype]|ndarray翻译代码
函数 merge(输入矩阵序列:序列[Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组], 输出矩阵:Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组 [或] None空值 = ...) -> 输出:Mat数组 [或] ndarray数组[任意类型, 每个元素的数据类型[泛型]] [或] ndarray数组函数讲解
这个函数的作用是合并图像通道,它的参数就是我们使用上一个函数分离出来的图像通道。我们能够把三个通道合并起来,或者把一个通道合并三次
我们当然也可以两个两个的合并,不过这个函数必须输入三个参数(或者说三个参数的意义最大,我们可以使用单参数和四参数,不过用的不多,故而我在此写三个参数),所以我们可以创建一个相同大小的ndarry数组,但在这里我就跳过了如何创建ndarray数组,直接给大家进行使用,由此这个函数有多种合并方式。但注意。注意,每个元素出现的次数,所在的位置的不同所得到的东西都完全不一致。
举例:merged = cv2.merge((b,g,g))merged = cv2.merge((g,g,b))merged = cv2.merge((b,b,g))merged = cv2.merge((b,g,r))
这三个产出的图片效果都完全不一样,懂了吗?懂了的自刎归天(刘备音)!还有一个好玩的,就是你可以直接的展示b,也可以把三个b合并在一起这个样子,如果这个做的话两张图片在肉眼看起来是完全一致的,就是一张灰度图。
函数结果
bgr
bbr
4.2 直接分离(使用数组)
原理
我们可以把图片的相关数据看作一个元组,这个元组就是上面写过的形状数组,故而:
tore_color_blue=tore_color[:,:,1]最后的那个数字可以是0,1,2。代表着bgl三色。
4.3进阶方法:numpy
原理:
opencv和numpy的关联很多,我们可以把这个看作是一个numpy数组。
importnumpyasnpimportcv2 b,g,r=cv2.split(tore_color)zero=np.zeros(tore.shape[:2],dtype=np.uint8)tore_color_blue=cv2.merge([b,zero,zero])cv2.imshow('tore',tore_color_blue)- 导入Numpy包
- 把b、g、r三个变量弄出来。
- 创造一个全0数组,这个全零数组的长宽和图片的长宽是一致的,shape的意思就拿出这个三通道图片的前两个数组,即长宽。
- 把zero当作参数放到里面,出来的也是一个三通道图片
由这个方法弄出来的图片是三通道图片,和上面两个图片是不同的