OpenCV实战 | 噪声生成与图像加噪声

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

引子

2020年第一篇技术文章,写点有意思的,图像噪声有美感的!

噪声图像生成

随机噪声

 

首先看两张图片,大小均为512* 512个像素, 第一张是纯蓝色

72b84ede1db7e2ec8502b46d6459fa6a.png

第二张是加有随机噪声的蓝色

9dd5cfcd97bab5febcbf7b56ae8fb779.jpeg

产生随机噪声的算法简单的不能再简单了

加速RGB图像的RED与GREEN通道数据为零,蓝色通道通过0~255范围之间随机数生成即可得到,代码演示如下:

1Mat src = Mat::zeros(Size(512, 512), CV_8UC3);
 2src = Scalar(255, 0, 0);
 3imshow("input", src);
 4imwrite("D:/blue.png", src);
 5// noise with blue
 6int w = src.cols;
 7int h = src.rows;
 8for (int row = 0; row < h; row++) {
 9    for (int col = 0; col < w; col++) {
10        int pv = 255 * rand() / (RAND_MAX + 1);
11        src.at<Vec3b>(row, col)[0] = pv;
12    }
13}
14imshow("random noise", src);

其中rand()是C++的随机函数,最大值为RAND_MAX,要得到0~1之间的随机值生成可以表示为:rand()/(RAND_MAX + 1), 如要要0~255范围之间则表示像素值 pixel = 255*rand()/(RAND_MAX + 1)。

如何给一张已经有的图像加上噪声,很容易,OpenCV提供了一个高斯分别随机数生成的函数:

1void cv::randn(
2    InputOutputArray dst,    
3    InputArray mean,    
4    InputArray stddev     
5)

dst:表示输入的Mat对象,同时也是输出

mean:表示分布的均值

stddev:表示标准方差

给图像添加高斯噪声的代码如下:

1Mat image = imread("D:/images/test.png");
2imshow("image", image);
3Mat noiseAdd = Mat::zeros(image.size(), image.type());
4randn(noiseAdd, (15, 15, 15), (30, 30, 30));
5add(image, noiseAdd, image);
6imshow("noiseAdd", image);

运行结果如下:

 

e721018d21326c2e045518f0bef41a67.jpeg

更好玩的噪声生成

你没看错,噪声有时候也可以很美的,很好玩的,请看下面这张图,也是基于噪声生成的。

2c5505d614bd4fa3f3652118020f7646.jpeg

前面生成噪声的方法都太过简单粗暴,都是线性计算,这里我们希望噪声可以周期性的变化,有一定的规律呈现,同时符合人眼的感官视觉变化曲线,不会觉得那么生硬。所以我们需要一个周期性函数,这里选择cos,在[0, PI]区间递减,在[PI, 2PI]区间递增,取值范围在[-1, 1]之间。但是我们像素值在0~255之间,缩放随机数可以取值范围为0~1之间,生成的浮点数坐标采样线性插值,所以我们需要cos(PI+(x-x0/x1-x0) * PI) + 1, 现在计算出来的值是[0, 1]区间之内 根据插值公式最终有:

y = (y1-y0) * cos(PI + (x-x0/x1-x0) * PI) + 1 + y0

其中[x, y]代表要计算的点,周围四个采样点为:

[x-N, y-N], [x+N, y-N], [x-N, y+N], [x+N, y+N ]

运用双线性插值原理即可计算出[1, N]个每个像素点的值。其中N表示变化周期。

线性插值代码如下:

1double interpolate(double x0, double xx0, double x1, double xx1, double x) {
2    return (1.0 + cos(CV_PI +(CV_PI / (x1 - x0)) * (x - x0))) / 2.0 * (xx1 - xx0) + xx0;
3}

随机噪声可以预先计算,然后根据坐标位置直接查询即可,这样可以减少计算量,代码实现如下:

1// 初始化噪声随机数
 2for (int i = 0; i< sum; i++) {
 3    blue_random[i] = ((float)rand()) / (float)(RAND_MAX + 1);
 4    red_random[i] = ((float)rand()) /(float) (RAND_MAX + 1);
 5    green_random[i] = ((float)rand()) / (float)(RAND_MAX + 1);
 6}
 7
 8// 查询获取噪声
 9double noise(int x, int y, int colorType) {
10    if (colorType == 1) {
11        if (x < s && y < s)
12            return red_random[y * s + x];
13        else
14            return 0.0;
15    }
16    else if (colorType == 2) {
17        if (x < s && y < s)
18            return green_random[y * s + x];
19        else
20            return 0.0;
21    }
22    else {
23        if (x < s && y < s)
24            return blue_random[y * s + x];
25        else
26            return 0.0;
27    }
28}

获取每个坐标颜色代码如下:

1double getColor(int x, int y, int M, int color_type) {
 2    int x0 = x - (x % M);
 3    int x1 = x0 + M;
 4    int y0 = y - (y % M);
 5    int y1 = y0 + M;
 6        // 获取噪声
 7    double x0y0 = noise(x0, y0, color_type);
 8    double x1y0 = noise(x1, y0, color_type);
 9    double x0y1 = noise(x0, y1, color_type);
10    double x1y1 = noise(x1, y1, color_type);
11        // 双线性插值
12    double xx0 = interpolate(x0, x0y0, x1, x1y0, x);
13    double xx1 = interpolate(x0, x0y1, x1, x1y1, x);
14    double N = interpolate(y0, xx0, y1, xx1, y);
15    return N;
16}

完整的代码调用如下:

1// add art noise
 2Mat noise_img = Mat::zeros(Size(s, s), CV_8UC3);
 3int intervalPixels = 50; // default
 4w = noise_img.cols;
 5h = noise_img.rows;
 6for (int row = 0; row < h; row++) {
 7    for (int col = 0; col < w; col++) {
 8        // set random color value for each pixel
 9        r = (int)(255.0 * getColor(row, col, intervalPixels, 1));
10        g = (int)(255.0 * getColor(row, col, intervalPixels, 2));
11        b = (int)(255.0 * getColor(row, col, intervalPixels, 4));
12        noise_img.at<Vec3b>(row, col)[0] = b;
13        noise_img.at<Vec3b>(row, col)[1] = g;
14        noise_img.at<Vec3b>(row, col)[2] = r;
15    }
16}
17imshow("art noise", noise_img);

可以选择变化周期与三个通道值,会生成各种颜色的噪声。更多测试结果如下:

34de663650d64ca623dddc5c90daf470.png

13f7e5887fb85f57bf682f1a85fe92e2.jpeg

叠加一下看看如下:

5939effa1528735737f55da470086cd2.jpeg

效果魔幻不/?原来噪声也可以这么玩!

 
 

好消息!

小白学视觉知识星球

开始面向外开放啦👇👇👇

 
 

0d0862904eac0956ade4d0c6df05695b.jpeg

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。


下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。


下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值