图像添加(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,只是在进行像素值相加的时候给与不同的权重系数,融合后的图像能够看出一种混合或透明的感觉。我们日常见到的水印技术可以采取这种方法。图像融合方式按照如下公式进行:

python add_ Pythonadd image_python add_

python add_ Pythonadd image_add()_02的取值范围处于[0 1],下面我们将两幅图像进行融合,分别给第一幅图像0.7的权重,第二幅图像0.3的权重系数。cv2.addWeighted()应用如下公式:

python add_ Pythonadd image_图像融合_03

python add_ Pythonadd image_addWeighted()_04参数为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融合结果:

将要融合的两幅图像:



python add_ Pythonadd image_add()_05

python add_ Pythonadd image_add()_06


图像融合后的结果:



python add_ Pythonadd image_python add__07


  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()

位运算原始图:



python add_ Pythonadd image_add()_08

python add_ Pythonadd image_python add__09


位运算结果示例图:



python add_ Pythonadd image_python add__10


参考

https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_core/py_image_arithmetics/py_image_arithmetics.html