【python-opencv】Numpy基础 图像的运算

认识Numpy.array

Python中提供了list容器,可以当作数组使用。但列表中的元素可以是任何对象,因此列表中保存的是对象的指针,这样一来,为了保存一个简单的列表[1,2,3]。就需要三个指针和三个整数对象。对于数值运算来说,这种结构显然不够高效。
  Python虽然也提供了array模块,但其只支持一维数组,不支持多维数组,也没有各种运算函数。因而不适合数值运算。
  而NumPy的出现弥补了这些不足。(——摘自张若愚的《Python科学计算》)
  简单来说,Numpy是用来处理多维数组的,也可以理解为线性代数的矩阵,通常为列表嵌套列表或多个列表的形式,来看看Numpy.array。

import numpy as np
import cv2
# 生成一个随机灰度图
# 使用NumPy库生成一个随机的256x256的二维数组
image_gray = np.random.randint(0,256,size=[256,256],dtype=np.uint8)

cv2.imshow('image_gray', image_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

图像的运算

加法运算

计算机一般使用八个比特位来表示灰度图像,定义矩阵类型为为八位无符号整型数时,范围为0-255。
cv2.add加法操作要求两个图片的长宽相同,通道数相同,或者第二个图是一个标量。

运算符+

两个图对应位置的元素相加,超出255的数字,会被截断,相当于% 256。

cv2.add()

两个图对应位置的元素相加,如果超过255,全部变成255。

import numpy as np
import cv2
# 定义两个随机的3*3矩阵,范围为0-255
img1 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
img2 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
print("img1=\n",img1)
print("img2=\n",img2)
print("img1 + img2=\n",img1+ img2)
print("------------")
print("cv2.add(img1,img2)=\n",cv2.add(img1,img2))

在这里插入图片描述

cv.addWeighted()

图像融合本质上也是图像加法,但是它可以为用于加法的图片设置权重系数,最后决定哪张图片占得比重更大。
一般格式:

 cv2.add Weighted(image1, weight1, Image2, weight2, gammaValue)

参数:

  • image1:第一个图像数组输入。
  • weight 1:输入图像中第一个图像元素的权重。建议范围[0,1]之间,实质上是第一个图的每个元素乘权重。
  • image2:第二个图像数组输入。
  • weight 2:输入图像中第一个图像元素的权重。
  • gammaValue:偏差,例如若相加的图片太亮,参数给-100,表示每个值都减100。
import numpy as np
import cv2
img1 = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")
print(img1.shape)
img2 = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-D.jpg")
print(img2.shape)
dst = cv2.addWeighted(img1, 0.4, img2, 0.6, 0)
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

减法运算

操作要求两个图片的长宽相同,通道数相同。

运算符-

两个图对应位置的元素相减,小于0的数字,会被截断,相当于% 255 +1。

cv2.subtract()

两个图对应位置的元素相减,小于0的数字,全部变成0。

import numpy as np
import cv2
# 定义两个随机的3*3矩阵,范围为0-255
img1 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
img2 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
print("img1=\n",img1)
print("img2=\n",img2)
print("img1 - img2=\n",img1 - img2)
print("------------")
print("cv2.subtract(img1,img2)=\n",cv2.subtract(img1,img2))


在这里插入图片描述

乘法运算

矩阵乘法

np.dot()主要用于矩阵的乘法运算,其中包括:向量内积、多维矩阵乘法等等。乘法符合线性代数中矩阵的乘法规则.

向量内积

向量其实是一维的矩阵,两个向量进行内积运算时,需要保证两个向量包含的元素个数是相同的。
运算:每个元素对应相乘,再相加所得.

import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7])
y = np.array([2, 3, 4, 5, 6, 7, 8])
result = np.dot(x, y)
print(result) # 结果:(1*2)+(2*3)+(3*4+(4*5)+(5*6)+(6*7)+(7*8) = 168
多维矩阵乘法

注意:

1.数组的运算是元素级的,数组相乘的结果是各对应元素的积组成的数组,而对于矩阵而言,需要求的是点积
2.两个矩阵(x, y)如果可以进行乘法运算,需要满足以下条件:
A为 m×n 阶矩阵,B为 n×p 阶矩阵,
则相乘的结果 result 为 m×p 阶矩阵。

运算:A的第一行乘B的第一列得到第一个元素…

arr5=np.array([[2,3],[4,5]])
arr6=np.array([[6,7],[8,9]])
print(np.dot(arr5,arr6))
[[36 41]
 [64 73]]

矩阵点乘cv2.multiply()

运算:两对应元素相乘.
当结果大于255时,类似于cv2.add()函数,计算机会进行截断,取最大值255.

import numpy as np
import cv2
# 定义两个随机的3*3矩阵,范围为0-255
img1 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
img2 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
print("img1=\n",img1)
print("img2=\n",img2)
print("cv2.multiply(img1,img2)=\n",cv2.multiply(img1,img2))

在这里插入图片描述

除法运算

矩阵的点除运算cv2.divide()

当定义随机矩阵为八位整型数时,做除运算时会主动取整.

import numpy as np
import cv2
# 定义两个随机的3*3矩阵,范围为0-255
img1 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
img2 = np.random.randint(0,256,size=[3,3],dtype=np.uint8)
print("img1=\n",img1)
print("img2=\n",img2)
print("cv2.divide(img1,img2)=\n",cv2.divide(img1,img2))

在这里插入图片描述

逻辑运算

图像由像素组成,每个像素可以用十进制整数表示,十进制整数又可以转化为二进制数,所以图像也可以做位运算。

功能函数
按位与cv2.bitwise_and()
按位或cv2.bitwise_or()
按位取反cv2.bitwise_not()
按位异或cv2.bitwise_xor()
掩膜

当计算机处理图像时,有些内容需要处理,有些内容不需要处理。能够覆盖原始图像,仅暴露原始图像“感兴趣区域”(ROI)的模板图像就叫做掩模。

掩模(mask),也叫做掩码,在程序中用二值图像来表示:0值(纯黑)区域表示被遮盖的部分,255值(纯白)区域表示暴露的部分(某些场景下也会用0和1当作掩模的值),通过对二进制进行按位操作可获得感兴趣或待处理的区域.
在这里插入图片描述

按位与

按位与就是按照二进制位进行判断,如果同一位的数字都是1,则运算结果的相同位数字取1,否则取0。(记作有0为0)
OpenCV提供 bitwise_and() 方法来对图像做位与运算。
与运算:
在这里插入图片描述
格式:

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

参数:

  • dst: 运算之后的结果图像
  • src1: 第一幅图像
  • src2: 第二幅图像
  • mask:(可选)掩模

与运算有两个特点✨:

  • 如果某像素与纯白色像素做与运算,结果仍然是某像素的原值
  • 如果某像素与纯黑色像素做与运算,结果为纯黑像素

结论or应用:
如果原图像与掩模进行与运算,原图像仅会保留掩模中白色区域所覆盖的内容,其他区域全部变成黑色。

import cv2
import numpy as np

img = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")  # 原始图像
mask = np.zeros(img.shape, np.uint8)  # 构造图像大小相等的掩模图像
mask[102:203, : , : ] = 255  # 横着的白色区域
mask[ : , 102:203,  : ] = 255  # 竖着的白色区域
img_and = cv2.bitwise_and(img, mask)  # 与运算
cv2.imshow("img", img)  # 展示图像
cv2.imshow("mask", mask)  # 展示掩模图像
cv2.imshow("img_and", img_and)  # 展示与运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

在这里插入图片描述

按位或

按位或就是按照二进制位进行判断,如果同一位的数字都是0,则运算结果的相同位数字取0,否则取1。(记作有1为1)
OpenCV提供 bitwise_or() 方法来对图像做位或运算。
或运算:
在这里插入图片描述格式:

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

参数:

  • dst: 运算之后的结果图像
  • src1: 第一幅图像
  • src2: 第二幅图像
  • mask:(可选)掩模

或运算有两个特点(同与运算相反)✨:

  • 如果某像素与纯白色像素做或运算,结果为纯白色像素
  • 如果某像素与纯黑色像素做或运算,结果仍然是某像素的原值

结论or应用:
如果原图像与掩模进行或运算,原图像仅会保留掩模中黑色区域所覆盖的内容,其他区域全部变成白色.

import cv2
import numpy as np

img = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")  # 原始图像
mask = np.zeros(img.shape, np.uint8)  # 构造图像大小相等的掩模图像
mask[102:203, : , : ] = 255  # 横着的白色区域
mask[ : , 102:203,  : ] = 255  # 竖着的白色区域
img_or = cv2.bitwise_or(img, mask)  
cv2.imshow("img", img)  # 展示图像
cv2.imshow("mask", mask)  # 展示掩模图像
cv2.imshow("img_or", img_or)  # 展示与运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

在这里插入图片描述

按位非

非运算是一种单目运算,仅需一个数字参与运算就可以得出结果。如果运算数某位上数字是0,则运算结果的相同位的数字就取1,如果这一位的数字是1,则运算结果的相同为的数字取0。注意OpenCV中的范围为0~255,1111 1111 表示255,255为0,0为255
OpenCV提供 bitwise_not() 方法来对图像做非运算。
非运算:

输入输出
01
10

格式:

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

参数:

  • dst: 运算之后的结果图像
  • src: 图像
  • mask:(可选)掩模

非运算的特点✨:

  • 在进行非运算时,等同于用255-img(图像),
  • 相片底片的颜色与图像的原色是正好相反的,即反色,又被称为补色,图像的反色与原色叠加后,可以变为纯白色。因此,为了得到一幅图像的底片效果,只需用255(纯白色)减去这幅图像中的每一个像素的BGR值,或者用非运算也可以.
import cv2
import numpy as np

img = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")  # 原始图像
img_not = cv2.bitwise_not(img)  
cv2.imshow("img_or", np.hstack((img,img_not)))

img_sub = 255-img 
cv2.imshow("img_sub", np.hstack((img,img_sub)))

cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

在这里插入图片描述

按位异或

如果两个运算数同一位上的数字相同,则运算结果的相同位数字取0,否则取1。
OpenCV提供 bitwise_xot() 方法来对图像做异或运算。
异或运算:
在这里插入图片描述
格式:

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

参数:

  • dst: 运算之后的结果图像
  • src1: 第一幅图像
  • src2: 第二幅图像
  • mask:(可选)掩模

异或运算有两个特点:

  • 如果某像素与纯白色像素做异或运算,结果为原像素的取反结果
  • 如果某像素与纯黑色像素做异或运算,结果仍然是某像素的原值
  • 异执行一次异或运算得到一个结果,再对这个结果执行第二次异或运算,则又会还原成最初的值。利用这个特点可以实现对图像内容的加密和解密。

结论or应用:
如果原图像与掩模进行异或运算,掩模白色区域所覆盖的内容呈现取反结果,黑色区域覆盖的内容保持不变。

import cv2
import numpy as np

img = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")  # 原始图像
mask = np.zeros(img.shape, np.uint8)  # 构造图像大小相等的掩模图像
mask[102:203, : , : ] = 255  # 横着的白色区域
mask[ : , 102:203,  : ] = 255  # 竖着的白色区域
img_xor = cv2.bitwise_xor(img, mask)  
cv2.imshow("img", img)  # 展示图像
cv2.imshow("mask", mask)  # 展示掩模图像
cv2.imshow("img_or", img_xor)  # 展示与运算结果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

在这里插入图片描述

import cv2
import numpy as np
#  对图像进行加密、解密
# 利用random.randint()方法创建一个随机像素值图像作为密钥图像,
# 让密钥图像与原始图像做异或运算得出加密运算,再使用密钥图像对加密图像进行解密。

def encode(img, img_key): # 加密、解密方法
    result = img = cv2.bitwise_xor(img, img_key)  # 两图像做异或运算
    return result

img = cv2.imread(r"C:\Users\lyx15\Pictures\OIP-C.jpg")  # 原始图像
rows, colmns, channel = img.shape  # 原图像的行数、列数和通道数
# 创建与图像大小相等的随机像素图像,作为密钥图像
img_key = np.random.randint(0, 256, (rows, colmns, 3), np.uint8)

cv2.imshow("1", img)  # 展示图像
cv2.imshow("2", img_key)  # 展示秘钥图像

result = encode(img, img_key)  # 对图像进行加密
cv2.imshow("3", result)  # 展示加密图像
result = encode(result, img_key)  # 对图像进行解密
cv2.imshow("4", result)  # 展示解密图像
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

在这里插入图片描述

————————————————
参考文章:
博主「Daetalus」NumPy简明教程
博主「zhaoweiwei369」dot()
偏应用文章推荐:
博主「趴抖」 图像的基本操作+图像上的算术运算

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值