找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4954|回復(fù): 1
收起左側(cè)

利用STM32控制ov2640軟件二值化源碼

[復(fù)制鏈接]
ID:334654 發(fā)表于 2018-5-21 09:44 | 顯示全部樓層 |閱讀模式
利用STM32控制ov2640軟件二值化采集數(shù)據(jù),進(jìn)行圖像識別,可以操作機(jī)械臂

本實(shí)驗(yàn)將實(shí)現(xiàn)如下功能:開機(jī)后,初始化攝像頭模塊(OV2640),如果初始化成功,則提示選擇模式:RGB565模式,或者JPEG模式。KEY0用于選擇RGB565模式,KEY1用于選擇JPEG模式。

    當(dāng)使用RGB565時,輸出圖像(固定為:UXGA)將經(jīng)過縮放處理(完全由OV2640的DSP控制),顯示在LCD上面。我們可以通過KEY_UP按鍵選擇:1:1顯示,即不縮放,圖片不變形,但是顯示區(qū)域小(液晶分辨率大。蛘呖s放顯示,即將1600*1200的圖像壓縮到液晶分辨率尺寸顯示,圖片變形,但是顯示了整個圖片內(nèi)容。通過KE0Y按鍵,可以設(shè)置對比度;KEY1按鍵,可以設(shè)置飽和度;KEY2按鍵,可以設(shè)置特效。

    當(dāng)使用JPEG模式時,圖像可以設(shè)置任意尺寸(QQVGA~UXGA),采集到的JPEG數(shù)據(jù)將先存放到STM32F4的內(nèi)存里面,每當(dāng)采集到一幀數(shù)據(jù),就會關(guān)閉DMA傳輸,然后將采集到的數(shù)據(jù)發(fā)送到串口2(此時可以通過上位機(jī)軟件(串口攝像頭.exe)接收,并顯示圖片),之后再重新啟動DMA傳輸。我們可以通過KEY_UP設(shè)置輸出圖片的尺寸(QQVGA~UXGA)。通過KEY0按鍵,可以設(shè)置對比度;KEY1按鍵,可以設(shè)置飽和度;KEY2按鍵,可以設(shè)置特效。
   

注意:本實(shí)驗(yàn)需要有ALIENTEK OV2640攝像頭模塊才可以做!


單片機(jī)源程序如下:
  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數(shù)據(jù)緩存jpeg_buf的大小(*4字節(jié))
  18. __align(4) u32 jpeg_buf[jpeg_buf_size];        //JPEG數(shù)據(jù)緩存buf
  19. volatile u32 jpeg_data_len=0;                         //buf中的JPEG有效數(shù)據(jù)長度
  20. volatile u8 jpeg_data_ok=0;                                //JPEG數(shù)據(jù)采集完成標(biāo)志
  21.                                                                                 //0,數(shù)據(jù)沒有采集完;
  22.                                                                                 //1,數(shù)據(jù)采集完了,但是還沒處理;
  23.                                                                                 //2,數(shù)據(jù)已經(jīng)處理完成了,可以開始下一幀接收

  24. void jpeg_data_process(void)
  25. {
  26.         if(ov2640_mode)//只有在JPEG格式下,才需要做處理.
  27.         {
  28.                 if(jpeg_data_ok==0)        //jpeg數(shù)據(jù)還未采集完?
  29.                 {       
  30.                         DMA_Cmd(DMA2_Stream1, DISABLE);//停止當(dāng)前傳輸
  31.                         while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){}//等待DMA2_Stream1可配置  
  32.                         jpeg_data_len=jpeg_buf_size-DMA_GetCurrDataCounter(DMA2_Stream1);//得到此次數(shù)據(jù)傳輸?shù)拈L度
  33.                                
  34.                         jpeg_data_ok=1;                                 //標(biāo)記JPEG數(shù)據(jù)采集完按成,等待其他函數(shù)處理
  35.                 }
  36.                 if(jpeg_data_ok==2)        //上一次的jpeg數(shù)據(jù)已經(jīng)被處理了
  37.                 {
  38.                         DMA2_Stream1->NDTR=jpeg_buf_size;       
  39.                         DMA_SetCurrDataCounter(DMA2_Stream1,jpeg_buf_size);//傳輸長度為jpeg_buf_size*4字節(jié)
  40.                         DMA_Cmd(DMA2_Stream1, ENABLE);                        //重新傳輸
  41.                         jpeg_data_ok=0;                                                //標(biāo)記數(shù)據(jù)未采集
  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);//顯示提示內(nèi)容
  59.     }
  60.                 sprintf((char*)msgbuf2,"mode=%d",mode);//g
  61.                 LCD_ShowString(200,220,100,16,16,msgbuf2);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  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);//顯示提示內(nèi)容
  116.                 while(KEY0==0);
  117.         }
  118. }


  119.                         DCMI_Start();
  120. }

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

  123.         u8 msgbuf1[15];        //消息緩存區(qū)

  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);//顯示提示內(nèi)容
  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. //低字節(jié)的前5位用來表示B(BLUE)
  154. //低字節(jié)的后三位+高字節(jié)的前三位用來表示G(Green)
  155. //高字節(jié)的后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數(shù)據(jù)直接顯示在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;                //默認(rèn)是全尺寸縮放
  186.         u8 msgbuf[15];        //消息緩存區(qū)
  187. //                u8 msgbuf2[15];        //消息緩存區(qū)
  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真實(shí)尺寸


  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);//設(shè)置系統(tǒng)中斷優(yōu)先級分組2
  228.         delay_init(168);  //初始化延時函數(shù)
  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計數(shù),1秒鐘中斷一次
  236.        
  237.         usmart_dev.init(84);                //初始化USMART
  238.         POINT_COLOR=RED;//設(shè)置字體為紅色
  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.        
復(fù)制代碼

所有資料51hei提供下載:
攝像頭采集程序.rar (575.18 KB, 下載次數(shù): 61)


回復(fù)

使用道具 舉報

ID:225110 發(fā)表于 2018-6-17 13:16 | 顯示全部樓層
圖像顯示只能顯示一小部分
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表