在图像处理的过程中,需要对图像进行加法运算。可以通过运算符“+”对图像进行加法运算,也可以调用函数cv2.add()函数进行运算。 通常图像像素灰度值范围为0~255,两像素值相加时可能会超过255,上述两种运算方式对这种情况的处理方式是不一样的。
使用运算符“+”对像素值为a和b的两个像素点进行操作时,运算结果为:mod(a+b,256),就是两像素值相加后的结果对256取模求余数。
import numpy as np image1=np.random.randint(0,256,(3,3),dtype=np.uint8) image2=np.random.randint(0,256,(3,3),dtype=np.uint8) image3=image1+image2 print("image1",image1) print("image2",image2) print("image1",image3)运算结果: 注意这里的数据类型设为np.uint8。
其运算规则为: 计算结果=min(a+b,255) 像素和小于255时,为和值;运算结果大于255时,视为255。
import cv2 import numpy as np image1=np.random.randint(0,256,(3,3),dtype=np.uint8) image2=np.random.randint(0,256,(3,3),dtype=np.uint8) image3=cv2.add(image1,image2) print("image1",image1) print("image2",image2) print("image1",image3)运行结果:
分别使用两种不同的方法对一副图像进行叠加,观察结果:
import cv2 import numpy image=cv2.imread("color_2.png") image1=image+image image2=cv2.add(image,image) cv2.imshow("original",image) cv2.imshow("运算符+",image1) cv2.imshow("cv2.add",image2) cv2.waitKey(0) cv2,destroyAllWindows()运行结果: 观察图像可以发现使用cv2.add()使图像与原来相比变的更亮,使用加法运算符,图像有的地方比原来更暗。
所谓加权和,就是在叠加的时候给每幅图像赋予不同的权值比重并可能会带有一定的偏移值。 计算公式:dst=(src1a+srcb+bias) 可以自己用运算符进行叠加,也可调用内置函数。 opencv提供了函数cv2.addWeighted()来实现图像加权和,语法格式:
dst=cv2.addWeighted(src1,a,src2,b,bias)参数说明: dst为运算后的图像 src1为图像1,a为其权重 src2为图像2,b为其权重 借助此函数实现两张图片的叠加:
import cv2 cat=cv2.imread("cat.jpg") dog=cv2.imread("dog.jpg") dog=cv2.resize(image1,(533,300)) cat_dog=cv2.addWeighted(cat,0.5,dog,0.5,0) cv2.imshow("cat",image) cv2.imshow("dog",image2) cv2.imshow("cat and dog",cat_dog) cv2.waitKey(0) cv2.destroyAllWindows()运行结果
将像素点灰度值的各个bit位进行与操作 若灰度值8位,将任一像素与0按位与,结果均为0;将任一像素与255按位与,结果均为其本身。我们可以构造一个掩模与其他图像按位与,可以突出其他图像的某些部分。 在opencv中提供了cv2.bitwise_and()函数。其语法如下:
dst=cv2.bitwise_and(src1,src2[,mask]])参数说明: dst为与输入具有同等规模的图像; src1为图像1; src2为图像2; mask为可选掩码操作;
构造一个掩模,保留图像特定部分
import cv2 import numpy as np dog=cv2.imread("dog_1.jpg") local=np.zeros((300,533,3),dtype=np.uint8) local[20:125,100:200,:]=255 face=cv2.bitwise_and(dog,local) #face=dog[20:125,100:200,:] cv2.imshow("dog",dog) cv2.imshow("local",local) cv2.imshow("face",face) cv2.waitKey(0) cv2.destroyAllWindows()运行结果:
在opencv中提供了cv2.bitwise_or()函数。其语法如下:
dst=cv2.bitwise_and(src1,src2[,mask]])参数说明: dst为与输入具有同等规模的图像; src1为图像1; src2为图像2; mask为可选掩码操作;
构造一个掩模,保留图像特定部分
import cv2 import numpy as np dog=cv2.imread("dog_1.jpg") local=np.zeros((300,533,3),dtype=np.uint8)+255 local[20:125,100:200,:]=0 face=cv2.bitwise_or(dog,local) #face=dog[20:125,100:200,:] cv2.imshow("dog",dog) cv2.imshow("local",local) cv2.imshow("face",face) cv2.waitKey(0) cv2.destroyAllWindows()运行结果:
按位非就是将灰度值各bit位上的数取反 可以将二值图像或灰度图像反转,即白变黑,黑变白。 在opencv中提供了cv2.bitwise_not()函数。其语法如下:
dst=cv2.bitwise_not(src[,mask]])参数说明: dst为与输入具有同等规模的图像; src为输入图像; mask为可选掩码操作;
import cv2 import numpy as np image=np.ones((300,300),dtype=np.uint8) image[0:100,:]=255 reverse=cv2.bitwise_not(image) cv2.imshow("image",image) cv2.imshow("reverse",reverse) cv2.waitKey(0) cv2.destroyAllWindows()运行结果:
异或的作用在于与0异或为本身,与255异或取反 在opencv中提供了cv2.bitwise_xor()函数。其语法如下:
dst=cv2.bitwise_xor(src1,src2[,mask]])参数说明: dst为与输入具有同等规模的图像; src1:输入图像1; src2为输入图像2; mask为可选掩码操作;
与数字图像空间滤波中的滤波器,核的概念基本相同。
图像与数值进行运算,就是图像每个像素点的值与该数进行运算。如要增加图像的亮度,可以将图像与一个固定值进行相加。
类似于数字图像处理中的位图切割,将灰度值0~255总共8个bit,分为8个位平面。处于高位的值对图像影响最大,低位对图像影响最小。我们可以借助位与操作实现位平面的分解。 对于灰度图,进行位平面分解步骤如下:
读入图像,彬获取图像的规格,如长与宽。
若要提取第n个位平面,则将只有第n位为1,其余位为0的值与像素值按位与。 第n个位平面的提取矩阵的的各个元素的值应该为2^n。
将图像与提取矩阵做位于操作
由于低位图值较小,显示时几乎为黑色,所以进行阈值处理,将其转换为二值图像,即大于0的值预置为255。
具体实例:
import cv2 import numpy as np import matplotlib.pyplot as plt dog=cv2.imread("dog_1.jpg",cv2.IMREAD_GRAYSCALE) #获取图像大小 x,y=dog.shape #创建提取矩阵 mode=np.zeros((x,y,8),dtype=np.uint8) for i in range(8): mode[:,:,i]=2**i plt.subplot(3,3,1),plt.imshow(dog,"gray"),plt.title("original") for i in range(0,8): #位图分解 image=cv2.bitwise_and(dog,mode[:,:,i]) thres=image>0 image[thres]=255 plt.subplot(3,3,i+2),plt.imshow(image,"gray"),plt.title(str(i))运行结果:
通过对原始图像与密匙图像进行按位异或,可以实现加密;将原始图像与密匙图像再次进行异或,可以实现解密;这是因为任何一位与0或1经历两次异或之后又会回到数据本身。
import cv2 import numpy as np import matplotlib.pyplot as plt dog=cv2.imread("dog_1.jpg",cv2.IMREAD_GRAYSCALE) key=np.random.randint(0,256,dog.shape,dtype=np.uint8) #加密 print(dog.shape) print(key.shape) encryption=cv2.bitwise_xor(dog,key) #解密 decryption=cv2.bitwise_xor(encryption,key) cv2.imshow("original",dog) cv2.imshow("key",key) cv2.imshow("encryption",encryption) cv2.imshow("decryption",decryption) cv2.waitKey(0) cv2.destroyAllWindows()运行结果:
由于位平面中最低有效位,即0位的信息对原始图像的影响基本忽略不计。所以我们可以实现最低位信息隐藏,将我们需要隐藏的图像信息嵌入实体图像的最低有效位,从而达到实体图像的目的,在需要的时候我们又可以将实体图像中最低位的信息提取出来,达到提取秘密信息的目的。这种信息隐藏的方式就是数字水印。 实现方法:
(1)将实体图像的最低有效位清零,保留其高7位的信息;可以通过像素值与254进行按位与运算实现。 (2)对于水印图像,我们要将其首先转化为二值图像,还要进行阈值处理,将255的值预置为1,便于信息的嵌入。 (3)将处理后的水印图像与实体图像进行按位或。
(1)提取图像低位信息,这与位平面分解原理相同 (2)对提取后的图像进行逆阈值处理,便于显示
实例:
import cv2 import numpy as np #水印图片 water_mark=cv2.imread("true.jpg",cv2.IMREAD_GRAYSCALE) #实体图片 image=cv2.imread("color_2.png",cv2.IMREAD_GRAYSCALE) x,y=image.shape #将两张图片大小统一 water_mark=cv2.resize(water_mark,(y,x)) #嵌入 #将实体图片最低有效位清零 #构建清零矩阵 mode1=np.zeros(image.shape,dtype=np.uint8)+254 #清零 image1=cv2.bitwise_and(image,mode1) #水印图片预处理 mark1=water_mark>0 water_mark1=water_mark.copy() water_mark1[mark1]=1 #嵌入 image2=cv2.bitwise_or(image1,water_mark1) #水印图片提取 #创建提取矩阵 mode2=np.ones(image.shape,dtype=np.uint8) #提取 water_mark2=cv2.bitwise_and(image2,mode2) mark2=water_mark2>0 water_mark2[mark2]=255 plt.subplot(2,2,1),plt.imshow(water_mark,"gray"),plt.title("original water_mark") plt.subplot(2,2,2),plt.imshow(image,"gray"),plt.title("original image") plt.subplot(2,2,3),plt.imshow(image2,"gray"),plt.title("after image") plt.subplot(2,2,4),plt.imshow(water_mark2,"gray"),plt.title("after water_mark") #cv2.imshow("original water_mark",water_mark) #cv2.imshow("original image",image) #cv2.imshow("after image",image2) #cv2.imshow("after water_mark",water_mark2) cv2.waitKey(0) cv2.destroyAllWindows()运行结果: