OpenCV(Python)学习日记1-图像运算

摘要

  • 加法运算
  • 加权和
  • 按位逻辑运算
  • 掩模
  • 位平面分解
  • 加密和解密
  • 数字水印

1 加法运算

在图像处理过程中,需要对图片进行加法运算。可以通过运算符+进行加法运算,也可以通过cv2.add()函数进行加法运算。我们以灰度图为例,假设图1中的某一像素值为a,图2中的某一像素值为b。

1.1 运算符+

因为灰度图中的数据类型为uint8,运算符+的运算规则如下:

a + b = { a + b , a + b < 256 m o d ( a + b ) , a + b > 255 a+b=\begin{cases} a+b, & a+b<256\\ mod(a+b), & a+b>255 \end{cases} a+b={a+b,mod(a+b),a+b<256a+b>255

1.2 cv2.add()函数

cv2.add()函数的运算规则如下:
a + b = { a + b , a + b < 256 255 , a + b > 255 a+b=\begin{cases} a+b, & a+b<256\\ 255, & a+b>255 \end{cases} a+b={a+b,255,a+b<256a+b>255
我们举一个例子比较运算符+和cv2.add()函数的差别

import cv2
import numpy as np

def add_operator():
    image1 = np.ones((4, 4), dtype=np.uint8) * 250
    image2 = np.ones((4, 4), dtype=np.uint8)
    image3 = np.ones((4, 4), dtype=np.uint8) * 10
    image4 = image1 + image2
    image5 = image1 + image3
    image6 = cv2.add(image1, image2)
    image7 = cv2.add(image1, image3)

    print("+ operator: \n", image4)
    print("+ operator: \n", image5)
    print("cv2.add function: \n", image6)
    print("cv2.add function: \n", image7)

    cv2.waitKey(0)

add_operator()

运算结果如下,可以发现:使用+,若两像素点值和超过255会有一个取余的操作,而使用cv2.add()函数,当两点像素点值和超过255时,取255位运算结果。
OpenCV(Python)学习日记1-图像运算_第1张图片

2 加权和

当两图不是简单相加,而是按一定权重相加时,可调用cv2.addWeighted()函数

addWeighted(src1, alpha, src2, beta, gamma, dst=..., dtype=...)
src1:图1
alpha: 图1的权重
src2:图2
beta:图2的权重
gamma:亮度调节量

计算公式为:
d s t = s r c 1 ∗ a l p h a + s r c 2 ∗ b e t a + g a m m a dst=src1*alpha+src2*beta+gamma dst=src1alpha+src2beta+gamma
举一个例子,将图1帆高和图2阳菜合融合在一起

def weight_add():
    fg_img = cv2.imread("fg.jpg")
    yc_img = cv2.imread("yc.jpg")
    fg_img = cv2.resize(fg_img, dsize=(yc_img.shape[1], yc_img.shape[0]))
    cv2.imshow("fg_img", fg_img)
    cv2.imshow("yc_img", yc_img)
    img = cv2.addWeighted(fg_img, 0.5, yc_img, 1, 1)
    
    cv2.imshow("yc&fg", img)
    cv2.waitKey(0)

weight_add()    

运行结果为:
OpenCV(Python)学习日记1-图像运算_第2张图片

3 按位逻辑运算

图片之间的按位逻辑运算有按位与按位或按位非按位异或等,逻辑运算规则如下:

算子1 算子2 非(算子1) 异或
0 0 0 0 1 0
0 1 0 1 1 1
1 0 0 1 0 1
1 1 1 1 0 0

OpenCV库中有对应的库函数:

  • 按位与:cv2.bitwise_and()
  • 按位或:cv2.bitwise_or()
  • 按位非:cv2.bitwise_not()
  • 按位异或:cv2.bitwise_xor()
    下面我们举一个例子,随机生成一个4*4的灰度图,分别与0矩阵进行按位与,或,非,异或操作
def logic_operation():
    image1 = np.random.randint(0, 256, size=(4, 4), dtype=np.uint8)
    image2 = np.zeros((4, 4), dtype=np.uint8)
    print("image1: \n", image1)
    #1 按位与
    print("and: \n", cv2.bitwise_and(image1, image2))
    #2 按位或
    print("or: \n", cv2.bitwise_or(image1, image2))
    #3 按位非
    print("not: \n", cv2.bitwise_not(image1))
    #4 按位异或
    print("xor: \n", cv2.bitwise_xor(image1, image2))
logic_operation()

运算结果为
OpenCV(Python)学习日记1-图像运算_第3张图片
我们对image第0行第0列元素(21)进行分析:
21的二进制表示为:0001 0101
00的二进制表示为:0000 0000
与:0000 0000,十进制为0
或:0001 0101,十进制为21
非:1110 1010,十进制为234
异或: 0001 0101,十进制为21

4 掩模

掩模是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。掩模中为0的部分表示遮挡的部分,掩模中为1的部分表示感兴趣或需要处理的部分。
以cv2.add()函数举例子

def mask_op():
    image1 = np.ones((3, 3), dtype=np.uint8) * 3
    image2 = np.ones((3, 3), dtype=np.uint8) * 7
    mask1 = np.zeros((3, 3), dtype=np.uint8)
    mask1[2][2] = 1
    image3 = cv2.add(image1, image2, mask=mask1)
    print("image3: \n", image3)
mask_op()

程序运行结果为
OpenCV(Python)学习日记1-图像运算_第4张图片

5 位平面分解

图片的数据类型为uint8(8位无符整型),将图片矩阵中相同的位组合,得到位平面,一张图片有八个位平面。可通过按位与的方法把位平面提出出来
举一个例子,将阳菜图片的位平面提取并显示出来

def bit_plane(): 
    image = cv2.imread("yc.jpg")
    bit0 = np.ones(image.shape, dtype=np.uint8)
    bit1 = bit0 * 2
    bit2 = bit1 * 2
    bit3 = bit2 * 2
    bit4 = bit3 * 2
    bit5 = bit4 * 2
    bit6 = bit5 * 2
    bit7 = bit6 * 2
    bit0_image = cv2.bitwise_and(image, bit0)
    bit1_image = cv2.bitwise_and(image, bit1)
    bit2_image = cv2.bitwise_and(image, bit2)
    bit3_image = cv2.bitwise_and(image, bit3)
    bit4_image = cv2.bitwise_and(image, bit4)
    bit5_image = cv2.bitwise_and(image, bit5)
    bit6_image = cv2.bitwise_and(image, bit6)
    bit7_image = cv2.bitwise_and(image, bit7)
    cv2.imshow("bit0", bit0_image)
    cv2.imshow("bit1", bit1_image)
    cv2.imshow("bit2", bit2_image)
    cv2.imshow("bit3", bit3_image)
    cv2.imshow("bit4", bit4_image)
    cv2.imshow("bit5", bit5_image)
    cv2.imshow("bit6", bit6_image)
    cv2.imshow("bit7", bit7_image)
    cv2.waitKey(0)

bit_plane()

程序运行结果为
OpenCV(Python)学习日记1-图像运算_第5张图片

6 加密和解密

a与b进行两次异或运算结果还是等于a,利用这一性质可对图像进行加密和解密,原图像与密钥矩阵进行一次异或运算得到加密图像(加密),加密图像与密钥再进行一次异或运算得到原图像(解密)。
举个例子,用帆高给阳菜加密

def En_decryption():
    fg_image = cv2.imread("fg.jpg")
    yc_image = cv2.imread("yc.jpg")
    fg_image = cv2.resize(fg_image, dsize=(yc_image.shape[1], yc_image.shape[0]))

    encryption = cv2.bitwise_xor(yc_image, fg_image)
    decryption = cv2.bitwise_xor(encryption, fg_image)

    cv2.imshow("encryption", encryption)
    cv2.imshow("decryption", decryption)
    cv2.waitKey(0)

En_decryption()

运算结果为
OpenCV(Python)学习日记1-图像运算_第6张图片

7 数字水印

由5可以找到一张图片可以分解为8个位平面,而位平面0对于整个图片的影响权重是最小的,因此,我们可以用位平面7到位平面1来保存图片信息,而位平面0用来储存其他数据,例如数字水印。
例如,随机生成一个数字水印,并把他嵌入图片中

def Water_Mark():
    image = cv2.imread("yc.jpg", 0)
    #1 将图片的所有像素的二进制表示的第0位置0
    image = cv2.bitwise_and(image, 254)
    cv2.imshow("yc", image)
    #2 随机生成一个数字水印,并把他嵌入图片中
    wm = np.random.randint(0, 2, size=image.shape, dtype=np.uint8)
    image = cv2.bitwise_or(image, wm)
    cv2.imshow("yc&wm", image)
    #3 数字水印的提取,即提取位平面0
    wm_ = cv2.bitwise_and(image, 1)
    print("提取出的数字水印:\n", wm_)
    print("数字水印为:\n", wm)

    cv2.waitKey(0)

Water_Mark()

程序运行的结果为
OpenCV(Python)学习日记1-图像运算_第7张图片
OpenCV(Python)学习日记1-图像运算_第8张图片

你可能感兴趣的:(OpenCV(Python)学习日记1-图像运算)