【opencv】(2) 图像处理:边界填充、图像融合、图像阈值、数值计算

主要内容有:边界填充 cv2.copyMakeBorder(),数值计算 cv2.add(),改变尺寸 cv2.resize(),图像融合 cv2.addWeighted(),图像阈值 cv2.threshold()


在开始之前,我们先导入图像,img中存放我们需要用到的图像。并定义一个图像显示函数,便于接下来画图。

# 导入opencv库
import cv2
# 定义图像显示函数
def cv_show(name,img):
    # 传入(自定义窗口名,图像数据)
    cv2.imshow(name,img) 
    # 等待时间设为0,让图像不会自己消失
    cv2.waitKey(0)
    # cv2.waitKey(1000)  # 图像显示1000毫秒后消失
    # 键盘上任意按一个图像消失
    cv2.destroyAllWindows()

# 指定图像所在的文件夹
filepath = 'C:\\...\\opencv\\img'
# 提取问价夹中的某一张图像
img = cv2.imread(filepath+'\\wise3.jpg')

1. 边界填充

设置边界框方法: cv2.copyMakeBorder(src, top, bottom, left, right, borderType,  value)

src: 输入的图片

top, bottom, left, right: 相应方向上的边框宽度

borderType: 定义添加边框的方法

value:如果borderType为 cv2.BORDER_CONSTANT 时需要填充的常数值

borderType方法如下:

cv2.BORDER_REPLICATE:复制法,复制最边缘像素

cv2.BORDER_REFLECT:反射法,在图像中指定像素的两边进行反射复制,如: gfedcba|abcdefgh|hgfedcb

cv2.BORDER_REFLECT_101:反射法,以最边缘像素为轴,如:dcba|abcd|dcba

cv2.BORDER_WRAP:外包装法,如:cdefgh|abcdefgh|abcdefg

cv2.BORDER_CONSTANT:常量数值填充

我们分别来看一下各种方法:

#(1)边界填充
# 先指定在上下左右分别填充的大小
top_size,bottom_size,left_size,right_size = (50,50,50,50)
# 填充函数cv2.copyMakeBorder(输入图像,填充多少,borderType=填充方法)

# 复制
img1 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
# 反射
img2 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REFLECT)
# 反射101
img3 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REFLECT_101)
# 外包装
img4 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_WRAP)
# 常量填充,value=0
img5 = cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_CONSTANT,value=0)

# 绘图
import matplotlib.pyplot as plt
# 显示中文宋体
plt.rcParams['font.sans-serif'] = ['SimSun'] 
# 设置画板大小
plt.figure(figsize=(10,7))
# 原图
plt.subplot(231),plt.imshow(img),plt.title('原图')
# 复制
plt.subplot(232),plt.imshow(img1),plt.title('复制')
# 反射
plt.subplot(233),plt.imshow(img2),plt.title('反射')
# 反射101
plt.subplot(234),plt.imshow(img3),plt.title('反射101')
# 外包装
plt.subplot(235),plt.imshow(img4),plt.title('外包装')
# 常量填充
plt.subplot(236),plt.imshow(img5),plt.title('常量0填充')

我们从图中可以看出不同方法的区别。可能有同学可能会问,这颜色怎么这么奇怪。注意,在opencv中图像的颜色通道是BGR组成的,而matplot中颜色通道是RGB构成,在展示图像时,会有颜色的差别,所以尽量用opencv的图像展示方法。


2. 数值计算

2.1 直接相加

两张图片直接做加法,需要两张图像的size一样大对应的像素点相加,由于每个像素点值的大小在0-255之间,因此相加后大于255的像素值自动减去255,如150+150=300,没有300的像素值,自动变成45。如果一张图像整体加上一个常量,即每个元素的增加一个常量值,亮度提升。

# 先读入2张图片
img1 = cv2.imread(filepath+'\\sit1.jpg')
img2 = cv2.imread(filepath+'\\wise2.jpg')
# ==1== 直接相加超过255的像素值会自动减去255
# 对img1上的所有像素点加10,整体的shape不变
img3 = img1+10
cv_show('img3',img3)
# 将两张图相加,两张图的shape需要一致
img4 = img1+img2
cv_show('img4',img4)
# 由于图中的每个像素点的取值是在0-255之间,如果超过255会自动减去255

size相同的两幅图像直接相加后的结果为


2.2 使用函数相加 cv2.add()

cv2.add(src1, src2)

要求两张图象的size和通道数相同。对应像素值相加,相加后,超过255的数值就让它等于255

 src1, src2:两幅图像相加,或一张图像加一个数值

 mask:图像掩膜,为8位单通道的灰度图像,用于指定要更改的输出图像数组的元素,即输出图像像素只有mask对应位置元素不为0的部分才输出,否则该位置像素的所有通道分量都设置为0

dtype:输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位)。

# ==2== cv2.add()
# 相加后若超过255,那像素点的值就取255
img5 = cv2.add(img1,img2)
cv_show('img5',img5)


3. 图像融合

将两张图像按一定比例融合在一起,需要两张图像的size和通道数相同

#(3)图像融合,两张图混合在一起
# 读取两张图片
img1 = cv2.imread(filepath+'\\sit2.jpg')
img2 = cv2.imread(filepath+'\\wise2.jpg')
# ==1== 先查看一下两张图的shape
img1.shape  #(503,1201,3) 
img2.shape  #(1080,1440,3)

3.1 改变图像大小

指定具体的长度和高度: cv2.resize(图像, (长, 高))

指定缩放比例: cv2.resize(图像, (0,0), fx=沿x轴缩放比例, fy=沿y轴缩放比例)

注意制定具体的长度和高度时,一定是先指定宽再指定长,如下 cv2.resize(img2,(1201,503)),把img2变成高为503长为1201,而我们.shape查到的结果是(高, 长)

# ==2== 改变大小cv2.resize(图像,指定大小),接收返回值
# 注意先指定宽,再指定高
# 将img2变得和img1的size一样
img2 = cv2.resize(img2,(1201,503))
img2.shape
# 不指定具体数值,只给出倍数关系,即图像沿x和y轴的缩放比例
img4 = cv2.resize(img2,(0,0),fx=3,fy=3)
cv_show('name', img4)

3.2 图像融合

两张图像按一定比例融合: cv2.addWeighted(图像1, 权重1, 图像2, 权重2, 亮度偏置)

相当于 y = a x1 + b x2 + c,其中a、b代表权重,c代表亮度上提亮多少

img5 = cv2.addWeighted(img1,0.5,img3,0.4,0)
cv_show('img5',img5)


4. 图像阈值

首先我们把需要用到的图像和库导入一下

import cv2
import matplotlib.pyplot as plt
# 指定图像所在文件夹
filepath = 'C:\\...\\opencv\\img'
# 转换成灰度
img = cv2.imread(filepath+'\\wise3.jpg',cv2.IMREAD_GRAYSCALE)

图像阈值处理函数: ret, dst = cv2.threshold(src, thresh, maxval, type)

参数:

src:  输入图,只能输入单通道图像,通常是灰度图

dst:  输出图

thresh:  阈值,是一个值,通常为127

maxval:  当图像超过了阈值或低于阈值(由type决定),所赋予的值

type:  二值化操作的类型,包含:

cv2.THRESH_BINARY  二值法,超过阈值thresh部分取maxval(设定的最大值),否则取0

cv2.THRESH_BINARY_INV  超过阈值的部分取0,小于阈值取maxval

cv2.THRESH_TRUNC  截断,大于阈值的部分设为阈值,小于阈值的不变

cv2.THRESH_TOZERO  大于阈值的部分不变,小于阈值的部分变成0。亮的部分不变,暗的部分变成黑点

cv2.THRESH_TOZERO_INV  大于阈值的变成0,小于阈值的不变。暗的部分不变,亮的部分变成黑点

返回值

ret:  阈值

dst:  输出图

# 方法1:输入灰度图,阈值127,大于阈值变成255,小于阈值变成0
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
# 方法2:大于阈值127变成0,小于阈值变成255。原本比较亮的变成黑点,原来暗的变成白点
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
# 方法3:大于阈值127的设为阈值,小于阈值的不变
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
# 方法4:大于阈值127的值变成127,小于127的值不变
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
# 方法5:小于127的值不变,大于127的值变成0
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

# 绘图
titles=['original','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images=[img,thresh1,thresh2,thresh3,thresh4,thresh5]
plt.figure(figsize=(8,8))
for i in range(6):
    plt.subplot(2,3,i+1)
    plt.imshow(images[i],'gray')
    plt.title(titles[i])
plt.show()   

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立Sir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值