OpenCV实战第二篇:用代码给照片做一场精细的“像素级整容”

发布时间:2026/11/6 3:23:11
OpenCV实战第二篇:用代码给照片做一场精细的“像素级整容”

本系列为超级适合新手入门的opencv教程

上一篇:OpenCV实战第一篇:计算机的眼里,你的自拍只是一堆破烂Mat数组

本篇内容:

  1. 访问与修改图片像素内容
  2. 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)
  1. 导入Numpy包
  2. 把b、g、r三个变量弄出来。
  3. 创造一个全0数组,这个全零数组的长宽和图片的长宽是一致的,shape的意思就拿出这个三通道图片的前两个数组,即长宽。
  4. 把zero当作参数放到里面,出来的也是一个三通道图片
    由这个方法弄出来的图片是三通道图片,和上面两个图片是不同的