图像添加(Image Addition):
Image Addition操作是将两幅图像的像素值进行相加,可以使用OpenCV的add()函数或者是Numpy的简单相加操作:res = img1 + img2. 两幅相加图像的在像素值类型与图像深度属性必须一致,且第二幅图像只能是标量值。
使用OpenCV的add()函数与numpy的直接加操作在像素值越界时,计算结果会存在一点差别。OpenCV的add()函数采取饱和操作:即当像素值和>255时候,直接取值255。Numpy数值操作是取余运算。
示例代码如下:
import cv2
import numpy as np
x = np.uint8([250])
y = np.uint8([10])
print('--------cv2.add() operations--------')
# 250 + 10 = 260 ==> 255
print(cv2.add(x, y))
print('--------numpy operations--------')
# 250 + 10 = 260 % 255 = 4
print(x + y)
'''
results:
--------cv2.add() operations--------
[[255]]
--------numpy operations--------
[4]
'''
函数cv2.add()参数示意:
def add(src1, src2, dst=None, mask=None, dtype=None): # real signature unknown; restored from __doc__
"""
add(src1, src2[, dst[, mask[, dtype]]]) -> dst
. @brief Calculates the per-element sum of two arrays or an array and a scalar.
.
. The function add calculates:
. - Sum of two arrays when both input arrays have the same size and the same number of channels:
. \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2}(I)) \quad \texttt{if mask}(I) \ne0\f]
. - Sum of an array and a scalar when src2 is constructed from Scalar or has the same number of
. elements as `src1.channels()`:
. \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1}(I) + \texttt{src2} ) \quad \texttt{if mask}(I) \ne0\f]
. - Sum of a scalar and an array when src1 is constructed from Scalar or has the same number of
. elements as `src2.channels()`:
. \f[\texttt{dst}(I) = \texttt{saturate} ( \texttt{src1} + \texttt{src2}(I) ) \quad \texttt{if mask}(I) \ne0\f]
. where `I` is a multi-dimensional index of array elements. In case of multi-channel arrays, each
. channel is processed independently.
.
. The first function in the list above can be replaced with matrix expressions:
. @code{.cpp}
. dst = src1 + src2;
. dst += src1; // equivalent to add(dst, src1, dst);
. @endcode
. The input arrays and the output array can all have the same or different depths. For example, you
. can add a 16-bit unsigned array to a 8-bit signed array and store the sum as a 32-bit
. floating-point array. Depth of the output array is determined by the dtype parameter. In the second
. and third cases above, as well as in the first case, when src1.depth() == src2.depth(), dtype can
. be set to the default -1. In this case, the output array will have the same depth as the input
. array, be it src1, src2 or both.
. @note Saturation is not applied when the output array has the depth CV_32S. You may even get
. result of an incorrect sign in the case of overflow.
. @param src1 first input array or a scalar.
. @param src2 second input array or a scalar.
. @param dst output array that has the same size and number of channels as the input array(s); the
. depth is defined by dtype or src1/src2.
. @param mask optional operation mask - 8-bit single channel array, that specifies elements of the
. output array to be changed.
. @param dtype optional depth of the output array (see the discussion below).
. @sa subtract, addWeighted, scaleAdd, Mat::convertTo
"""
pass
所以,建议在进行图像像素相加操作时候使用OpenCV add()或者OpenCV-Python cv2.add()函数会提供更好的结果。
图像融合(Image Blending):
Image Blending的方式类似Image Addition,只是在进行像素值相加的时候给与不同的权重系数,融合后的图像能够看出一种混合或透明的感觉。我们日常见到的水印技术可以采取这种方法。图像融合方式按照如下公式进行:
的取值范围处于[0 1],下面我们将两幅图像进行融合,分别给第一幅图像0.7的权重,第二幅图像0.3的权重系数。cv2.addWeighted()应用如下公式:
参数为0。
示例代码如下:
import cv2
img1 = cv2.imread('./data/ml.png')
img2 = cv2.imread('./data/opencv_logo.jpg')
dst = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
cv2.imshow('dst', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数cv2.addWeighted()示意:
def addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None): # real signature unknown; restored from __doc__
"""
addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) -> dst
. @brief Calculates the weighted sum of two arrays.
.
. The function addWeighted calculates the weighted sum of two arrays as follows:
. \f[\texttt{dst} (I)= \texttt{saturate} ( \texttt{src1} (I)* \texttt{alpha} + \texttt{src2} (I)* \texttt{beta} + \texttt{gamma} )\f]
. where I is a multi-dimensional index of array elements. In case of multi-channel arrays, each
. channel is processed independently.
. The function can be replaced with a matrix expression:
. @code{.cpp}
. dst = src1*alpha + src2*beta + gamma;
. @endcode
. @note Saturation is not applied when the output array has the depth CV_32S. You may even get
. result of an incorrect sign in the case of overflow.
. @param src1 first input array.
. @param alpha weight of the first array elements.
. @param src2 second input array of the same size and channel number as src1.
. @param beta weight of the second array elements.
. @param gamma scalar added to each sum.
. @param dst output array that has the same size and number of channels as the input arrays.
. @param dtype optional depth of the output array; when both input arrays have the same depth, dtype
. can be set to -1, which will be equivalent to src1.depth().
. @sa add, subtract, scaleAdd, Mat::convertTo
"""
pass
Image Blending融合结果:
将要融合的两幅图像:
图像融合后的结果:
cv2.add()与函数cv2.addWeighted()函数针对待融合图像的大小、图像深度属性需要一致。在这里图像融合技术可以将图像中信息进行加权融合,例如日常生活中使用较多的水印技术,同时去水印技术也是一项功能,关于去水印技术后期会考虑使用OpenCV中的Inpainting技术。
图像位运算(Bitwise Operations):
图像位运算操作包括:与、或、非、异或操作。这些算术操作在提取图像中的任意形状感兴趣区域ROI都会发出非常强大的作用。下面将会有一个简单的示例演示如何更改图像特定区域的示例。
例如:假设我想把OpenCV的标志图像放在图像的上面。如果使用上述Image Addition功能,它会改变颜色。如果我使用Image Blending功能,将会得到一个透明的效果。但是,并不希望它是透明的。如果是矩形区域,可以采取使用ROI,但是OpenCV的logo并不是矩形的。
所以采用如下的位操作运算:
示例代码如下:
import cv2
# Load two images
img1 = cv2.imread('./data/messi5.jpg')
img2 = cv2.imread('./data/opencv_logo.png')
# I want to put logo on top-left corner, So I create a ROI
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]
# Now create a mask of logo and create its inverse mask also
img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
# inverse the image_binary
mask_inv = cv2.bitwise_not(mask)
# Now black-out the area of logo in ROI
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
# Take only region of logo from logo image.
img2_fg = cv2.bitwise_and(img2, img2, mask=mask)
# Put logo in ROI and modify the main image
dst = cv2.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst
cv2.imshow('res', img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
位运算原始图:
位运算结果示例图:
参考