OpenCV笔记之六(2)——图像处理之图像算术

2、图像运算

相信大家都记得,在RGB图像中,每个像素点的强度是分布在[0, 255]之间的。如果我们对一个像素值为250的像素点进行加10的运算的话,结果显然不会是260,因为RGB图像是以8位无符号整型表示的,亦即260是一个无效数。这个时候会有两种可选的做法。

其一是饱和运算。为保证所有的像素点都落在[0, 255]之间,直接将像素值超过255的像素全部置为255,使其不至于逃逸出8位无符号整型所能表示的数值范围。

另一种方法就是采用模运算。在模运算下,250+10将得出260 = 4 mod 256,实现“回绕”(warp),即260在溢出256后又重新从0开始来到了4。

事实上,我们通过想要得到的不同结果来选取不同的运算方式。需要注意的是在OpenCV和Numpy中加法的差异。

Numpy:实行模运算;OpenCV:实行饱和运算。

接下来就通过书中的代码进行进一步深刻细致的体会和理解。

a.源代码展示

arithmetic.py

from __future__ import print_function
import numpy as np
import argparse
import cv2

# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())

# Load the image and show it
image = cv2.imread(args["image"])
cv2.imshow("Original", image)

# Images are NumPy arrays, stored as unsigned 8 bit integers.
# What does this mean? It means that the values of our pixels
# will be in the range [0, 255]. When using functions like
# cv2.add and cv2.subtract, values will be clipped to this
# range, even if the added or subtracted values fall outside
# the range of [0, 255]. Check out an example:
print("max of 255: {}".format(cv2.add(np.uint8([200]), np.uint8([100]))))
print("min of 0: {}".format(cv2.subtract(np.uint8([50]), np.uint8([100]))))

# NOTE: If you use NumPy arithmetic operations on these arrays,
# the values will be modulos (wrap around) instead of being
# clipped to the [0, 255] arrange. This is important to keep
# in mind when working with images.
print("wrap around: {}".format(np.uint8([200]) + np.uint8([100])))
print("wrap around: {}".format(np.uint8([50]) - np.uint8([100])))

# Let's increase the intensity of all pixels in our image
# by 100. We accomplish this by constructing a NumPy array
# that is the same size of our matrix (filled with ones)
# and the multiplying it by 100 to create an array filled
# with 100's. Then we simply add the images together. Notice
# how the image is "brighter".
M = np.ones(image.shape, dtype = "uint8") * 100
added = cv2.add(image, M)
cv2.imshow("Added", added)

# Similarly, we can subtract 50 from all pixels in our
# image and make it darker:
M = np.ones(image.shape, dtype = "uint8") * 50
subtracted = cv2.subtract(image, M)
cv2.imshow("Subtracted", subtracted)
cv2.waitKey(0)
b.代码解释

Line 21-22

通过format格式化函数分别输出使用cv2.add函数进行加法200+100的结果及使用cv2.subtract函数进行减法50-100的结果。

Line 28-29

分别输出直接采用numpy进行加法200+100及进行减法50-100的结果。

根据打印结果我们不难验证:OpenCV中的加减法实行饱和运算,而Numpy中的加减法实行模运算。

在这里插入图片描述

接下来我们对图像进行加减运算。观察图像算术运算的效果。

Line 37-46

分别定义了两个与原图像大小一致,数据类型为8位无符号整型的全1数组,并分别将其*100、*50来构造两个数组元素分别全为100和全为50的数组。使用opencv中的加法和减法函数分别在原图像上作+100和-50的算术运算并显示进行加/减法后的图像。

在这里插入图片描述在这里插入图片描述在这里插入图片描述
OriginalAddedSubtracted

从输出的图像上不难看出,经过加法运算后的图像显得更“亮”,而经过减法后的图像显得更“暗”。因为像素值表征了像素点的亮度,因此在经过加法后,像素强度增加,故而图像变亮;而减法则使得原图像的各像素点像素强度减小,因而变暗。要注意的是,因为在opencv中对图像进行算术运算采用的是饱和运算,所以不会出现“回绕”(warp)的现象,若采用numpy加法则不然。

我们可以将图像算术部分的代码改为采用numpy运算的形式来测试一下,相应的代码和输出结果如下所示:

···
# Use Numpy arithmetic operations on the source image to make a comparison
M = np.ones(image.shape, dtype = "uint8") * 100
added = image + M
cv2.imshow("Added_np", added)

M = np.ones(image.shape, dtype = "uint8") * 50
subtracted = image - M
cv2.imshow("Subtracted_np", subtracted)
cv2.waitKey(0)
在这里插入图片描述在这里插入图片描述在这里插入图片描述
OriginalAdded_npSubtracted_np

可以看到,由于在numpy运算中,许多像素点发生了翻转,加法和减法得出的图片与原图片相去甚远甚至面目全非。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值