迪文科技论坛

 找回密码
 立即注册
搜索
查看: 132|回复: 0

【2023.5.20获奖项目】基于迪文屏的智能眼方案

[复制链接]

567

主题

167

回帖

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11978
发表于 2024-1-11 09:52:57 | 显示全部楼层 |阅读模式
【开源】基于迪文屏的智能眼方案


该方案是基于迪文屏设计的模拟人眼跟随运动的智能眼例程。工程师使用几张人眼图片素材,实现了眼珠运动、眨眼、人脸识别和跟随等功能。


一、介绍

其实这个智能在做雷达设计的时候已经在着手了,但是由于素材紧缺,关于眼睛的素材网上比较少,只能自己去P,也是现学现卖,做出来的效果还是可以的,也加入了AI(人脸识别)的元素。


二、设计

首先是素材,我先晒一下素材,因为这次设计素材花的时间也比较多,比如眨眼的动画,以及眼球+眼白的血丝,这里分享给大家,大家在后面的开源文件自取。

之后就是页面的设计,页面设计还是比较简单的,因为就是两张图形控件,如下图所示。

首先要设计眨眼,眨眼的话,就是隔一段时间让眼皮的图片轮流显示一下,这里我是这么进行设计的。

  1. //眨眼动画
  2. void blink_animat(void)
  3. {
  4.     if(blink_flag == 0)
  5.     {
  6.         blink_cnt++;
  7.         if(blink_cnt >= 4)
  8.         {
  9.             blink_flag = 1;
  10.         }
  11.     }
  12.     else
  13.     {
  14.         blink_cnt--;
  15.         if(blink_cnt <= 0)
  16.         {
  17.             blink_flag = 0;
  18.         }
  19.     }
  20.    
  21.     write_dgus_vp(0x3000, (u8 *)&blink_cnt, 2);
  22. }

  23. void blink_run()
  24. {
  25.     static u32 run_timer_cnt = 0;
  26.     run_timer_cnt++;
  27.     if(run_timer_cnt >= 2000000)
  28.     {
  29.         run_timer_cnt = 0;
  30.         blink_animat();
  31.         Delay_ms(30);
  32.         blink_animat();
  33.         Delay_ms(30);
  34.         blink_animat();
  35.         Delay_ms(30);
  36.         blink_animat();
  37.         Delay_ms(30);
  38.         blink_animat();
  39.         Delay_ms(30);
  40.         blink_animat();
  41.         Delay_ms(30);
  42.         blink_animat();
  43.         Delay_ms(30);
  44.         blink_animat();
  45.         Delay_ms(30);   
  46.     }
  47. }
复制代码

眨眼动画看起来还是很简单的,接下来就是眼珠自然左右看,这里设计和眨眼类似,但是需要比较晶振的控制眼球运动的时间,这里经过多次调试,我设计出了下面这套代码。

  1. //眼珠动画
  2. void eyeball_animat(void)
  3. {
  4.     eyeball_timer_cnt++;

  5.     if(eyeball_timer_cnt < 50)
  6.     {
  7.         eyeball_cnt = 20;
  8.     }
  9.     else if(eyeball_timer_cnt < 51)
  10.     {
  11.         eyeball_cnt = 50;
  12.     }
  13.     else if(eyeball_timer_cnt < 52)
  14.     {
  15.         eyeball_cnt = 80;
  16.     }
  17.     else if(eyeball_timer_cnt < 53)
  18.     {
  19.         eyeball_cnt = 94;
  20.     }
  21.     else if(eyeball_timer_cnt < 103)
  22.     {
  23.         eyeball_cnt = 94;
  24.     }
  25.     else if(eyeball_timer_cnt < 104)
  26.     {
  27.         eyeball_cnt = 80;
  28.     }
  29.     else if(eyeball_timer_cnt < 105)
  30.     {
  31.         eyeball_cnt = 50;
  32.     }
  33.     else if(eyeball_timer_cnt < 106)
  34.     {
  35.         eyeball_cnt = 20;
  36.     }
  37.     else if(eyeball_timer_cnt < 107)
  38.     {
  39.         eyeball_cnt = -10;
  40.     }
  41.     else if(eyeball_timer_cnt < 108)
  42.     {
  43.         eyeball_cnt = -40;
  44.     }
  45.     else if(eyeball_timer_cnt < 158)
  46.     {
  47.         eyeball_cnt = -54;
  48.     }
  49.     else if(eyeball_timer_cnt < 159)
  50.     {
  51.         eyeball_cnt = -40;
  52.     }
  53.     else if(eyeball_timer_cnt < 160)
  54.     {
  55.         eyeball_cnt = -10;
  56.     }
  57.     else if(eyeball_timer_cnt < 161)
  58.     {
  59.         eyeball_cnt = 20;
  60.         eyeball_timer_cnt = 0;
  61.     }
  62.     //左右移动
  63. //    if(eyeball_flag == 0)
  64. //    {
  65. //        eyeball_cnt++;
  66. //        if(eyeball_cnt >= 94)
  67. //        {
  68. //            eyeball_flag = 1;
  69. //        }
  70. //    }
  71. //    else
  72. //    {
  73. //        eyeball_cnt--;
  74. //        if(eyeball_cnt <= -54)
  75. //        {
  76. //            eyeball_flag = 0;
  77. //        }
  78. //    }

  79.     if(eyeball_cnt >= 0)
  80.     {
  81.         eyeball_pos[0] = 0x00;
  82.         eyeball_pos[1] = eyeball_cnt;
  83.     }
  84.     else
  85.     {
  86.         eyeball_pos[0] = 0xFF;
  87.         eyeball_pos[1] = (eyeball_cnt & 0xFF);
  88.     }
  89.    
  90.    
  91.     write_dgus_vp(0x3111, (u8 *)&eyeball_pos, 2);
  92. }

  93. void eyeball_run()
  94. {
  95.     static u32 run_timer_cnt = 0;
  96.     run_timer_cnt++;
  97.     if(run_timer_cnt >= 20000)
  98.     {
  99.         run_timer_cnt = 0;
  100.         eyeball_animat();
  101.     }
  102. }
复制代码

这样其实就完成了一个Demo,但是我觉得还是不够的,因为眼睛光自己动怎么行,所以我就加入的ESP32去识别人脸,然后眼珠跟着人脸进行运动,需要做的处理就是,检测到人脸的时候,眼睛就不能自己运动了,这里我就定义了一个变量在while循环中自增,当自增到一定数值时,眼珠就自己运动,当串口收到数据时,这个变量就清理,然后只根据人脸的位置进行眼睛的移动。主要代码如下。

  1. if(rec_data_timer_cnt < 1000000)
  2.         {
  3.             rec_data_timer_cnt++;
  4.         }
  5.         else
  6.         {
  7.             eyeball_run();
  8.         }
复制代码
  1. extern u32 rec_data_timer_cnt;
  2. extern u16 eyeball_timer_cnt;
  3. void Communication_CMD(u8 st)
  4. {
  5.         if((uart[st].Rx_F==1 )&&(uart[st].Rx_T==0))
  6.     {
  7.         rec_data_timer_cnt = 0;
  8.         eyeball_timer_cnt = 0;                                                        
  9. #if(Type_Communication==1)               
  10.         Describe_8283(st);
  11. #elif(Type_Communication==2)               
  12.         Describe_Modbus(st);
  13. #endif                                       
  14.         uart[st].Rx_F=0;
  15.         uart[st].Rx_Num=0;
  16.     }
  17. }
复制代码

然后我还设计了3D外壳,让整个Demo更好看,整体效果如下图所示。




三、总结

这次设计主要是基于圆形屏想出来的,因为眼睛是圆的,屏幕也是圆的,刚好就可以做一个这样的设计。

演示视频:https://www.bilibili.com/video/BV1ga4y1g7CX/



备注说明:如需源码,请参考此链接:http://inforum.dwin.com.cn:20080/forum.php?mod=viewthread&tid=8175&_dsign=a85a29ac


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2024-11-24 09:13 , Processed in 0.079817 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表