如何使用 OpenCV 在 Python 中为图像添加噪声(高斯/盐和胡椒等)[重复]
Posted
技术标签:
【中文标题】如何使用 OpenCV 在 Python 中为图像添加噪声(高斯/盐和胡椒等)[重复]【英文标题】:How to add noise (Gaussian/salt and pepper etc) to image in Python with OpenCV [duplicate] 【发布时间】:2014-05-21 04:21:52 【问题描述】:我想知道 Python 中是否存在使用 OpenCV 或任何其他 python 图像处理库向图像添加高斯或椒盐噪声的函数?例如,在 MATLAB 中存在执行相同工作的直接函数。
或者,如何使用 Python 和 OpenCV 为图像添加噪点?
【问题讨论】:
你试过搜索吗?以***.com/questions/14435632/… 为例 @Cyber 是的,我知道它们,但它们适用于 MATLAB。它们是用于在图像中添加噪声的 MATLAB 函数。但是,我的问题是在使用 python 和 opencv 时做同样的事情。 @Sanchit,Cyber 提到的问题的答案不是 Matlab 而是 OpenCV @MichaelBurdinov:对不起,我错误地查看了另一个页面(他们正在使用 MATLAB 函数)。是的,我认为可以使用这个概念(对于高斯噪声)。我试试看。 【参考方案1】:函数在图像中添加高斯、椒盐、泊松和散斑噪声
Parameters
----------
image : ndarray
Input image data. Will be converted to float.
mode : str
One of the following strings, selecting the type of noise to add:
'gauss' Gaussian-distributed additive noise.
'poisson' Poisson-distributed noise generated from the data.
's&p' Replaces random pixels with 0 or 1.
'speckle' Multiplicative noise using out = image + n*image,where
n is uniform noise with specified mean & variance.
import numpy as np
import os
import cv2
def noisy(noise_typ,image):
if noise_typ == "gauss":
row,col,ch= image.shape
mean = 0
var = 0.1
sigma = var**0.5
gauss = np.random.normal(mean,sigma,(row,col,ch))
gauss = gauss.reshape(row,col,ch)
noisy = image + gauss
return noisy
elif noise_typ == "s&p":
row,col,ch = image.shape
s_vs_p = 0.5
amount = 0.004
out = np.copy(image)
# Salt mode
num_salt = np.ceil(amount * image.size * s_vs_p)
coords = [np.random.randint(0, i - 1, int(num_salt))
for i in image.shape]
out[coords] = 1
# Pepper mode
num_pepper = np.ceil(amount* image.size * (1. - s_vs_p))
coords = [np.random.randint(0, i - 1, int(num_pepper))
for i in image.shape]
out[coords] = 0
return out
elif noise_typ == "poisson":
vals = len(np.unique(image))
vals = 2 ** np.ceil(np.log2(vals))
noisy = np.random.poisson(image * vals) / float(vals)
return noisy
elif noise_typ =="speckle":
row,col,ch = image.shape
gauss = np.random.randn(row,col,ch)
gauss = gauss.reshape(row,col,ch)
noisy = image + image * gauss
return noisy
【讨论】:
输出图片noise_img = sp_noise(image,0.05) cv2.imwrite('sp_noise.jpg', noise_img)
size 0
这种“盐和胡椒”方法分别添加到每个颜色通道。我见过的一些例子即使是彩色图像也会出现黑白斑点......这是正确的还是真实的?
s_vs_p和amount是什么意思?
对于彩色图像,在 HSV 空间中进行然后转换为 RGV 可能是有意义的
如果是 RGB,我想你应该将 1 作为盐改为 255【参考方案2】:
我不知道 Python API 中是否有任何方法。但是您可以使用这个简单的代码将椒盐噪声添加到图像中。
import numpy as np
import random
import cv2
def sp_noise(image,prob):
'''
Add salt and pepper noise to image
prob: Probability of the noise
'''
output = np.zeros(image.shape,np.uint8)
thres = 1 - prob
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = random.random()
if rdn < prob:
output[i][j] = 0
elif rdn > thres:
output[i][j] = 255
else:
output[i][j] = image[i][j]
return output
image = cv2.imread('image.jpg',0) # Only for grayscale image
noise_img = sp_noise(image,0.05)
cv2.imwrite('sp_noise.jpg', noise_img)
【讨论】:
好一个。效果很好 简单明了。谢谢。由于您使用的是 NumPy 数组,因此我建议您使用矢量化操作来提高效率。 我在这里根据这个答案实现了一个矢量化版本:gist.github.com/lucaswiman/1e877a164a69f78694f845eab45c381a 确实快得多。 你为什么用 rdn>thres 来添加盐噪声? 有什么原因会改变图像的颜色?【参考方案3】:只要看看cv2.randu() 或 cv.randn(),我猜它已经和 matlab 非常相似了。
让我们玩一会儿;):
import cv2
import numpy as np
>>> im = np.empty((5,5), np.uint8) # needs preallocated input image
>>> im
array([[248, 168, 58, 2, 1], # uninitialized memory counts as random, too ? fun ;)
[ 0, 100, 2, 0, 101],
[ 0, 0, 106, 2, 0],
[131, 2, 0, 90, 3],
[ 0, 100, 1, 0, 83]], dtype=uint8)
>>> im = np.zeros((5,5), np.uint8) # seriously now.
>>> im
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]], dtype=uint8)
>>> cv2.randn(im,(0),(99)) # normal
array([[ 0, 76, 0, 129, 0],
[ 0, 0, 0, 188, 27],
[ 0, 152, 0, 0, 0],
[ 0, 0, 134, 79, 0],
[ 0, 181, 36, 128, 0]], dtype=uint8)
>>> cv2.randu(im,(0),(99)) # uniform
array([[19, 53, 2, 86, 82],
[86, 73, 40, 64, 78],
[34, 20, 62, 80, 7],
[24, 92, 37, 60, 72],
[40, 12, 27, 33, 18]], dtype=uint8)
要将其应用于现有图像,只需在所需范围内生成噪声,然后添加它:
img = ...
noise = ...
image = img + noise
【讨论】:
执行此cv2.randn(im,(0),(99))
不会返回数组,如答案所示。它返回 NoneType 。请打印im
数组以检查随机值。 randn
也许你可以改变 dtype=np.int8 与 uint8 相比。这样,噪声也可以是负的,并且整体亮度保持大致相同。有了这个解决方案,它只会变得更亮。
我建议cv2.add(img, noise)
因为img+noise
会产生不良结果。这是因为 opencv 将 250+10
处理为 255
而 numpy 将其处理为 (250+10)%255 = 5
以上是关于如何使用 OpenCV 在 Python 中为图像添加噪声(高斯/盐和胡椒等)[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何在opencv中为图像添加边框,边框颜色必须与图像颜色相同