高雄市网站建设_网站建设公司_论坛网站_seo优化
2025/12/26 23:24:41 网站建设 项目流程

一、图像的加减乘除

  我们可以在终端中使用 pip 安装 OpenCV 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip 指令后通过 -i 指定国内镜像源下载

pip install opencv-python -i https://mirrors.aliyun.com/pypi/simple

  国内常用的 pip 下载源列表:

  • 阿里云 https://mirrors.aliyun.com/pypi/simple
  • 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple
  • 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple
  • 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple

  我们可以通过加号运算符 + 对图像进行加法运算,也可以通过 cv2.add() 函数对图像进行加法运算。

  通常情况下,在灰度图像中,一个像素值用 8 个比特位(一字节)来表示,其表示的范围是 0000 0000(8 个比特位都是 0,对应十进制 0,是 8 位二进制所能够表示的最小值)到 1111 1111(8 个比特位都是 1,对应十进制 255,是 8 位二进制所能够表示的最大值),对应像素值的范围是 [0,255]。两个像素值在进行加法运算时,求得的和很可能超过 255。

  使用加号运算符 + 对图像 a(像素值为 a)和图像 b(像素值为 b)进行求和运算时,遵循以下规则:

\[a + b = (a + b) \% 256 \]

import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)print("image1: \n", image1)print("image2: \n", image2)print("image1 + image2: \n", image1 + image2)

  我们还可以通过 cv2.add() 函数计算图像像素值相加的和。使用 cv2.add() 函数对像素值 a 和像素值 b 进行求和运算时,如果求得的和超过了当前图像像素值所能够表示的范围,则使用所能表示范围的最大值作为计算结果。该最大值,一般被称为图像的像素饱和值,所以函数 cv2.add() 的求和一般被称为饱和值求和(也被称为饱和求和、饱和运算、饱和求和运算等)。

cv2.add(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ..., dtype: int = ...) -> cv2.typing.MatLike: ...
import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)print("image1: \n", image1)print("image2: \n", image2)print("cv2.add(image1, image2): \n", cv2.add(image1, image2))

OpenCV 在相加两个图像时,要求两个图像的长宽相同,并且通道数也相同。

使用加号运算符 + 计算图像像素值的和时,将和大于 255 的值进行了取模处理,取模后大于 255 的这部分值变得更小了,导致本来应该更亮的像素点变得更暗了。

使用 cv2.add() 函数计算图像像素值的和时,将和大于 255 的值处理为饱和值 255。图像像素值相加后让图像的像素值增大了,图像整体变亮。

  同样,我们可以使用 cv2.subtract()cv2.multiply()cv2.divide() 方法进行减法、乘法和除法操作。

cv2.subtract(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ..., dtype: int = ...) -> cv2.typing.MatLike: ...
cv2.multiply(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., scale: float = ..., dtype: int = ...) -> cv2.typing.MatLike: ...
cv2.divide(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., scale: float = ..., dtype: int = ...) -> cv2.typing.MatLike: ...
import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)print("image1: \n", image1)print("image2: \n", image2)# 两个数相减,如果结果小于0,则按无符号数读取print("image1 - image2: \n", image1 - image2)# 两个数相减,如果结果小于0,则为0print("cv2.subtract(image1, image2): \n", cv2.subtract(image1, image2))
import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)print("image1: \n", image1)print("image2: \n", image2)# 两个数相乘法,如果结果大于255,则取余256print("image1 * image2: \n", image1 * image2)# 两个数相乘法,如果结果大于255,则按255处理print("cv2.multiply(image1, image2): \n", cv2.multiply(image1, image2))
import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 3), dtype=np.uint8)print("image1: \n", image1)print("image2: \n", image2)print("image1 / image2: \n", image1 / image2)print("image1 // image2: \n", image1 // image2)print("cv2.divide(image1, image2): \n", cv2.divide(image1, image2))

二、图像加权和

  所谓 图像加权和,就是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来,可以用公式表示为:

\[dst=saturate(src1×α+src2×β+γ) \]

  式中,saturate() 表示取饱和值(所能表示范围的最大值)。图像进行加权和计算时,要求 src1src2 必须大小、类型相同,但是对具体是什么类型和通道没有特殊限制。它们可以是任意数据类型,也可以有任意数量的通道(灰度图像或者彩色图像),只要二者相同即可。

  OpenCV中 提供了 cv2.addWeighted() 函数,用来实现图像的加权和(混合、融合),该函数的语法格式如下:

`cv2.addWeighted(src1: cv2.typing.MatLike, alpha: float, src2: cv2.typing.MatLike, beta: float, gamma: float, dst: cv2.typing.MatLike | None = ..., dtype: int = ...) -> cv2.typing.MatLike: ...

  其中,参数 alphabetasrc1src2 所对应的系数,它们的和可以等于 1,也可以不等于 1。该函数实现的功能是dst = saturate(src1 × alpha + src2 × beta + gamma)。需要注意,式中参数 gamma 的值可以是 0,但是该参数是必选参数,不能省略。可以将上式理解为 “结果图像 = 计算饱和值(图像 1 × 系数 1+ 图像 2× 系数 2+ 亮度调节量)”。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (3, 5), dtype=np.uint8)image2 = np.random.randint(0, 256, (3, 5), dtype=np.uint8)image3 = np.zeros((3, 5), dtype=np.uint8)print("image1 = \n", image1)print("image2 = \n", image2)gamma = 3image3 = cv2.addWeighted(image1, 2, image2, 1, gamma)print("image3 = \n", image3)

推荐 α 与 β 的取值范围为 [0, 1]。

三、按位逻辑运算

3.1、按位与运算

  按位与运算是指将数值转换为二进制值后,在对应的位上逐位进行与运算。在 与运算 中,当参加与运算的两个逻辑值都是真时,结果才为真。在 OpenCV 中,我们可以使用 cv2.bitwise_and() 函数来实现 按位与运算

cv2.bitwise_and(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ...) -> cv2.typing.MatLike: ...

  其中,src1 表示第一个 array 或 scalar 类型的输入值。src2 示第二个 array 或 scalar 类型的输入值。mask 表示可选操作掩码,8 位单通道 array。dst 表示与输入值具有同样大小的 array 输出值。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (5, 5), dtype=np.uint8)image2 = np.zeros((5, 5), dtype=np.uint8)image2[0:3, 0:3] = 255image2[4, 4] = 255image3 = cv2.bitwise_and(image1, image2)print("image1 = \n", image1)print("image2 = \n", image2)print("image3 = \n", image3)

任一像素值与白色像素值(数值 255,8 位二进制数是 1111 1111)进行按位与操作,结果是原像素值(数值 N)本身。

任一像素值与黑色像素值(数值 0)进行按位与操作,结果是黑色像素值(数值 0)。

3.2、按位或运算

  按位或运算是指将数值转换为二进制值后,在对应的位置上逐位进行或运算。或运算 的规则是,当参与或运算的两个逻辑值中有一个为真时,结果就为真。在 OpenCV 中,我们可以使用 cv2.bitwise_or() 函数来实现按位或运算。

cv2.bitwise_or(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ...) -> cv2.typing.MatLike: ...

  其中,src1 表示第一个 array 或 scalar 类型的输入值。src2 示第二个 array 或 scalar 类型的输入值。mask 表示可选操作掩码,8 位单通道 array。dst 表示与输入值具有同样大小的 array 输出值。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (5, 5), dtype=np.uint8)image2 = np.zeros((5, 5), dtype=np.uint8)image2[0:3, 0:3] = 255image2[4, 4] = 255image3 = cv2.bitwise_or(image1, image2)print("image1 = \n", image1)print("image2 = \n", image2)print("image3 = \n", image3)

任一像素值与白色像素值(数值 255,8 位二进制数是 1111 1111)进行按位或操作,结果是白色像素值(数值 255)。

任一像素值与黑色像素值(数值 0)进行按位或操作,结果是原像素值(数值 N)本身。

3.3、按位非运算

  按位非运算是指将数值转换为二进制值后,在对应的位置上逐位进行非运算。非运算是取反操作,满足如下逻辑:

  • 当运算数为真时,结果为假。
  • 当运算数为假时,结果为真。

  在OpenCV中,我们可以使用 cv2.bitwise_not() 来实现按位取反操作。

cv2.bitwise_not(src: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ...) -> cv2.typing.MatLike: ...

  其中,src 表示一个 array 或 scalar 类型的输入值mask 表示可选操作掩码,8 位单通道 array。dst 表示与输入值具有同样大小的 array 输出值。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (5, 5), dtype=np.uint8)image1[0:3, 0:3] = 255image1[4, 4] = 255image2 = cv2.bitwise_not(image1)print("image1 = \n", image1)print("image2 = \n", image2)

在 OpenCV 中,按位非运算的结果就相当于 255 减去这个数。

3.4、按位异或运算

  按位异或运算是指将数值转换为二进制值后,在对应的位置上逐位进行异或运算。异或运算 的规则是 相同为 0,不同为 1。异或运算也叫半加运算,其运算法则与不带进位的二进制加法类似,其英文为 “exclusive OR”,因此其函数通常表示为 xor。在 OpenCV 中,我们可以使用 cv2.bitwise_xor() 函数来实现按位异或运算。

cv2.bitwise_xor(src1: cv2.typing.MatLike, src2: cv2.typing.MatLike, dst: cv2.typing.MatLike | None = ..., mask: cv2.typing.MatLike | None = ...) -> cv2.typing.MatLike: ...

  其中,src1 表示第一个 array 或 scalar 类型的输入值。src2 示第二个 array 或 scalar 类型的输入值。mask 表示可选操作掩码,8 位单通道 array。dst 表示与输入值具有同样大小的 array 输出值。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.random.randint(0, 256, (5, 5), dtype=np.uint8)image2 = np.zeros((5, 5), dtype=np.uint8)image3 = np.full((5, 5), 255, dtype=np.uint8)image4 = cv2.bitwise_xor(image1, image2)image5 = cv2.bitwise_xor(image1, image3)print("image1 = \n", image1)print("image4 = \n", image4)print("image5 = \n", image5)

任一像素值与白色像素值(数值 255,8 位二进制数是 1111 1111)进行按位异或操作,结果是按位非的结果。

任一像素值与黑色像素值(数值 0)进行按位异或操作,结果是原像素值(数值 N)本身。

我们可以将图像 B 作为一个密钥图像,图像 A 与密钥图像执行按位异或运算后,可以的得出图像 A 加密后的图像 C。如果需要解密,我们可以将图像 C 与密钥图像执行一个按位异或操作,这样就可以得出原来的图像 A。

四、掩膜

  在 OpenCV 中,很多函数都会指定一个掩膜(也称为掩码、掩模)参数。当使用掩膜参数时,操作只会在掩膜值为非空的像素点上执行,并将其它像素点的值置为 0。

import cv2
import numpy as npif __name__ == '__main__':image1 = np.ones((4, 4), dtype=np.uint8) * 5image2 = np.ones((4, 4), dtype=np.uint8) * 7print("image1: \n", image1)print("image2: \n", image2)m = np.zeros((4, 4), dtype=np.uint8)m[2: 4, 2: 4] = 1print("m: \n", m)image3 = cv2.add(image1, image2, mask=m)print("image3: \n", image3)

掩膜值为非空(不是 0),即可以实现掩膜效果。

五、位平面分解

  将灰度图像中所有像素点的二进制值中处于同一比特位上的值提取出来,得到一副二值图像,该图像被称为灰度图像的一个 位平面,这个过程被称为 位平面分解。例如,将一副灰度图像内所有像素点上处于二进制位内最低位上的值进行组合,就可以构成 “最低有效位” 位平面。

  在 8 位灰度图中,每一个像素点使用 8 位二进制值来表示,其值的范围在 [0, 255] 之间,可以将其中的值表示为:

\[value = a_{7} * 2^{7} + a_{6} * 2^{6} + a_{5} * 2^{5} + a_{4} * 2^{4} + a_{3} * 2^{3} + a_{2} * 2^{2} + a_{1} * 2^{1} + a_{0} * 2^{0} \]

  其中,\(a_{i}\) 的可能值为 0 或 1。根据上述公式,我们可以看出,各个 \(a_{i}\) 的权重是不一样的,其中 \(a_{7}\) 的权重最高,\(a_{0}\) 的权重最低。这代表 \(a_{7}\) 对图像的影响最大,而 \(a_{0}\) 的值对图像的影响最小,即图像与 \(a_{7}\) 具有较大的相似性,而 \(a_{0}\) 通常与图像的相似性不高。

  由于图像与最低有效位的相似度不高 ,因此我们可以将需要隐藏的二值图像信息嵌入到图像的最低有效位,从而实现将二值图像隐藏的目的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询