LED阵列动态随机显示效果,把随机过程改成马尔科夫链的方式。

[复制链接]
 楼主| keer_zu 发表于 2025-5-22 13:47 | 显示全部楼层 |阅读模式



改过后如下代码:
  1. // 马尔科夫链状态结构体(修正字段类型)
  2. struct MarkovState {
  3.   uint8_t baseHue;     // 改为8位存储
  4.   uint8_t speed;       // 速度范围1-5
  5.   int8_t direction;    // 风向
  6.   uint8_t intensity;   // 强度范围
  7. };

  8. // 初始化状态(调整参数)
  9. MarkovState currentState = {200, 3, 1, 150}; // 提高初始baseHue

  10. // 简化转移概率矩阵
  11. const uint8_t transitionProb[4][4] = {
  12.   {80, 10, 5, 5},   
  13.   {15, 70, 10, 5},  
  14.   {10, 5, 80, 5},  
  15.   {5, 5, 5, 85}   
  16. };

  17. // 噪声参数
  18. uint16_t z = 0;
  19. const uint8_t scale = 30;
  20. const uint8_t blurAmount = 64;


  21. // 马尔科夫状态转移实现
  22. void applyMarkovTransition() {
  23.   uint8_t randVal = random8();
  24.   uint8_t probSum = 0;
  25.   
  26.   // 选择要改变的状态维度
  27.   uint8_t targetDim = 0;
  28.   for(; targetDim<4; targetDim++) {
  29.     probSum += transitionProb[targetDim][targetDim];
  30.     if(randVal < probSum) break;
  31.   }
  32.   
  33.   // 执行状态转移(有限差分法)
  34.   switch(targetDim) {
  35.     case 0: // 基础色调变化
  36.       currentState.baseHue += random8(3) - 1; // ±1微调
  37.       currentState.baseHue = constrain(currentState.baseHue, 180, 255);
  38.       break;
  39.       
  40.     case 1: // 速度变化
  41.       currentState.speed = constrain(
  42.         currentState.speed + random8(3) - 1, 1, 5);
  43.       break;
  44.       
  45.     case 2: // 方向变化
  46.       if(random8() < 30) currentState.direction *= -1;
  47.       break;
  48.       
  49.     case 3: // 强度变化
  50.       currentState.intensity = constrain(
  51.         currentState.intensity + random8(21) - 10, 100, 200);
  52.       break;
  53.   }
  54. }

  55. // 基于状态的图案生成
  56. void generateWindPattern() {
  57.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
  58.     for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
  59.       uint8_t noise = inoise8(
  60.         (x * scale) / 2 + (currentState.direction * z),
  61.         y * scale + z/2,
  62.         currentState.intensity * 10
  63.       );
  64.       
  65.       // 修正色调计算(添加循环处理)
  66.       uint8_t hue = currentState.baseHue + map(noise, 0,255, -20,20);
  67.       hue = (hue < 180) ? hue + 75 : hue; // 确保在180-255范围
  68.       
  69.       // 修正亮度计算(移除错误处理)
  70.       uint8_t val = map(noise, 50, 205, 30, 230);
  71.       val = constrain(val, 30, 230); // 硬约束
  72.       
  73.       leds[XY(x,y)] = CHSV(hue, 230, val);
  74.     }
  75.   }
  76.   
  77.   blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, blurAmount);
  78.   z += currentState.speed;
  79. }



  80. void wind_vision() {
  81.   static uint32_t lastUpdate = 0;
  82.   static uint8_t hueShift = 0;

  83.   if(millis() - lastUpdate > 50) { // 降低更新频率
  84.     lastUpdate = millis();
  85.    
  86.     // 马尔科夫状态转移
  87.     applyMarkovTransition();
  88.    
  89.     // 生成动态风场
  90.     generateWindPattern();
  91.    
  92.     FastLED.show();
  93.   }
  94. }


 楼主| keer_zu 发表于 2025-5-22 15:44 | 显示全部楼层
修正后,虽然不再不连续的画面跳变,连续了,但是很碎片化

  1. // 马尔科夫链增强平滑版本
  2. struct MarkovState {
  3.   uint8_t baseHue;     // 当前色相
  4.   uint8_t targetHue;   // 目标色相(新增)
  5.   uint8_t speed;
  6.   uint8_t targetSpeed; // 新增目标速度
  7.   int8_t direction;
  8.   float directionF;    // 新增浮点方向(用于平滑过渡)
  9.   uint8_t intensity;
  10. };

  11. MarkovState currentState = {200, 200, 3, 3, 1, 1.0f, 150};
  12. const uint8_t transitionProb[4][4] = {
  13.   {90, 5, 3, 2},     // 提高保持色相的概率
  14.   {10, 85, 3, 2},    // 降低速度变化频率
  15.   {5, 5, 88, 2},     // 增强方向稳定性
  16.   {3, 2, 2, 93}      // 提高强度保持率
  17. };

  18. uint32_t z = 0;       // 改为32位防溢出
  19. const float DIRECTION_TRANSITION = 0.1f; // 方向过渡系数

  20. void applyMarkovTransition() {
  21.   static uint32_t lastChange = 0;
  22.   const uint32_t CHANGE_INTERVAL = 3000; // 延长状态变化间隔
  23.   
  24.   if(millis() - lastChange < CHANGE_INTERVAL) return;
  25.   lastChange = millis();

  26.   uint8_t randVal = random8();
  27.   uint8_t probSum = 0;
  28.   uint8_t targetDim = 0;
  29.   
  30.   // 概率累计方式优化
  31.   while(targetDim < 4 && randVal > (probSum += transitionProb[targetDim][targetDim])) {
  32.     targetDim++;
  33.   }

  34.   // 有限渐变状态转移
  35.   switch(targetDim) {
  36.     case 0: // 色相渐变
  37.       currentState.targetHue = constrain(currentState.baseHue + random8(-8, 9), 180, 255);
  38.       break;
  39.       
  40.     case 1: // 速度渐变
  41.       currentState.targetSpeed = constrain(currentState.speed + random8(-1, 2), 1, 5);
  42.       break;
  43.       
  44.     case 2: // 方向平滑过渡
  45.       currentState.directionF = -currentState.directionF; // 缓慢反转
  46.       break;
  47.       
  48.     case 3: // 强度渐变
  49.       currentState.intensity = constrain(currentState.intensity + random8(-8, 9), 100, 200);
  50.       break;
  51.   }
  52. }

  53. void smoothUpdateStates() {
  54.   // 色相线性插值
  55.   currentState.baseHue = lerp8by8(currentState.baseHue, currentState.targetHue, 10);
  56.   
  57.   // 速度指数平滑
  58.   currentState.speed = (currentState.speed * 7 + currentState.targetSpeed * 1) / 8;
  59.   
  60.   // 方向浮点过渡
  61.   currentState.directionF += (currentState.direction - currentState.directionF) * DIRECTION_TRANSITION;
  62. }

  63. void generateWindPattern() {
  64.   const float dirFactor = currentState.directionF; // 使用浮点方向因子


  65.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
  66.     for(uint8_t x=0; x<MATRIX_WIDTH; x++) {
  67.       // 改进的噪声参数(增加Z轴细分)
  68.       uint8_t noise = inoise8(
  69.         (x * 25) + (z * dirFactor * 0.7f),
  70.         y * 35 + z * 0.3f,
  71.         currentState.intensity * 8 + (z >> 6)
  72.       );
  73.       
  74.       // 循环色相映射(替代硬约束)
  75.       uint8_t hue = currentState.baseHue + map(noise, 0,255, -15,15);
  76.       hue = 180 + ((hue - 180) % 76); // 180-255循环
  77.       
  78.       // 亮度S曲线处理
  79.       uint8_t val = cubicwave8(noise);
  80.       val = map(val, 30, 225, 50, 220);  // 压缩两端
  81.       
  82.       leds[XY(x,y)] = CHSV(hue, 235, val);
  83.     }
  84.   }
  85.   
  86.    // 使用标准二维模糊 + 逐行模糊替代方案
  87.   blur2d(leds, MATRIX_WIDTH, MATRIX_HEIGHT, 64);
  88.   
  89.   // 手动实现行模糊
  90.   for(uint8_t y=0; y<MATRIX_HEIGHT; y++) {
  91.     CRGB* rowStart = &leds[XY(0, y)];
  92.     blur1d(rowStart, MATRIX_WIDTH, 32);
  93.   }
  94.   
  95.   z += currentState.speed;
  96. }

  97. void wind_vision() {
  98.   static uint32_t lastUpdate = 0;
  99.   
  100.   if(millis() - lastUpdate > 33) { // 30FPS
  101.     lastUpdate = millis();
  102.    
  103.     smoothUpdateStates();  // 先更新状态
  104.     applyMarkovTransition();
  105.     generateWindPattern();
  106.    
  107.     // 添加残影效果
  108.     fadeToBlackBy(leds, NUM_LEDS, 220);
  109.     FastLED.show();
  110.   }
  111. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1477

主题

12909

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部