OpenCV-python学习笔记(三)——图像运算

三、图像运算

1、图像加法运算

3.1.1 加法运算符

对图像a(像素值为a)和图像b(像素值为)进行求和运算

a + b = a + b , a + b < = 255 a+b=a+b , a+b<=255 a+b=a+b,a+b<=255

$a+b=mod(a+b,256), a+b>255 $

mod(a+b,256) “表示计算a+b的和除以256取余数”

3.1.2 cv2.add()函数

计算结果 = cv2.add(像素值a,像素值b)

a + b = a + b , a + b < = 255 a+b=a+b,a+b<=255 a+b=a+b,a+b<=255

a + b = 255 , a + b > 255 a+b=255,a+b>255 a+b=255,a+b>255

**形式1:**计算结果=cv2.add(图像1,图像2),两个参数都是图像,此时参与运算的图像大小和类型必须保持一致。

形式2∶计算结果=cv2.add(数值,图像),第1个参数是数值,第2个参数是图像,此时将超过图像饱和值的数值处理为饱和值(最大值)。

形式3∶计算结果=cv2.add(图像,数值),第1个参数是图像,第2个参数是数值,此时将超过图像饱和值的数值处理为饱和值(最大值)。

示例:用加法运算符和cv2.add()函数计算两幅灰度图像的像素值之和

import cv2
a=cv2.imread ("lena.png",0)
b=a
result1=a+b
result2=cv2.add (a,b)
cv2.imshow ("original",a)
cv2.imshow ("result1",result1)
cv2.imshow ("result2",result2)
cv2.waitKey ()
cv2.destroyAllWindows ()

结果:

在这里插入图片描述

2、图像加权和

dst=cv2.addWeighted (src1,alpha,src2,beta,gamma)

参数alpha和beta是src1和src2所对应的系数

dst=src1×alpha+src2×beta+gamma

其中gamma不能省略,表示亮度调节量

3、按位逻辑运算

常见位运算函数:

函数名 基本含义
cv2.bitwise_and() 按位与
cv2.bitwise_or() 按位或
cv2.bitwise_xor() 按位异或
cv2.bitwise_not() 按位取反

3.3.1 按位与运算

dst=cv2.bitwise_and (src1,src2[,mask]])

**src1、src2:**为输入图像或标量,标量可以为单个数值或一个四元组
**mask:**图像掩膜,可选参数,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0
构造掩模图像M,值只有0和255,与灰度图像进行按位与操作,与掩模图像255对应的数值来源灰度图像,与0对应的值为0

示例:构造掩模图像,只保留lena的头部

import cv2
import numpy as np
a=cv2.imread ("lena.png",0)
b=np.zeros (a.shape,dtype=np.uint8)
b[100:400,200:400]=255
b[100:500,100:200]=255
c=cv2.bitwise_and (a,b)
cv2.imshow ("a",a)
cv2.imshow ("b",b)
cv2.imshow ("c",c)
cv2.waitKey()
cv2.destroyAllWindows()

结果:
在这里插入图片描述

3.3.2 按位或运算

dst=cv2.bitwise_or (src1,src2[,mask]])

3.3.3 按位非运算

dst=cv2.bitwise_not (src[,mask]])

3.3.4 按位异或运算

相同为0,不同为1

dst=cv2.bitwise_xor (src1,src2[,mask]])

四、掩模

计算结果=cv2.add(参数1,参数2,掩模)

当使用掩模参数时,操作只会在掩模值为非空的像素点上执行,并将其他像素点的值置为0。

我们通过将掩模图像转换为BGR模式的彩色图像,让彩色图像与(彩色)掩模图像进行按位与操作,从而实现掩模运算。

使用掩模图像作为掩模参数,完成按位与运算,即可得到由掩模控制的彩色图像。

五、图像与数值的运算

参与运算的两个算子既可以是两幅图像,也可以是一幅图像与一个数值。

例如,如果想要增加图像的整体亮度,可以将每一个像素值加上一个特定值。

六、位平面分解

定义:将灰度图像中处于同一比特位上的二进制像素值进行组合,得到一幅二进制值图像,该图像被称为灰度图像的一个位平面,这个过

程被称为位平面分解

每一个像素用8位二进制表示为:value=a7×27+a6×26+a5×25+a4×24+a3×23+a2×22+a1×21+a0×20

a7权重最高,其值对图像影响最大

平面分解的具体步骤:

(1)图像预处理

读取原始图像O,获取原始图像O的宽度M和高度N

(2)构造提取矩阵

使用按位与操作提取指定位置上的数字

构造值为 2 n 2^n 2n的mat作为提取矩阵(数组),与原始图像进行按位与运算,提取第n个位平面

(3)提取位平面

将灰度图像与提取矩阵进行按位与运算,得到各个位平面

(4)阈值处理

通过计算得到的位平面是一个二值图像,要想让二值位平面能够以黑白颜色显示出来,要将得到的二值位平面进行阈值处理,大于0的值处理为255

mask=RD[:,:,i]>0
RD[mask]=255

(5)显示图像

示例:观察灰度图的各个位平面

import cv2
import numpy as np
lena=cv2 .imread("lena.png",0)
cv2.imshow("lena",lena)
r,c=lena.shape
x=np.zeros((r,c,8), dtype=np.uint8)		#该矩阵是r行高,c列宽,8通道的矩阵,用来提取灰度图像的8个位平面
for i in range(8):
	x[ :,:,i]=2**i		#2的i次方,提取各个位平面的提取矩阵的值
r=np.zeros((r,c,8),dtype=np.uint8)		#该矩阵是r行高,c列宽,8通道的矩阵,用来提取灰度图像的8个位平面
for i in range(8):
	r[:, :,i]=cv2.bitwise_and (lena,x[:,:,i])	#位平面提取
	mask=r[:, :,i]>0
	r[mask]=255			#阈值处理
	cv2 .imshow (str(i),r[:,:,i])	#显示
cv2.waitKey()
cv2.destroyAllWindows()

七、图像加密和解密

通过按位异或可以实现图像的加密和解密

按位异或运算的过程示例

a b c=(xor(a,b)) xor(c,b)=a xor(c,a)=b
0 0 0 0 0
0 1 1 0 1
1 0 1 1 0
1 1 0 1 1

所以有:

a:明文,原始数据

b:密匙

c:密文,通过xor(a,b)实现

(1)加密过程: 将明文a与密钥b进行按位异或,完成加密,得到密文c。
(2)解密过程: 将密文c与密钥b进行按位异或,完成解密,得到明文a。

示例:

import cv2
import numpy as np
lena=cv2.imread("lena.png",0)	#明文(原始图像)
r,c=lena.shape
key=np.random.randint (0,256,size=[r,c],dtype=np.uint8)		#密匙图像,由随机数生成
encryption=cv2.bitwise_xor(lena,key)						#加密图像,明文与密匙按位异或生成
decryption=cv2.bitwise_xor (encryption,key)
cv2.imshow ("lena",lena)		#解密图像
cv2.imshow("key",key)
cv2.imshow("encryption",encryption)
cv2.imshow("decryption",decryption)
cv2.waitKey()
cv2.destroyAllWindows()

八、数字水印

**最低有效位(Least Significant Bit,LSB):**指的是一个二进制数中的第0位(即最低位)

**数字水印:**最低有效位信息隐藏指的是,将一个需要隐藏的二值图像信息嵌入载体图像的最低有效位,即将载体图像的最低有效位

层替换为当前需要隐藏的二值图像,从而实现将二值图像隐藏的目的。由于二值图像处于载体图像的最低有效位上,所以对于载体图像

的影响非常不明显,具有极高的隐蔽性,这种信息隐藏叫做数字水印

3.8.1 原理

3.8.1.1 嵌入过程

**嵌入过程:**将载体图像的第0个位平面替换为数字水印信息(一幅二值图像)。

嵌入过程步骤:以原始图像为灰度图像,水印图像为二值图像

(1)原始载体图像预处理

提取图像的第0个位平面

(2)水印图像处理

将灰度二值水印信息进行阈值处理,转为二进制二值水印信息

(3)嵌入水印

将载体图像的最低有效位替换为二进制水印图像,完成水印的嵌入

3.8.1.2 提取过程

**提取过程: **将载体图像的最低有效位所构成的第0个位平面提取出来,得到数字水印信息。

​ 在实际中可以根据需要在多个通道内嵌入相同的水印(提高鲁棒性,即使部分水印丢失,也能提取出完整水印信息),或在各个不同的通道内嵌入不同的水印(提高嵌入容量)

3.8.2 实现方法

3.8.2.1 嵌入过程

将数字水印信息嵌入载体图像内,步骤如下:

(1)载体图像预处理

读取原始载体图像,并获取载体图像的行数M和列数N

(2)建立提取矩阵

建立一个MxN大小、元素值均为254的提取矩阵(数组),用来提取载体图像的高七位。

(3)保留载体图像的高七位,将最低位置为0

载体图像与元素值为254的矩阵进行按位与运算

(4)水印图像处理

将8位灰度图的二值图像转换为二进制二值图像

(5)嵌入水印

将一个最低有效位(LSB)为0的数值A与一个单位二进制值B进行按位或运算,相当于用该单位二进制值B替换原始数值A的最低有效位,即可以实现将单位二进制值B嵌入数值A的最低有效位上。

(6)显示图像

水印嵌入过程的流程图

Created with Raphaël 2.3.0 初始化 载体图像预处理 建立提取矩阵 载体图像最低有效位置零 水印图像处理 嵌入水印 显示原始图像、水印、含水印图像 结束框
3.8.2.2 提取过程

(1)含水印载体图像处理

读取包含水印的载体图像,获取含水印载体的图像的大小M×N

(2)建立提取矩阵

定义一个与含水印载体图像等大小的值为1的矩阵作为提取矩阵

(3)提取水印信息

将含水印载体图像与提取矩阵进行按位与运算,提取水印信息

基于上述规则,针对图像内的每个像素,将其与数值1进行按位与操作,即可将图像的最低有效位提取出来

(4)计算去除水印后的载体图像

有时需要删除包含在水印载体图像内的水印信息。通过将含水印载体图像的最低有效位置零,即可实现删除水印信息。

(5)显示图像

Created with Raphaël 2.3.0 初始化 含水印图像处理 建立提取矩阵 提取水印信息 计算删除水印后的载体图像 显示图像 结束框

示例:

import cv2
import numpy as np
#读取原始载体图像
lena=cv2.imread ("lena.bmp",0)
#读取水印图像
watermark=cv2.imread ("watermark.bmp",0)
#将水印图像内的值255处理为1,以方便嵌入
#后续章节会介绍使用threshold处理
w=watermark[:,:]>0
watermark[w]=1
#读取原始载体图像的shape值
r,c=lena.shape
#============嵌入过程============
#生成元素值都是254的数组
t254=np.ones ( (r,c) ,dtype=np.uint8) *254
#获取lena图像的高七位
lenaH7=cv2.bitwise_and (lena,t254)
#将watermark嵌入lenaH7内
e=cv2.bitwise_or (lenaH7,watermark)
#==========提取过程============
#生成元素值都是1的数组
t1=np.ones ( (r,c) ,dtype=np.uint8)
#从载体图像内提取水印图像
wm=cv2.bitwise_and (e,t1 )
print (wm)
#将水印图像内的值1处理为255,以方便显示
#后续章节会介绍使用threshold实现
w=wm[:,:]>0
wm[w]=255
#============显示============
cv2.imshow ("lena",lena)
cv2.imshow ("watermark",watermark*255)
#当前watermark内最大值为1
cv2.imshow ("e",e)
cv2.imshow ("wm",wm)cv2.waitKey ()
cv2.destroyAllWindows ()

猜你喜欢

转载自blog.csdn.net/weixin_56321457/article/details/125903258