如何正确地将蒙版插入原始图像?
How to properly insert mask into original image?
我的目标是用圆形噪声(盐和 pepper/black 和白点)覆盖一张脸,但我设法实现的只是矩形噪声。
使用这张图片:
我找到了面部坐标 (x,y,w,h) = [389, 127, 209, 209]
并使用这个 function 添加噪音
喜欢:
img = cv2.imread('like_this.jpg')
x,y,w,h = [389, 127, 209, 209]
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised
cv2.imshow('new', new)
从 x,y,w,h
我发现我希望我的圆在 (493, 231)
处,半径为 105
我研究过我发现了一些关于屏蔽和按位运算的东西,所以我尝试了:
mask = np.zeros(new.shape[:2], dtype='uint8')
cv2.circle(mask, (493, 231), 105, 255, -1)
new_gray = cv2.cvtColor(new, cv2.COLOR_BGR2GRAY)
masked = cv2.bitwise_and(new_gray, new_gray , mask=mask)
cv2.imshow('masked', masked)
这里,问题出现了:
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
OR = cv2.bitwise_or(masked, img_gray) # removes the black dots, idk why
cv2.imshow('bitwise - OR', OR)
黑点从噪声中移除,除此之外,我似乎无法将 OR
转换回 BGR。
也许有更好的方法。
拜托,help/guidance需要!
二进制条件下的按位运算函数在像素值为零时“关闭”像素,在像素值大于零时将其“打开”。
在你的例子中,bitwise_or“移除”了蒙版的黑色背景和噪声的黑点。
我建议这样做:
# Read image
img = cv2.imread('like_this.jpg')
x,y,w,h = [389, 127, 209, 209]
# Add squared noise
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised
# Transform the image to graylevel
new_gray = cv2.cvtColor(new, cv2.COLOR_BGR2GRAY)
# Create a mask in which black noise is equal to 0 and white to 2
mask = np.zeros(new.shape[:2], dtype='uint8')
mask[new_gray==0] = 1
mask[new_gray==255] = 2
# Mask the previous mask with a circle
circle = np.zeros(new.shape[:2], dtype='uint8')
circle = cv2.circle(circle, (493, 231), 105, 1, -1)
mask = mask * circle
plt.imshow(mask)
plt.show()
# Join the mask adding the noise to the image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray[mask==1] = 0
gray[mask==2] = 255
cv2.imshow('Result', gray)
cv2.waitKey(0)
希望有用。如果您需要更多帮助,请告诉我。
所以问题是如何使用掩码。有两个选项,numpy
和 OpenCV.
numpy
由于您将噪声区域复制到结果中,现在想要恢复圆之外的所有内容,我将使用mask == 0
获得一个布尔数组圈外处处为真
使用 numpy,布尔数组可以用作索引。结果是一个“视图”,它的行为就像一个切片。通过它的操作会影响原始数据。
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised # whole rectangle affected
new[mask == 0] = img[mask == 0] # restore everything outside of the circle
所有三个数组 (mask, new, img
) 需要具有相同的形状。
OpenCV,掩码
与 Python 和 numpy 无关,但它的许多 C++ API 都采用可选的 mask
参数来修改该函数的操作。 Mat::copyTo()
就是这样一种方法。
OpenCV,按位运算
通过按位运算,掩码将不再只是将每个像素标记为真或假,但它必须是 3 通道并且每个值的所有八位都计数,因此它必须仅包含 0 和 255 ( 0xFF).
我会先擦除圆圈外的所有内容,然后添加回到圆圈外的源部分。两个操作都使用 bitwise_and
。需要两个操作,因为按位操作不能只是“覆盖”。它们对两个操作数都有反应。我还将使用 numpy 的 ~
运算符按位取反掩码。
bitwise_mask = cv.cvtColor(mask, cv.COLOR_GRAY2BGR) # blow it up
new = cv.bitwise_and(new, bitwise_mask)
new += cv.bitwise_and(img, ~bitwise_mask)
我的目标是用圆形噪声(盐和 pepper/black 和白点)覆盖一张脸,但我设法实现的只是矩形噪声。
使用这张图片:
我找到了面部坐标 (x,y,w,h) = [389, 127, 209, 209]
并使用这个 function 添加噪音
喜欢:
img = cv2.imread('like_this.jpg')
x,y,w,h = [389, 127, 209, 209]
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised
cv2.imshow('new', new)
从 x,y,w,h
我发现我希望我的圆在 (493, 231)
处,半径为 105
我研究过我发现了一些关于屏蔽和按位运算的东西,所以我尝试了:
mask = np.zeros(new.shape[:2], dtype='uint8')
cv2.circle(mask, (493, 231), 105, 255, -1)
new_gray = cv2.cvtColor(new, cv2.COLOR_BGR2GRAY)
masked = cv2.bitwise_and(new_gray, new_gray , mask=mask)
cv2.imshow('masked', masked)
这里,问题出现了:
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
OR = cv2.bitwise_or(masked, img_gray) # removes the black dots, idk why
cv2.imshow('bitwise - OR', OR)
黑点从噪声中移除,除此之外,我似乎无法将 OR
转换回 BGR。
也许有更好的方法。
拜托,help/guidance需要!
二进制条件下的按位运算函数在像素值为零时“关闭”像素,在像素值大于零时将其“打开”。
在你的例子中,bitwise_or“移除”了蒙版的黑色背景和噪声的黑点。
我建议这样做:
# Read image
img = cv2.imread('like_this.jpg')
x,y,w,h = [389, 127, 209, 209]
# Add squared noise
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised
# Transform the image to graylevel
new_gray = cv2.cvtColor(new, cv2.COLOR_BGR2GRAY)
# Create a mask in which black noise is equal to 0 and white to 2
mask = np.zeros(new.shape[:2], dtype='uint8')
mask[new_gray==0] = 1
mask[new_gray==255] = 2
# Mask the previous mask with a circle
circle = np.zeros(new.shape[:2], dtype='uint8')
circle = cv2.circle(circle, (493, 231), 105, 1, -1)
mask = mask * circle
plt.imshow(mask)
plt.show()
# Join the mask adding the noise to the image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray[mask==1] = 0
gray[mask==2] = 255
cv2.imshow('Result', gray)
cv2.waitKey(0)
希望有用。如果您需要更多帮助,请告诉我。
所以问题是如何使用掩码。有两个选项,numpy
和 OpenCV.
numpy
由于您将噪声区域复制到结果中,现在想要恢复圆之外的所有内容,我将使用mask == 0
获得一个布尔数组圈外处处为真
使用 numpy,布尔数组可以用作索引。结果是一个“视图”,它的行为就像一个切片。通过它的操作会影响原始数据。
noised = add_noise(img[y:y+h,x:x+w])
new = img.copy()
new[y:y+h,x:x+w] = noised # whole rectangle affected
new[mask == 0] = img[mask == 0] # restore everything outside of the circle
所有三个数组 (mask, new, img
) 需要具有相同的形状。
OpenCV,掩码
与 Python 和 numpy 无关,但它的许多 C++ API 都采用可选的 mask
参数来修改该函数的操作。 Mat::copyTo()
就是这样一种方法。
OpenCV,按位运算
通过按位运算,掩码将不再只是将每个像素标记为真或假,但它必须是 3 通道并且每个值的所有八位都计数,因此它必须仅包含 0 和 255 ( 0xFF).
我会先擦除圆圈外的所有内容,然后添加回到圆圈外的源部分。两个操作都使用 bitwise_and
。需要两个操作,因为按位操作不能只是“覆盖”。它们对两个操作数都有反应。我还将使用 numpy 的 ~
运算符按位取反掩码。
bitwise_mask = cv.cvtColor(mask, cv.COLOR_GRAY2BGR) # blow it up
new = cv.bitwise_and(new, bitwise_mask)
new += cv.bitwise_and(img, ~bitwise_mask)