微信公众号:OpenCV学堂
关注获取更多计算机视觉与深度学习知识
引子
噪声图像生成
随机噪声
首先看两张图片,大小均为512* 512个像素, 第一张是纯蓝色
第二张是加有随机噪声的蓝色
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(row, col)[0] = pv;
12 }
13}
14imshow("random noise", src);
1void cv::randn(
2 InputOutputArray dst,
3 InputArray mean,
4 InputArray stddev
5)
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);
运行结果如下:
更好玩的噪声生成
你没看错,噪声有时候也可以很美的,很好玩的,请看下面这张图,也是基于噪声生成的。
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 ]
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(row, col)[0] = b;
13 noise_img.at(row, col)[1] = g;
14 noise_img.at(row, col)[2] = r;
15 }
16}
17imshow("art noise", noise_img);
可以选择变化周期与三个通道值,会生成各种颜色的噪声。更多测试结果如下:
叠加一下看看如下:
效果魔幻不/?原来噪声也可以这么玩!
推荐阅读
OpenCV4.8+YOLOv8对象检测C++推理演示
ZXING+OpenCV打造开源条码检测应用
攻略 | 学习深度学习只需要三个月的好方法
三行代码实现 TensorRT8.6 C++ 深度学习模型部署
实战 | YOLOv8+OpenCV 实现DM码定位检测与解析
对象检测边界框损失 – 从IOU到ProbIOU
初学者必看 | 学习深度学习的五个误区