Chinaunix首页 | 论坛 | 博客
  • 博客访问: 831752
  • 博文数量: 290
  • 博客积分: 511
  • 博客等级: 下士
  • 技术积分: 1590
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 13:14
文章分类

全部博文(290)

文章存档

2018年(28)

2017年(19)

2016年(8)

2015年(1)

2014年(14)

2013年(12)

2012年(22)

2011年(186)

分类:

2011-10-18 15:37:58

原文地址:图像运动检测程序 作者:luozhiyong131

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/ioctl.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9. #include <sys/select.h>
  10. #include <sys/time.h>
  11. #include <errno.h>
  12. #include <sys/wait.h>
  13. #include <string.h>
  14. #include <sys/ipc.h>
  15. #include <sys/shm.h>
  16. #include <time.h>

  17. /*
  18. 1. 检测到图像变化,报警
  19. 2. 检测到外部中断,报警
  20. 3. 3分钟能连续检测图像变化20次,则暂停2小时,2小时后在开启
  21. */
  22. /*define globe variable*/

  23. /*play_pid:当前播放的MP3子进程ID*/
  24. unsigned int play_pid = 0;

  25. /*gradchild:当前播放的MP3孙子进程ID*/
  26. unsigned int gradchild = 0;

  27. unsigned int play_flag;

  28. /*共享内存描述标记
  29. sharemem:
  30.  byte1:孙子进程ID号
  31.  byte2:是否有MP3播放标识play_flag_2
  32.  //byte3:MP3播放次数
  33. */
  34. int shmid;
  35. char *p_addr;

  36. #define PERM S_IRUSR|S_IWUSR



  37. /*报警铃声歌曲名,song1图像变化报警铃声
  38. song2外部中断报警铃声*/
  39. char *song1="11.mp3";
  40. char *song2="22.mp3";
  41. //char *song="234.mp3";



  42. /*定时器时间为3分钟*/
  43. #define THREE_ALARM 3*60
  44. /*睡眠时间为2小时*/
  45. #define SLEEP_TIME 2*60*60
  46. #define CPM_CNT 20
  47. int threemin_alarm = 1;

  48. static int con_cnt=0;
  49. int sleep_flag = 0;
  50. unsigned int time_tmp;

  51. #define max(flag) (flag) >1 ? "pic":"key"
  52. //#define DEBUG

  53. int alarm_flag;

  54. static int pic_cnt;
  55. int cnt_fd;
  56. /*计算图像变化次数,超过2次则认为有图像变化*/
  57. #define COMPARE_CNT 5


  58. /*************************************************
  59. Function name: count_pic
  60. Called by         : 函数main
  61. Parameter : void
  62. Description     : 计算图片变化数
  63. Return         : int
  64. Autor & date : ykz 10.4.25
  65. **************************************************/
  66. int count_pic(void)
  67. {
  68.     int fd,ret;
  69.     char *buf;
  70.     buf = (char *)malloc(10);

  71.     system("ls /root/motion | wc -l > count.txt");
  72.     lseek(cnt_fd, 0 ,SEEK_SET);
  73.     ret = read(cnt_fd , buf , 10);
  74.     if(ret)
  75.      ret = atoi(buf);
  76.     
  77.     free (buf);
  78.     return ret;
  79. }


  80. /*************************************************
  81. Function name: my_func_sleepalarm
  82. Called by         : 函数my_func_3alarm
  83. Parameter : sing_no
  84. Description     : 3分钟连续变化20次后,延时2小时后的唤醒函数
  85. Return         : void
  86. Autor & date : ykz 10.4.25
  87. **************************************************/
  88. void my_func_sleepalarm(int sign_no)
  89. {

  90.     if( sign_no == SIGALRM){
  91.         printf("Now sleep time finished!start a new work!\n");
  92.         /*则睡眠表示sleep_flag为0*/
  93.         sleep_flag = 0;
  94.     }//end sing_no

  95. }


  96. /*************************************************
  97. Function name: my_func_3alarm
  98. Called by         : 函数restart_caculate_play
  99. Parameter : sing_no
  100. Description     : 每隔3分钟检测图像连续变化是否超过20次
  101. Return         : void
  102. Autor & date : ykz 10.4.25
  103. **************************************************/
  104. void my_func_3alarm(int sign_no)
  105. {

  106.     if( sign_no == SIGALRM){

  107.         struct tm *p;
  108.         time_t timep;
  109.         unsigned int second;
  110.      printf("\n------------------warning------------------\n");
  111.      printf("[%s]3alarm!con_cnt=%d\n",max(alarm_flag),con_cnt);
  112.      /*判断图像运动次数是否超过20次
  113.      如果是:则系统睡眠2小时;
  114.      不是,则系统继续添加下一个3分钟的定时器*/
  115.      if( con_cnt >= CPM_CNT){
  116.          if(play_flag){
  117.          kill(play_pid,SIGKILL);
  118.             kill(gradchild,SIGKILL);
  119.             wait(NULL);
  120.          }
  121.          //sleep (1);

  122.         time(&timep);
  123.         p = localtime(&timep);
  124.         second = (p->tm_hour)*60*60 + (p->tm_min) * 60 + p->tm_sec;
  125.         time_tmp=second;

  126.          printf("Now maybe it is rainning!,system will sleep %d seconds!\n",SLEEP_TIME);
  127.          con_cnt = 0;
  128.          /*置睡眠标识sleep_flag为1*/
  129.          sleep_flag = 1;
  130.          /*系统睡眠2小时*/
  131.          if(signal(SIGALRM,my_func_sleepalarm)<0)
  132.          perror("signal");
  133.          alarm(SLEEP_TIME);
  134.      }
  135.      else{
  136.      printf("Nornal test!not rainning!\n");
  137.      con_cnt = 0;
  138.      /*添加下一个3分钟的定时器*/
  139.      if(signal(SIGALRM,my_func_3alarm)<0)
  140.          perror("signal");
  141.      alarm(THREE_ALARM);        
  142.      }

  143.      printf("\n------------------warning------------------\n");
  144.     } //end sing_no

  145. }



  146. /*************************************************
  147. Function name: play
  148. Called by         : 函数startplaymp3
  149. Parameter : void
  150. Description     : 子进程创建孙子进程播放MP3
  151. Return         : void
  152. Autor & date : ykz 10.4.2
  153. **************************************************/
  154. void play(void)
  155. {

  156.     pid_t fd;
  157.     char *c_addr;
  158.     char *song_name;
  159.     int play_flag_gradchild1=1;
  160.     int play_flag_gradchild2=2;
  161.     int i=0;

  162.         /*创建孙子进程*/
  163.         fd = fork();
  164.         if(fd == -1)
  165.         {    
  166.             perror("fork");
  167.             exit(1);
  168.         }
  169.         else if(fd == 0) /*孙子进程,播放MP3*/
  170.         {

  171.             printf("\n--------------play mp3----------------\n");
  172.             if(alarm_flag==1)
  173.              song_name=song1;
  174.             else song_name=song1;
  175.             printf("THIS SONG IS %s\n",song_name);
  176.             /*使用madplay播放MP3*/
  177.             execl("/motion/madplay","madplay",song_name,NULL);
  178.             printf("\n\n\n");
  179.         }
  180.         else /*子进程*/
  181.         {
  182.         
  183.             /*把孙子进程的id传入共享内存*/
  184.             memcpy(c_addr,&fd,sizeof(pid_t));
  185.             
  186.             /*目前在播放MP3,将播放标记传入共享内存*/
  187.             memcpy(c_addr+sizeof(int),&play_flag_gradchild1,4);
  188.             
  189.             /*等待孙子进程结束,只要结束:
  190.             传回play_flag_gradchild2=2,表示现在MP3没有播放*/
  191.             if(fd == wait(NULL))
  192.             {
  193.                 printf("\n------------------warning------------------\n");
  194.                 
  195.             /*通过共享内存传回play_flag_gradchild2=2,表明后面的一定不是连续的MP3播放*/
  196.                     memcpy(c_addr+sizeof(int),&play_flag_gradchild2,4);
  197.                     printf("Gradchild normal finish!\n");
  198.          printf("------------------warning------------------\n");
  199.             }//end if(fd == wait(NULL))

  200.         }

  201. }



  202. /*************************************************
  203. Function name: startplaymp3
  204. Called by         : 函数caculate_play,restart_caculate_play
  205. Parameter : pid_t *childpid
  206. Description     : 主进程创建子进程
  207. Return         : void
  208. Autor & date : ykz 10.4.2
  209. **************************************************/
  210. void startplaymp3(pid_t *childpid,int flag)
  211. {

  212.         int ret = 0;
  213.      pid_t cun_pid;
  214.         /*创建子进程*/
  215.         cun_pid = fork();
  216.         
  217.         if(cun_pid == -1)
  218.         {    
  219.             perror("son fork");
  220.             exit(1);
  221.         }

  222.         if(cun_pid == 0) /*子进程*/
  223.          play();
  224.         

  225.         if(cun_pid > 0) /*父进程*/
  226.         {
  227.             *childpid = cun_pid;
  228.          sleep(1); /*让孙子进程先执行*/
  229.         
  230.          /*如果是图像运动变化,将全局变量con_cnt加1*/
  231.          if( flag == 2 )
  232.             con_cnt++;
  233.         
  234.          printf("\nNow con_cnt=%d\n",con_cnt);
  235.          /*把孙子进程的pid传给父进程*/
  236.          memcpy(&gradchild,p_addr,sizeof(pid_t));

  237.         }

  238. }

  239. /*************************************************
  240. Function name: caculate_play
  241. Called by         : 函数key_pic_mp3
  242. Parameter : int flag
  243. Description     : 连续播放时,计算连续播放时间,调用函数startplaymp3开始新的播放
  244. Return         : int
  245. Autor & date : ykz 10.4.2
  246. **************************************************/
  247. int caculate_play(int flag)
  248. {

  249.     int ret;
  250.     
  251.     /*kill掉当前播放MP3的子进程,孙子进程*/
  252.         
  253.         kill(play_pid,SIGKILL);
  254.         kill(gradchild,SIGKILL);
  255.         wait(NULL);
  256.     
  257.     /*将共享内存清空*/
  258.         memset(p_addr,'\0',1024);

  259.      startplaymp3(&play_pid , flag);
  260.    return 1;
  261. }


  262. /*************************************************
  263. Function name: restart_caculate_play
  264. Called by         : 函数key_pic_mp3
  265. Parameter : int flag
  266. Description     : 未超过连续播放时间时,有新的图像或者外部中断检测到时调用函数
  267. Return         : void
  268. Autor & date : ykz 10.4.2
  269. **************************************************/
  270. void restart_caculate_play(int flag)
  271. {

  272.         int ret;
  273.         /*add 3 minute alarm*/
  274.         if(threemin_alarm){
  275.             if(signal(SIGALRM,my_func_3alarm)<0)
  276.                 perror("signal");
  277.             ret = alarm(THREE_ALARM);
  278.             printf("[%s]Start add 3 minute alarm!\n",max(flag));
  279.             threemin_alarm = 0;
  280.         }


  281. #if 1
  282.     /*判断是否有子进程,或者孙子进程,如果有则KILL掉*/
  283.         if(play_flag){
  284.             kill(play_pid,SIGKILL);
  285.             kill(gradchild,SIGKILL);
  286.             wait(NULL);
  287.             //sleep(1);

  288.         }
  289. #endif
  290.         play_pid = 0;
  291.         gradchild = 0;
  292.         
  293.         memset(p_addr,'\0',1024);
  294.     
  295.      /*开始播放MP3*/
  296.      startplaymp3(&play_pid,flag);
  297. }



  298. /*************************************************
  299. Function name: key_pic_mp3
  300. Called by         : 函数main
  301. Parameter : int flag
  302. Description     : 当检测到有外部中断,或者图像变化时处理函数
  303. Return         : int
  304. Autor & date : ykz 10.4.2
  305. **************************************************/
  306. int key_pic_mp3(int flag)
  307. {

  308.   printf("------------------------- KEY_PIC_MP3 ----------------------------\n");
  309.     printf("[%s]Now detect ** %s ** have change\n",max(flag),max(flag));
  310.     int ret = 0;
  311.     int over_flag_2;
  312.     int play_flag_2;

  313.   /*sleep_flag 用于判断,检测系统是否处于2小时的睡眠状态*/
  314.     if(sleep_flag){
  315.         printf("It is rainning!system is sleeping!\n");
  316.         struct tm *p;
  317.         time_t timep;
  318.         unsigned int second;
  319.         
  320.         time(&timep);
  321.         p = localtime(&timep);
  322.         second = (p->tm_hour)*60*60 + (p->tm_min) * 60 + p->tm_sec;

  323.         printf("summary time:%d seconds,sleep:%d seconds,need sleep:%d seconds\n",
  324.                     SLEEP_TIME,second-time_tmp,SLEEP_TIME-(second-time_tmp));

  325.         return 0;
  326.     }
  327.     
  328.     alarm_flag = flag;


  329.     /*从sharemem中读出是否有MP3处在播放状态标识*/
  330.     memcpy(&play_flag_2,p_addr + sizeof(int),sizeof(int));
  331. //    printf("===>key_pic_mp3,play_flag_2=%d\n",play_flag_2);

  332.     
  333.     play_flag = play_flag_2;
  334.     /*play_flag_2:当前是否有MP3在播放
  335.     0:当前没有MP3播放
  336.   1:子进程当前处在MP3播放状态
  337.   2:孙子当前播放MP3正常结束,且当前没有MP3播放*/

  338.     /*当前有MP3在播放*/
  339.     if(play_flag_2 == 1){
  340.             printf("[%s]Yes,have mp3 play\n",max(flag));
  341.             /*调用*/
  342.             ret = caculate_play(flag);
  343.     }
  344.     
  345.     /*当前无MP3在播放*/
  346.     else{
  347.             printf("[%s]No, have not mp3 play\n",max(flag));        
  348.          restart_caculate_play(flag);
  349.     }
  350.     
  351.     
  352.         return ret;
  353. }



  354. /*************************************************
  355. Function name: main
  356. Called by         :
  357. Parameter : void
  358. Description     : 主函数,检测按键是否有按下,通过pic.txt检测图像是否有变化
  359. Return         : int
  360. Autor & date : ykz 10.4.2
  361. **************************************************/
  362. main(void)
  363. {
  364.     
  365.      int buttons_fd,pic_fd;
  366.      char pic_buf[1];
  367.      int key_value;
  368.      int flag;
  369.      int ret;
  370.      int tmp_cnt;
  371.      /*设备文件的打开*/
  372.      buttons_fd = open("/dev/buttons", 0);
  373.      if(buttons_fd < 0) {
  374.         perror("open device buttons");
  375.         exit(1);
  376.      }
  377.      printf("open buttons sucess!\n");
  378.     
  379.     
  380.     
  381.      /*文件pic.txt记录是否有图像变化。
  382.      1:有图像变化
  383.      0:没有图像变化*/
  384.      pic_fd = open("pic.txt",O_RDWR | O_CREAT,0666);
  385.      if(pic_fd < 0) {
  386.         perror("open pic.txt");
  387.         exit(1);
  388.      }
  389.      printf("open pic.txt success!\n");
  390.     
  391.      /*文件count.txt用于图像连续变化时,记录/root/motion中图片张数*/
  392.      cnt_fd = open("count.txt",O_RDWR | O_CREAT,0666);
  393.      if(cnt_fd < 0){
  394.         perror("open count.txt");
  395.         exit(1);
  396.      }
  397.      printf("open count.txt success!\n");
  398.      system("ls > count.txt");
  399.     
  400.      /*共享内存申请*/
  401.          if((shmid = shmget(IPC_PRIVATE,20,PERM))== -1)
  402.             exit(1);
  403.         p_addr = shmat(shmid,0,0);
  404.         memset(p_addr,'\0',1024);
  405.         
  406.         
  407.     /*主循环,首先判断是外部中断还是图像变化*/
  408.     while(1){
  409.     
  410.         /*外部中断检测,监听获取键值*/
  411.             ret = read(buttons_fd, &key_value, sizeof key_value);
  412.             if (ret != sizeof key_value)         
  413.                     perror("read buttons\n");    
  414.             else {
  415.                 if(key_value){
  416.                     printf("====================================================================\n");
  417.                     printf("\n\n\n====================================================================\n");
  418.                     printf("[type1]button detect,buttons_value: %d\n", key_value);
  419.                     /*外部中断处理*/
  420.                     key_pic_mp3(1);
  421.                 }
  422.             } //end else

  423.         
  424.         
  425.         
  426.         /*图形变化检测,当有图像变化时motion会产生一个事件,
  427.         事件处理为脚本/motion/appon,该脚本先点亮LED灯;
  428.         然后向文件/motion/pic.txt写入字符"1"表明现在有图像变化被检测到;
  429.         
  430.         读取文件/motion/pic.txt第一个字符
  431.          0:没有图像变化
  432.          1:有图像变化*/
  433.         
  434.          lseek(pic_fd, 0 ,SEEK_SET);
  435.          ret = read(pic_fd, pic_buf, 1);

  436.        if(ret==1)
  437.          {
  438.             if(pic_buf[0] == '1'){ /*有图像变化被检测到*/
  439.              printf("====================================================================\n");
  440.              printf("\n\n\n====================================================================\n");
  441.              printf("[type2]pic motion detect!\n");
  442.              lseek(pic_fd, 0 ,SEEK_SET);
  443.             
  444.              if((ret = write(pic_fd, "0", 1)))
  445.                  lseek(pic_fd, 0 ,SEEK_SET);
  446.             
  447. //             system("rm /root/motion/* -rf");

  448.              pic_cnt = count_pic();
  449.              //printf("first pic_cnt=%d\n",pic_cnt);

  450.              /*图像运动变化处理*/
  451.               key_pic_mp3(2);
  452.          }
  453.         
  454.             else if(pic_buf[0] == '0'){
  455.              tmp_cnt = count_pic();
  456.              if( (tmp_cnt-pic_cnt) > COMPARE_CNT){
  457.                 printf("====================================================================\n");
  458.                 printf("\n\n\n====================================================================\n");
  459.                 printf("[type3]pic motion detect!\n");
  460.             
  461. //                system("rm /root/motion/* -rf");

  462.                 pic_cnt = count_pic();
  463.                 /*连续图像运动变化处理*/
  464.                 key_pic_mp3(2);
  465.              }
  466.             } //end else if

  467.             
  468.          }

  469.         sleep (2);
  470.              
  471.      }//end while

  472.      close (cnt_fd);
  473.      close (pic_fd);
  474.      close (buttons_fd);
  475.     exit(0);    
  476. }
阅读(696) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~