柏林噪声C++

柏林噪声

随机噪声
在这里插入图片描述
如上图所示随机噪声没有任何规律可言,我们希望生成有一些意义的局部连续的随机图案

一维柏林噪声

在这里插入图片描述

假设希望生成一段局部连续的随机曲线,可以采用插值的方式:在固定点随机分配y值(一般是整数点),其他的点使用插值算法

方法一:线性插值的方式

公式如下:
在这里插入图片描述
【数字图像处理】二维(2D)线性插值的应用
y = a*y1 + (1-a)*y2

我们画图看看:
在这里插入图片描述

import math
import numpy as np
import matplotlib.pyplot as pltperm = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]def perlin1D(x):# 整数x1和x2的坐标x1 = math.floor(x)x2 = x1 + 1# x1和x2的梯度值grad1 = perm[x1 % 255] * 2.0 - 255.0grad2 = perm[x2 % 255] * 2.0 - 255.0#x1和x2指向x的方向向量vec1 = x - x1vec2 = x - x2# x到x1的距离即vec1,利用公式3计算平滑参数t = 3 * pow(vec1, 2) - 2 * pow(vec1, 3)#梯度值与方向向量的乘积product1 = grad1 * vec1product2 = grad2 * vec2return product1 + t * (product2 - product1)def linear1D(x):# 整数x1和x2的坐标x1 = math.floor(x)x2 = x1 + 1# y值 随机数grad1 = perm[x1 % 255] * 2.0 - 255.0grad2 = perm[x2 % 255] * 2.0 - 255.0t=x - x1return grad1 + t * (grad2 - grad1)def linear1D_plus(x):# 整数x1和x2的坐标x1 = math.floor(x)x2 = x1 + 1# x1和x2的梯度值grad1 = perm[x1 % 255] * 2.0 - 255.0grad2 = perm[x2 % 255] * 2.0 - 255.0#x1和x2指向x的方向向量vec1 = x - x1vec2 = x - x2t=x - x1#梯度值与方向向量的乘积product1 = grad1 * vec1product2 = grad2 * vec2return product1 + t * (product2 - product1)def draw1D():# 绘制散点图x0=[]y0=[]for i in range(11):x0.append(i)y0.append( perm[i] * 2.0 - 255.0)plt.scatter(x0, y0,color='red')# 绘制1D的图像x = np.linspace(0, 10, 100)y = np.zeros(100)y1 = np.zeros(100)y2 = np.zeros(100)for i in range(100):y[i] = perlin1D(x[i])y1[i] = linear1D(x[i])y2[i] =linear1D_plus(x[i])# 绘制图像plt.plot(x, y,color='deepskyblue')plt.plot(x, y1,color='green')plt.plot(x, y2,color='orange')plt.show()draw1D()

线性插值

x取[0,10]这个区间,y在整数点随机取值,非整数点使用线性插值
ps 随机值使用伪随机数perm,柏林噪声在图像领域使用,颜色的取值范围是[0,255],所以perm的值也是[0,255]
上图红色的点是:整数点随机取值的结果,绿色的线是线性插值。
y = t ∗ y 2 + ( 1 − t ) ∗ y 1 = y 1 + t ( y 2 − y 1 ) y = t*y2+ (1-t)*y1 = y1 + t(y2- y1 ) y=ty2+(1t)y1=y1+t(y2y1)
t = x − x 1 t=x-x1 t=xx1

线性插值plus

我们希望它更平滑一点,如果插值点x的值y与附近点x1,x2的位置相关
所以改进上述算法:
y = t ∗ y 2 ∗ w 2 + ( 1 − t ) ∗ y 1 ∗ w 1 = y 1 ∗ w 1 + t ( y 2 ∗ w 2 − y 1 ∗ w 1 ) y = t*y2*w2 + (1-t)*y1*w1 = y1*w1 + t(y2*w2 - y1*w1 ) y=ty2w2+(1t)y1w1=y1w1+t(y2w2y1w1)
w是权重系数,也是柏林算法中的方向向量vec1 = x - x1
如图中黄色的线

柏林噪声

柏林噪声在此基础上再加强一步:
t = 3 t 2 − 2 t 3 t=3t^2 -2t^3 t=3t22t3

算法步骤:
input: x

  1. 计算周围的点:x1 , x2
  2. 计算x1 , x2 梯度 : grad1, grad2 随机取[0,255]
  3. 方向向量: (vec1 =x-x1 ;vec2 = x-x2)
  4. 梯度值与方向向量的乘积 product=grad*vec
  5. 计算系数 t=3t^2 -2t^3
  6. 插值:y = product1 + t * (product2 - product1)
    output :y

根据上述原理 可以画一个不规则的圆形

def drawCircle():#画圆形# 创建一个坐标系fig, ax = plt.subplots()# 定义圆心和半径center = (0, 0)radius = 10# 生成圆的数据theta = np.linspace(0, 2*np.pi, 100)x = radius * np.cos(theta) + center[0]y = radius * np.sin(theta) + center[1]y1 = np.zeros(100)for i in range(100):y1[i] = y[i]+ perlin1D(theta[i]*5)/255*2# 画出圆形ax.plot(x, y,color='orange')ax.plot(x, y1,color='deepskyblue')# 设置坐标轴范围ax.set_xlim([-15, 15])ax.set_ylim([-15, 15])# 显示图像plt.show()

在这里插入图片描述

二维柏林噪声

头文件

#pragma once
#include<array>
class PerlinNoise2D
{
public:PerlinNoise2D();~PerlinNoise2D();float BasePerlinNoise2D(float x , float y); //输出数值的范围应该是[-1,1]float Octave2D_01(float x, float y, int octaves, float persistence = 0.5);//输出数值的范围限定在[0,1]
private:template<typename STLIterator>inline void shuffle(STLIterator begin, STLIterator end);/*生成最大值为max的随机数*/int random(int max);/*input: 方向向量(x,y) 哈希值 hash根据哈希值可以达到随机梯度输出:随机梯度与方向向量的乘积*/inline float Grad(int hash, float x, float y);inline float Grad2(int hash, float x, float y);inline float Fade(const float t);inline float Lerp(const float a, const float b, const float t);inline float RemapClamp_01(float x);float Octave2D(float x, float y, int octaves, float persistence = 0.5);
private:std::array<int, 256> m_permutation;};

cpp

#include "PerlinNoise2D.h"
#include <random>
#include <numeric>
PerlinNoise2D::PerlinNoise2D()
{std::iota(m_permutation.begin(), m_permutation.end(), 0);shuffle(m_permutation.begin(), m_permutation.end());
}PerlinNoise2D::~PerlinNoise2D()
{}int PerlinNoise2D::random(int max)
{return (std::random_device{}() % (max)+1);
}/*
洗牌算法
*/
template<typename STLIterator>
inline void PerlinNoise2D::shuffle(STLIterator begin, STLIterator end)
{if (begin == end){return;}using difference_type = typename std::iterator_traits<STLIterator>::difference_type;for (STLIterator it = begin + 1; it < end; ++it){int n = random(static_cast<int>(it - begin));std::iter_swap(it, begin + static_cast<difference_type>(n));}}inline float PerlinNoise2D::Grad(int hash, float x, float y)
{float z = 0.34567;switch (hash & 0xF){case 0x0: return  x + y;case 0x1: return -x + y;case 0x2: return  x - y;case 0x3: return -x - y;case 0x4: return  x + z;case 0x5: return -x + z;case 0x6: return  x - z;case 0x7: return -x - z;case 0x8: return  y + z;case 0x9: return -y + z;case 0xA: return  y - z;case 0xB: return -y - z;case 0xC: return  y + x;case 0xD: return -y + z;case 0xE: return  y - x;case 0xF: return -y - z;default: return 0; // never happens}
}inline float PerlinNoise2D::Grad2(int hash, float x, float y)
{const double PI = 3.14159265359;const int numPoints = 36;hash = hash % numPoints;double angle = 2 * PI * hash / numPoints;double gradx = cos(angle);double grady = sin(angle);return gradx * x + grady*y;
}inline float PerlinNoise2D::Fade(const float t)
{return t * t * t * (t * (t * 6 - 15) + 10);
}inline float PerlinNoise2D::Lerp(const float a, const float b, const float t)
{return (a + (b - a) * t);
}
float PerlinNoise2D::BasePerlinNoise2D(float x, float y)
{//得到周围四个点int _x = std::floor(x);int _y = std::floor(y);int ix = _x & 255;int iy = _y & 255;//hash函数得到随机索引值int AA = m_permutation[(m_permutation[ix & 255] + iy) & 255];int BA = m_permutation[(m_permutation[(ix + 1) & 255] + iy) & 255];int AB = m_permutation[(m_permutation[ix & 255] + iy+1) & 255];int BB = m_permutation[(m_permutation[ix+1 & 255] + iy+1) & 255];//根据索引值 得到方向向量和随机梯度的向量积float fx = x - _x;float fy = y - _y;float g1 = Grad2(AA,fx,fy);float g2 = Grad2(BA, fx - 1, fy);float g3 = Grad2(AB, fx, fy - 1);float g4 = Grad2(BB, fx - 1, fy - 1);//插值float u = Fade(fx);float v = Fade(fy);float x1 = Lerp(g1, g2, u);float x2 = Lerp(g3, g4, u);return Lerp(x1, x2, v);
}float PerlinNoise2D::Octave2D(float x, float y, int octaves, float persistence)
{float result = 0.0;float amplitude = 1.0;for (int i = 0; i < octaves; i++){result += (BasePerlinNoise2D(x, y) * amplitude);x *= 2;y *= 2;amplitude *= persistence;}return result;
}inline float PerlinNoise2D::RemapClamp_01(float x)
{if (x <=  -1.0) {return 0.0;}else if (1.0 <= x){return 1.0;}return (x * 0.5 + 0.5);
}float PerlinNoise2D::Octave2D_01(float x, float y, int octaves, float persistence )
{return RemapClamp_01(Octave2D(x,y, octaves));
}

测试

class PerlinNoiseTest
{
public:PerlinNoiseTest() {};~PerlinNoiseTest() {};void drawImage(float frequency=4.0, int octaves=2,int width = 400, int height = 400);
};#include "PerlinNoiseTest.h"
#include "PerlinNoise2D.h"
#include <opencv2/opencv.hpp>
# include <algorithm>
#include <iostream>
using namespace cv;
void PerlinNoiseTest::drawImage(float frequency, int octaves, int width , int height )
{// 创建一个空白图像cv::Mat image(height, width, CV_8UC3, cv::Scalar(255, 255, 255));frequency = std::clamp((double)frequency, 0.1, 64.0);const double fx = (frequency / width);const double fy = (frequency / height);int maxcolor = 0;PerlinNoise2D perlin;for (std::int32_t y = 0; y <  height; ++y){for (std::int32_t x = 0; x < width; ++x){int color = 255*perlin.Octave2D_01((x * fx), (y * fy), octaves);maxcolor = max(maxcolor , color);image.at<cv::Vec3b>(y, x) = cv::Vec3b(color, color, color); // 绘制像素点}}std::cout << "maxcolor: "<< maxcolor;imshow("Generated Texture", image);imwrite("D:\\code\\noise\\image\\PerlinNoiseTest.jpg", image);waitKey(0);
}int main() {PerlinNoiseTest perlinTest;perlinTest.drawImage(20,1,400,400);}

在这里插入图片描述

参考文献

Using Perlin Noise to Generate 2D Terrain and Water
FastNoiseSIMD github
libnoise
柏林噪声
一篇文章搞懂柏林噪声算法,附代码讲解

游戏开发技术杂谈2:理解插值函数lerp

[Nature of Code] 柏林噪声
https://adrianb.io/2014/08/09/perlinnoise.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/206880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据分析实战】酒店行业华住集团门店分布与评分多维度分析

文章目录 1. 写在前面2. 数据集展示3. 多维度分析3.1 门店档次多元化&#xff1a;集团投资战略观察3.1.1 代码实现3.1.2 本人浅薄理解 3.2 门店分布&#xff1a;各省市分布概览3.2.1 代码实现3.2.2 本人浅薄理解 3.3 门店分级评分&#xff1a;服务水平的多维度观察3.3.1 代码实…

F5怎么样?从负载均衡到云原生的进阶之路

从Web时代开始至云原生时代的应用服务交付的市场&#xff0c;技术与人的变化就是关注的焦点。从单纯的Web负载均衡到复杂的企业应用交付&#xff0c;从单体应用到分布式、微服务架构&#xff0c;F5为企业技术架构更好、更优、更安全的运行做出了极大的努力。那么F5怎么样&#…

题目:分糖果(蓝桥OJ 2928)

题目描述&#xff1a; 解题思路&#xff1a; 本题采用贪心思想 图解 题解&#xff1a; #include<bits/stdc.h> using namespace std;const int N 1e6 9; char s[N];//写字符串数组的一种方法,像数组一样***int main() {int n, x;cin >> n >> x;for(int …

CSS新手入门笔记整理:元素类型相互转换

元素类型 块元素&#xff08;block&#xff09; 独占一行&#xff0c;排斥其他元素跟其位于同一行&#xff0c;包括块元素和行内元素。块元素内部可以容纳其他块元素和行内元素。可以定义 width&#xff0c;也可以定义 height。可以定义 4 个方向的 margin。 行内元素&#xf…

使用navicat(或者其他数据库管理工具)、powerdesigner导出数据字典

适合先有数据库结构&#xff0c;后需要导出数据字典的情况&#xff0c;多数在发开完成交文档或者用户有库的情况下 有条件的话推荐用powerdesigner导出&#xff0c;比较好看 如果用powerdesigner导出的注释不对&#xff0c;是因为数据库的编码不对 1、使用navicat导出 在该数…

代码随想录算法训练营第45天| 70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数

JAVA代码编写 70. 爬楼梯&#xff08;进阶版) 卡码网&#xff1a;57. 爬楼梯&#xff08;第八期模拟笔试&#xff09; 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f…

菜鸟学习日记(python)——推导式

python中的推导式是一种独特的数据处理方式&#xff0c;可以从一个数据序列去构建另一个新的数据序列的结构体。 它包括以下推导式&#xff1a; 列表&#xff08;list&#xff09;推导式字典&#xff08;dict&#xff09;推导式集合&#xff08;set&#xff09;推导式元组&am…

Multi-Cell Downlink Beamforming: Direct FP, Closed-Form FP, Weighted MMSE

这里写自定义目录标题 Direct FPClosed-Form FPthe Lagrangian functionthe Lagrange dual function: maximizing the Lagrangianthe Lagrange dual problem: minimizing the Lagrange dual functionClosed-Form FP Weighted MMSE原论文 Lagrange dual5.1.1 The Lagrangian5.1.…

阿里云服务器经济型、通用算力型、计算型、通用型、内存型实例区别及选择参考

当我们通过阿里云的活动购买云服务器会发现&#xff0c;相同配置的云服务器往往有多个不同的实例可选&#xff0c;而且价格差别也比较大&#xff0c;例如同样是4核8G的配置的云服务器&#xff0c;经济型e实例活动价格只要1500.48/1年起&#xff0c;通用算力型u1实例要1795.97/1…

nvidia安装出现7-zip crc error解决办法

解决办法&#xff1a;下载network版本&#xff0c;重新安装。&#xff08;选择自己需要的版本&#xff09; 网址&#xff1a;CUDA Toolkit 12.3 Update 1 Downloads | NVIDIA Developer 分析原因&#xff1a;local版本的安装包可能在下载过程中出现损坏。 本人尝试过全网说的…

无公网IP环境如何SSH远程连接Deepin操作系统

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

Python---time库

目录 时间获取 时间格式化 程序计时 time库包含三类函数&#xff1a; 时间获取&#xff1a;time() ctime() gmtime() 时间格式化&#xff1a;strtime() strptime() 程序计时&#xff1a;sleep() perf_counter() 下面逐一介绍&#…

H3.3K27M弥漫性中线胶质瘤的反义寡核苷酸治疗

今天给同学们分享一篇实验文章“Antisense oligonucleotide therapy for H3.3K27M diffuse midline glioma”&#xff0c;这篇文章发表在Sci Transl Med期刊上&#xff0c;影响因子为17.1。 结果解读&#xff1a; CRISPR-Cas9消耗H3.3K27M恢复了H3K27三甲基化&#xff0c;并延…

在AWS Lambda上部署标准FFmpeg工具——Docker方案

大纲 1 确定Lambda运行时环境1.1 Lambda系统、镜像、内核版本1.2 运行时1.2.1 Python1.2.2 Java 2 启动EC23 编写调用FFmpeg的代码4 生成docker镜像4.1 安装和启动Docker服务4.2 编写Dockerfile脚本4.3 生成镜像 5 推送镜像5.1 创建存储库5.2 给EC2赋予角色5.2.1 创建策略5.2.2…

【带头学C++】----- 九、类和对象 ---- 9.10 C++设计模式之单例模式设计

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️麻烦您点个关注&#xff0c;不迷路❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️ 目 录 9.10 C设计模式之单例模式设计 举例说明&#xff1a; 9.10 C设计模式之单例模式设计 看过我之前的文章的&#xff0c;简单讲解过C/Q…

遥测终端机RTU:实现远程监测和控制的重要工具

遥测终端机RTU对设备进行远程监测和控制&#xff0c;支持采集和传输数据&#xff0c;以实现对工业过程、公用事业、水文和环境的监测和管理。 遥测终端机RTU工作原理 计讯物联遥测终端机RTU通过网口、串口进行传感器/设备等现场数据采集&#xff0c;将其转换为数字信号&#xf…

高校网站建设的效果如何

高校有较高的信息承载需求、招生宣传、学校内容呈现、内部消息触达等需求&#xff0c;对高校来说&#xff0c;如今互联网深入生活各个场景&#xff0c;无论学校发展、外部拓展还是内部师生互动、通知触达等都需要完善。 除了传统传单及第三方平台展示外&#xff0c;学校构建属…

Html5响应式全开源网站建站源码系统 附带完整的搭建教程

Html5响应式全开源网站建站源码系统是基于Html5、CSS3和JavaScript等技术开发的全开源网站建站系统。它旨在为初学者和小型企业提供一套快速、简便的网站建设解决方案。该系统采用响应式设计&#xff0c;可以自适应不同设备的屏幕大小&#xff0c;提高用户体验。同时&#xff0…

Clean My Mac X2024解锁完整版本

Clean My Mac X是Mac上一款美观易用的系统优化清理工具&#xff0c;也是小编刚开始用Mac时的装机必备。垃圾需要时时清&#xff0c;电脑才能常年新。Windows的垃圾清理工具选择有很多&#xff0c;但是Mac的清理工具可选择的就很少。 今天给大家推荐大名鼎鼎的Clean My Mac X&a…

elasticsearch-head 启动教程

D:\elasticsearch-head-master>grunt server ‘grunt’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 npm install -g grunt-clinpm install