找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4307|回复: 1
收起左侧

利用STM32控制ov2640软件二值化源码

[复制链接]
ID:334654 发表于 2018-5-21 09:44 | 显示全部楼层 |阅读模式
利用STM32控制ov2640软件二值化采集数据,进行图像识别,可以操作机械臂

本实验将实现如下功能:开机后,初始化摄像头模块(OV2640),如果初始化成功,则提示选择模式:RGB565模式,或者JPEG模式。KEY0用于选择RGB565模式,KEY1用于选择JPEG模式。

    当使用RGB565时,输出图像(固定为:UXGA)将经过缩放处理(完全由OV2640的DSP控制),显示在LCD上面。我们可以通过KEY_UP按键选择:1:1显示,即不缩放,图片不变形,但是显示区域小(液晶分辨率大小),或者缩放显示,即将1600*1200的图像压缩到液晶分辨率尺寸显示,图片变形,但是显示了整个图片内容。通过KE0Y按键,可以设置对比度;KEY1按键,可以设置饱和度;KEY2按键,可以设置特效。

    当使用JPEG模式时,图像可以设置任意尺寸(QQVGA~UXGA),采集到的JPEG数据将先存放到STM32F4的内存里面,每当采集到一帧数据,就会关闭DMA传输,然后将采集到的数据发送到串口2(此时可以通过上位机软件(串口摄像头.exe)接收,并显示图片),之后再重新启动DMA传输。我们可以通过KEY_UP设置输出图片的尺寸(QQVGA~UXGA)。通过KEY0按键,可以设置对比度;KEY1按键,可以设置饱和度;KEY2按键,可以设置特效。
   

注意:本实验需要有ALIENTEK OV2640摄像头模块才可以做!!


单片机源程序如下:
  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart.h"
  4. #include "led.h"
  5. #include "key.h"
  6. #include "fing.h"
  7. #include "lcd.h"
  8. #include "usmart.h"  
  9. #include "usart2.h"  
  10. #include "timer.h"
  11. #include "ov2640.h"
  12. #include "dcmi.h"

  13. u8 ov2640_mode=0;                                                //工作模式:0,RGB565模式;1,JPEG模式
  14. u8 x=174,wide=51,mode=0,stop=1;
  15. u8 tempdrum[4][201];
  16. u8 delaytime=50,time=0;

  17. #define jpeg_buf_size 31*1024                          //定义JPEG数据缓存jpeg_buf的大小(*4字节)
  18. __align(4) u32 jpeg_buf[jpeg_buf_size];        //JPEG数据缓存buf
  19. volatile u32 jpeg_data_len=0;                         //buf中的JPEG有效数据长度
  20. volatile u8 jpeg_data_ok=0;                                //JPEG数据采集完成标志
  21.                                                                                 //0,数据没有采集完;
  22.                                                                                 //1,数据采集完了,但是还没处理;
  23.                                                                                 //2,数据已经处理完成了,可以开始下一帧接收

  24. void jpeg_data_process(void)
  25. {
  26.         if(ov2640_mode)//只有在JPEG格式下,才需要做处理.
  27.         {
  28.                 if(jpeg_data_ok==0)        //jpeg数据还未采集完?
  29.                 {       
  30.                         DMA_Cmd(DMA2_Stream1, DISABLE);//停止当前传输
  31.                         while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置  
  32.                         jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次数据传输的长度
  33.                                
  34.                         jpeg_data_ok=1;                                 //标记JPEG数据采集完按成,等待其他函数处理
  35.                 }
  36.                 if(jpeg_data_ok==2)        //上一次的jpeg数据已经被处理了
  37.                 {
  38.                         DMA2_Stream1->NDTR=jpeg_buf_size;       
  39.                         DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//传输长度为jpeg_buf_size*4字节
  40.                         DMA_Cmd(DMA2_Stream1, ENABLE);                        //重新传输
  41.                         jpeg_data_ok=0;                                                //标记数据未采集
  42.                 }
  43.         }
  44. }

  45. void KeyMode()
  46. {
  47.                 u8 msgbuf2[20];

  48.         DCMI_Stop(); //停止显示
  49.        

  50.        
  51.         if(WK_UP==1)
  52.         {
  53.                 mode+=1;
  54.                 if(mode==3)
  55.                 {
  56.                         mode=0;
  57.                         sprintf((char*)msgbuf2,"x=%d w=%d",x,wide);//g
  58.                    LCD_ShowString(200,200,100,16,16,msgbuf2);//显示提示内容
  59.     }
  60.                 sprintf((char*)msgbuf2,"mode=%d",mode);//g
  61.                 LCD_ShowString(200,220,100,16,16,msgbuf2);//显示提示内容
  62.                 while(WK_UP==1);
  63.         }

  64.                        
  65.        
  66.        

  67. if(mode==1)
  68. {
  69.                

  70.                         if(KEY0==0)
  71.         {
  72.                 x+=1;
  73.           sprintf((char*)msgbuf2,"   x=%d   ",x);//g
  74.                 LCD_ShowString(200,200,100,16,16,msgbuf2);//显示提示内容
  75.                 while(KEY0==0);
  76.         }
  77.                         if(KEY2==0)
  78.         {
  79.                 x-=1;
  80.            sprintf((char*)msgbuf2,"   x=%d   ",x);//g
  81.                 LCD_ShowString(200,200,100,16,16,msgbuf2);//显示提示内容
  82.                 while(KEY2==0);
  83.         }
  84. }
  85. if(mode==2)
  86. {

  87.                 if(KEY0==0)
  88.         {
  89.                 wide+=1;
  90.                 sprintf((char*)msgbuf2,"  w=%d   ",wide);//g
  91.                 LCD_ShowString(200,200,100,16,16,msgbuf2);//显示提示内容
  92.                 while(KEY0==0);
  93.         }
  94.                         if(KEY2==0)
  95.         {
  96.                 wide-=1;
  97.                 sprintf((char*)msgbuf2,"  w=%d   ",wide);//g
  98.                 LCD_ShowString(200,200,100,16,16,msgbuf2);//显示提示内容
  99.                 while(KEY0==0);
  100.         }
  101. }
  102. if(mode==0)
  103. {

  104.                 if(KEY0==0)
  105.         {
  106.                 delaytime+=1;
  107.                 sprintf((char*)msgbuf2,"  w=%d   ",delaytime);//g
  108.                 LCD_ShowString(200,220,100,16,16,msgbuf2);//显示提示内容
  109.                 while(KEY0==0);
  110.         }
  111.                         if(KEY2==0)
  112.         {
  113.                 delaytime-=1;
  114.                 sprintf((char*)msgbuf2,"  w=%d   ",delaytime);//g
  115.                 LCD_ShowString(200,220,100,16,16,msgbuf2);//显示提示内容
  116.                 while(KEY0==0);
  117.         }
  118. }


  119.                         DCMI_Start();
  120. }

  121. void getcolor(tx,ty,num)
  122. {

  123.         u8 msgbuf1[15];        //消息缓存区

  124.         u16 tempcolor;

  125.       
  126.                  
  127.                   DCMI_Stop(); //停止显示
  128.                         tempcolor=LCD_ReadPoint(tx,ty);
  129.                   
  130.             sprintf((char*)msgbuf1,"%d",(int) ((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5));//g
  131.                   LCD_ShowString(tx-8,ty+24,210,16,16,msgbuf1);//显示提示内容
  132.        

  133.         if((int) ((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5)>30)   //软件二值化
  134.         {
  135.           LCD_Fill((num-1)*120+1,150-20,num*120-1,150+20,WHITE);
  136.     tempdrum[num-1][time]=1;
  137.         }
  138.         else
  139.         {
  140.           LCD_Fill((num-1)*120+1,150-20,num*120-1,150+20,BLACK);
  141.     tempdrum[num-1][time]=0;
  142.         }
  143.                

  144.                
  145.                   LCD_DrawRectangle(tx-1,ty-1, tx+1, ty+1);
  146.                         LCD_DrawLine(tx, ty-2, tx, ty-7);
  147.                         LCD_DrawLine(tx-2, ty, tx-7, ty);
  148.                         LCD_DrawLine(tx+2, ty, tx+7, ty);               

  149. //          
  150. //                        while(KEY_Scan(0))
  151. //                        KeyMode();

  152.                         DCMI_Start();

  153. //低字节的前5位用来表示B(BLUE)
  154. //低字节的后三位+高字节的前三位用来表示G(Green)
  155. //高字节的后5位用来表示R(RED)               

  156. // R8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);
  157. // G8 = (int) floor( G6 * 255.0 / 63.0 + 0.5);
  158. // B8 = (int) floor( R5 * 255.0 / 31.0 + 0.5);

  159. // R8 = (int) floor( (tempcolor>>11) * 255.0 / 31.0 + 0.5);
  160. // G8 = (int) floor((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5);
  161. // B8 = (int) floor( (tempcolor&0x1f) * 255.0 / 31.0 + 0.5);
  162.                
  163.         //        delay_ms(1);       

  164. }

  165. //RGB565测试
  166. //RGB数据直接显示在LCD上面
  167. void fing()
  168. {
  169. u16 temptime;
  170.         if (time<delaytime)temptime=time+201-delaytime;
  171.         else temptime=time-delaytime;
  172.        
  173.                 if(tempdrum[0][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_2);
  174.            else                       GPIO_ResetBits(GPIOG,GPIO_Pin_2);
  175.                 if(tempdrum[1][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_4);
  176.            else                       GPIO_ResetBits(GPIOG,GPIO_Pin_4);
  177.                 if(tempdrum[2][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_6);
  178.            else                       GPIO_ResetBits(GPIOG,GPIO_Pin_6);
  179.                 if(tempdrum[3][temptime]==1)GPIO_SetBits(GPIOG,GPIO_Pin_8);
  180.      else                       GPIO_ResetBits(GPIOG,GPIO_Pin_8);
  181. }
  182. void rgb565_test()
  183. {

  184.         u8 effect=0,saturation=2,contrast=2;
  185.         u8 scale=1;                //默认是全尺寸缩放
  186.         u8 msgbuf[15];        //消息缓存区
  187. //                u8 msgbuf2[15];        //消息缓存区
  188.         u16 tempx;
  189.        
  190.         LCD_Clear(BLACK);
  191.   POINT_COLOR=RED;

  192.         OV2640_RGB565_Mode();        //RGB565模式
  193.         My_DCMI_Init();                        //DCMI配置
  194. //OV2640_Window_Set(0,0,lcddev.width,lcddev.height/4);
  195.         DCMI_DMA_Init((u32)&LCD->LCD_RAM,1,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Disable);//DCMI DMA配置  
  196.   OV2640_ImageWin_Set((800-lcddev.width)/2,(800-lcddev.height/4)/2,lcddev.width,lcddev.height/8);//1:1真实尺寸


  197.         OV2640_OutSize_Set(480,lcddev.height/8);


  198.   delay_ms(800);

  199.                
  200.   DCMI_Start();                 //启动传输

  201.        
  202.         while(1)
  203.         {
  204.    
  205.     tempx=x;
  206.        
  207.     getcolor(tempx,20,1);
  208.                 tempx+=wide;
  209.                 getcolor(tempx,20,2);
  210.                 tempx+=wide;
  211.                 getcolor(tempx,20,3);
  212.                 tempx+=wide;
  213.                 getcolor(tempx,20,4);
  214.                
  215.                 fing();
  216.                 time++;
  217.                 if(time>200)time=0;
  218.                
  219.                 if(KEY_Scan(0))
  220.     KeyMode();

  221.         }   
  222. }


  223. int main(void)
  224. {
  225.         u8 key;
  226.         u8 t;

  227.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  228.         delay_init(168);  //初始化延时函数
  229.         uart_init(115200);                //初始化串口波特率为115200
  230.         usart2_init(42,115200);                //初始化串口2波特率为115200
  231.         LED_Init();                                        //初始化LED
  232.         LCD_Init();                                        //LCD初始化  
  233.         KEY_Init();                                        //按键初始化
  234.         FINE_Init();
  235.         TIM3_Int_Init(10000-1,8400-1);//10Khz计数,1秒钟中断一次
  236.        
  237.         usmart_dev.init(84);                //初始化USMART
  238.         POINT_COLOR=RED;//设置字体为红色
  239.          
  240.         while(OV2640_Init())//初始化OV2640
  241.         {
  242.                 LCD_ShowString(30,130,240,16,16,"OV2640 ERR");
  243.                 delay_ms(200);
  244.             LCD_Fill(30,130,239,170,WHITE);
  245.                 delay_ms(200);
  246.         }
  247.         LCD_ShowString(30,130,200,16,16,"OV2640 OK");            

  248.         while(1)
  249.         {       

  250.    rgb565_test();

  251.                   
  252.         }
  253. }
  254.        
复制代码

所有资料51hei提供下载:
摄像头采集程序.rar (575.18 KB, 下载次数: 61)
回复

使用道具 举报

ID:225110 发表于 2018-6-17 13:16 | 显示全部楼层
图像显示只能显示一小部分
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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