关于ov2640边缘提取相关代码解读

2019-07-20 01:53发布


在网上看到一个和我做的课题相同的源码 根据实验35ov2640实验基础上改良的边缘提取算法 下面是main函数 我看不懂每一步干什么的 也不知道这个是什么算子实现的 求各位大神指教
#include "sys.h"
#include "delay.h"  
#include "usart.h"   
#include "led.h"
#include "lcd.h"
#include "key.h"  
//#include "usmart.h"  
#include "usart2.h"  
#include "timer.h"
#include "ov2640.h"
#include "dcmi.h"
u8 ov2640_mode=0;      //工作模式:0,RGB565模式;1,JPEG模式

#define CAMERA_H  160 //定义数组CAMERA_H
#define CAMERA_W  160 //定义数组CAMERA_W
u16 Image[CAMERA_H][CAMERA_W]= {0};
u8  address[40][2]={0};
u8 x_address,y_address;
u8 hold_for_gray=12;
u8 hold_for=5;
#define jpeg_buf_size 2     //定义JPEG数据缓存jpeg_buf的大小(*4字节)
__align(4) u32 jpeg_buf[jpeg_buf_size]; //JPEG数据缓存buf
volatile u32 jpeg_data_len=0;    //buf中的JPEG有效数据长度
volatile u8 jpeg_data_ok=0;    //JPEG数据采集完成标志

#define yuv_buf_size 160*160*2/4
__align(4) u32 yuv_buf[yuv_buf_size]; //yuv数据缓存buf【__align(4)为四字节对齐】
volatile u32 yuv_data_len=12800;   

int my_abs(int a)
{
if(a<0)
  return -a;
else
  return a;
}
//处理JPEG数据
//当采集完一帧JPEG数据后,调用此函数,切换JPEG BUF.开始下一帧采集.
void jpeg_data_process(void)
{
if(ov2640_mode)//只有在JPEG格式下,才需要做处理.
{
  if(jpeg_data_ok==0) //jpeg数据还未采集完?
  {
   DMA2_Stream1->CR&=~(1<<0);  //停止当前传输
   while(DMA2_Stream1->CR&0X01); //等待DMA2_Stream1可配置   
   jpeg_data_len=jpeg_buf_size-DMA2_Stream1->NDTR;//得到此次数据传输的长度
   jpeg_data_ok=1;     //标记JPEG数据采集完按成,等待其他函数处理
  }
  if(jpeg_data_ok==2) //上一次的jpeg数据已经被处理了
  {
   DMA2_Stream1->NDTR=jpeg_buf_size; //传输长度为jpeg_buf_size*4字节
   DMA2_Stream1->CR|=1<<0;    //重新传输
   jpeg_data_ok=0;      //标记数据未采集
  }
}
}


//函数功能:YUV422格式转灰度图像(RGB565格式显示)
//yuv422:yuv格式数据
u16 yuv422_to_Gray(u16 yuv422)
{
u16 Gray; //用于储存灰度值变量(RGB565格式显示)
Gray =(((yuv422>>(8+3))<<11)|((yuv422>>(8+2))<<5)|((yuv422>>(8+3))<<0));//Y量转为灰度值(RGB565格式显示)
return Gray; //返回灰度图像值(RGB565格式显示)
}

//函数功能:YUV422格式Y量二值化(RGB565格式显示)
//yuv422:yuv格式数据
//threshold:阀值
u16 yuv422_y_to_bitmap(u8 threshold,u16 yuv422)
{
u16 bitmap; //二值化数据变量(RGB565格式显示)
u8 temp; //用于储存yuv422格式数据中的亮度值Y量

temp = (u8)(yuv422>>8);//把yuv422格式数据中的亮度值Y量提取出来赋值给temp变量(Y值在高字节,根据OV2640寄存器设置决定)
if(temp >= threshold)//如果,Y值大于等于阀值
{
  bitmap =0xffff; //白
}
else
{
  bitmap =0x0000; //黑
}

return bitmap; //返回二值化像素值
}
void img_send()
{  
  u8 j,k;
  
  u8 *p;
  u32 i;
      
//  for(j=hold_for+1;j<160-hold_for;j++)
//   {
//     if((my_abs(address[j][0]-address[j-1][0])<3)&&(my_abs(address[j][0]-address[j-1][0])<3))
//       if((my_abs(address[j][0]-address[j+1][0])<3)&&(my_abs(address[j][0]-address[j+1][0])<3))
//        if((my_abs(address[j][0]-address[j+2][0])<3)&&(my_abs(address[j][0]-address[j+2][0])<3))
//         if((my_abs(address[j][0]-address[j+3][0])<3)&&(my_abs(address[j][0]-address[j+3][0])<3))
//         {
//          if((address[j+1][0]>0)&&(address[j+1][1]>0))
//          {
//           x_address=address[j+1][1];
//           y_address=address[j+1][0];
////          LCD_Fast_DrawPoint(address[j+1][1],address[j+1][0],RED);
////          LCD_Fast_DrawPoint(address[j+2][1],address[j+2][0],RED);
////          LCD_Fast_DrawPoint(address[j+3][1],address[j+3][0],RED);
//           LCD_ShowString(x_address,y_address,50,16,16,"x");
//          }
//        }
//   }

          p=(u8*)Image;
         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);  //循环发送,直到发送完毕
          USART_SendData(USART2,0x01);
         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
          USART_SendData(USART2,0xfe);   
          for(i=0;i<yuv_data_len*4;i++)  //dma传输1次等于4字节,所以乘以4.
          {
             while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕  
             USART_SendData(USART2,p[i]);
          }
         
         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
          USART_SendData(USART2,0xfe);
         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕
          USART_SendData(USART2,0x01);
//while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);
//   USART_SendData(USART2,253);//行标志
//while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕  
//   USART_SendData(USART2,x_address);
//   while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);
//   USART_SendData(USART2,254);//列标志
//  while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕  
//   USART_SendData(USART2,y_address);     
   LCD_ShowNum(59,310,(u32)x_address,3,16);
   LCD_ShowNum(59,330,(u32)y_address,3,16);
   LCD_Fast_DrawPoint(y_address,x_address,RED);//快速画点
   LCD_Fast_DrawPoint(y_address+1,x_address,RED);
   LCD_Fast_DrawPoint(y_address,x_address+1,RED);
//   for(j=0;j<160;j++)
//   {
//     address[j][0]=0;
//     address[j][1]=0;
//   }
}

u16 imag_proc(u16 imag,u16 i)
{
  u8 night;
  u8 count=0;
  u16 imagtemp;
  imagtemp=imag;
  night=imag>>8;
  if((u8)(yuv_buf[i-320]>>8)-night>hold_for_gray) count++;
  if((u8)(yuv_buf[i-160]>>8)-night>hold_for_gray) count++;
  if((u8)(yuv_buf[i+320]>>8)-night>hold_for_gray) count++;
  if((u8)(yuv_buf[i+320]>>8)-night>hold_for_gray) count++;  
  if((u8)(yuv_buf[i-1]>>24)-night>hold_for_gray) count++;
  if((u8)(yuv_buf[i+1]>>24)-night>hold_for_gray) count++;
  if(count>3)
  {imag=0x0000;return imag;}
  else return imagtemp;
  
}
int main(void)
{        
u8 key=0;
u8 threshold=130; //二值化时用到的阀值变量   threshold=128   TEST

// u16 Direction_value1=0,Direction_value2=0,Direction_value3=0; //方向值变量
Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
delay_init(168);   //延时初始化  
uart_init(84,115200);  //初始化串口波特率为115200
usart2_init(42,115200);  //初始化串口2波特率为115200
LED_Init();     //初始化LED
  LCD_Init();     //LCD初始化

  KEY_Init();     //按键初始化
TIM3_Int_Init(10000-1,8400-1);//10Khz计数,1秒钟中断一次
  POINT_COLOR=RED;//设置字体为红 {MOD}
LCD_ShowString(30,10,200,16,16,"Explorer STM32F4");

while(OV2640_Init())//初始化OV2640
{
  LCD_ShowString(30,30,240,16,16,"OV2640 ERROR");
  delay_ms(200);
     LCD_Fill(30,130,239,170,WHITE);
  delay_ms(200);
}
LCD_ShowString(30,30,200,16,16,"OV2640 OK");
LCD_ShowString(30,50,240,16,16,"KEY_UP: 阙值+"); //按键上:阀值增加
LCD_ShowString(30,70,240,16,16,"  KEY1: 阙值-"); //按键1:阀值减少
delay_ms(100);

  while(1)
{ //RGB565测试
  //RGB数据直接显示在LCD上面

  LCD_Clear(WHITE); //清屏函数
  POINT_COLOR=RED; //画笔颜 {MOD}
  My_DCMI_Init();   //DCMI配置 初始化
  DCMI_DMA_Init((u32)&yuv_buf,yuv_buf_size,2,1);//DCMI DMA配置
  OV2640_OutSize_Set(160,160);//OV2640输出图像 设置图像输出大小

  while(1) //这里将会重复执行{}中的代码
  {
   u16 i,temp_h,temp_l;
   u16 j,k;
   u8 n=0;
//      u16 signal1=0,signal2=0,signal=0;
   OV2640_YUV422_Mode();
   DCMI_Start();   //启动传输
   DCMI_Stop(); //停止显示
   
   LCD_Set_Window(0,0,160,160); //设置窗口,并自动设置画点坐标到窗口左上角(sx,sy
   LCD_WriteRAM_Prepare(); //开始写入GRAM
   i=0;
   //for(j = 0; j < CAMERA_H; j++)
   for(j = 7; j < 154; j++)
  {
   for(k = 7; k < 148; k=k+2)
   {
    temp_l=(u16)(yuv_buf[i]);
    temp_l=imag_proc(temp_l,i);
   
   
//    imag_for_gray[j][k]=temp_l>>8;
    //Image[j][k]   = yuv422_y_to_bitmap(threshold,temp_l);//先写入低16位
    Image[j][k]   = yuv422_to_Gray(temp_l);
    if(Image[j][k]==0)
     {
       n++;
       if(Image[j-2][k-2]==0) n++;if(Image[j-2][k-1]==0) n++;if(Image[j-2][k]==0) n++;if(Image[j-2][k+1]==0) n++;if(Image[j-2][k+2]==0) n++;
       if(Image[j-1][k-2]==0) n++;if(Image[j-1][k-1]==0) n++;if(Image[j-1][k]==0) n++;if(Image[j-1][k+1]==0) n++;if(Image[j-1][k+2]==0) n++;
       if(Image[j][k-2]==0) n++;if(Image[j][k-1]==0) n++;if(Image[j][k+1]==0) n++;if(Image[j][k+2]==0) n++;
       if(Image[j+1][k-2]==0) n++;if(Image[j+1][k-1]==0) n++;if(Image[j+1][k]==0) n++;if(Image[j+1][k+1]==0) n++;if(Image[j+1][k+2]==0) n++;
       if(Image[j+2][k-2]==0) n++;if(Image[j+2][k-1]==0) n++;if(Image[j+2][k]==0) n++;if(Image[j+2][k+1]==0) n++;if(Image[j+2][k+2]==0) n++;
       if(n>15)
       {
         if(((j>10)&&(j<150))||((k>10)&&(k<150)))
         {
          Image[j][k]=255;
          x_address=j;y_address=k;
         }
       }
      
       n=0;
     }
     
    temp_h=(u16)(yuv_buf[i]>>16);
    temp_h=imag_proc(temp_h,i);
//    if((temp_h==0x0000)&&(j>hold_for)&&(j<160-hold_for)&&(k>hold_for)&&(k<160-hold_for))
//    {
//      if((temp_h==0x0000)&&(j>hold_for)&&(j<160-hold_for)&&(k>hold_for)&&(k<160-hold_for))
//        {address[n][0]=j;address[n][1]=k+1;n++;}
//      else{address[n][0]=0;address[n][1]=0;}
//    }
     
        
  //  imag_for_gray[j][k+1]=temp_h;
//   Image[j][k+1] = yuv422_y_to_bitmap(threshold,temp_h);//后写入高16?
    Image[j][k+1] = yuv422_to_Gray(temp_h);     //    LCD->LCD_RAM  = Image[j][k+1];
     if(Image[j][k+1]==0)
     {
       n++;
       if(Image[j-2][k-1]==0) n++;if(Image[j-2][k]==0) n++;if(Image[j-2][k+1]==0) n++;if(Image[j-2][k+2]==0) n++;if(Image[j-2][k+3]==0) n++;
       if(Image[j-1][k-1]==0) n++;if(Image[j-1][k]==0) n++;if(Image[j-1][k+1]==0) n++;if(Image[j-1][k+2]==0) n++;if(Image[j-1][k+3]==0) n++;
       if(Image[j][k-1]==0) n++;if(Image[j][k]==0) n++;if(Image[j][k+2]==0) n++;if(Image[j][k+3]==0) n++;
       if(Image[j+1][k-1]==0) n++;if(Image[j+1][k]==0) n++;if(Image[j+1][k+1]==0) n++;if(Image[j+1][k+2]==0) n++;if(Image[j+1][k+3]==0) n++;
       if(Image[j+2][k-1]==0) n++;if(Image[j+2][k]==0) n++;if(Image[j+2][k+1]==0) n++;if(Image[j+2][k+2]==0) n++;if(Image[j+2][k+3]==0) n++;
       if(n>15)
       {
         if((j>10)&&(j<150)||(k>10)&&(k<150))
         {
           Image[j][k+1]=255;
           x_address=j;y_address=k+1;
         }
       }
       n=0;
     }
    i++;
    }
    }
///////////////////////*********LCD显示**********///////////////////////
  for(j = 0; j < CAMERA_H; j++)
  {
   for(k = 0; k < CAMERA_W; k=k+2)
   {
    LCD->LCD_RAM  = Image[j][k];   
    LCD->LCD_RAM  = Image[j][k+1];
   
    }
    }
   key=KEY_Scan(1); //按键扫描函数
   if(key)
   {
    switch(key)
    {        
     case WKUP_PRES: //阀值+1
      hold_for++;break;   //hold_for_gray
     case KEY1_PRES: //阀值-1
      hold_for_gray--;break;
     case KEY0_PRES: //阀值-1
      hold_for_gray++;break;
     case KEY2_PRES: //阀值-1
      hold_for--;break;
    }
   }
   img_send();
//     for(n=0;n<40;n++)
//     {
//       if((address[n][0]>0)||(address[n][1]<0))
//       {
//         address[n][0]=0;
//         address[n][1]=0;
//       }
//       else n++;
//     }
//     n=0;
   LCD_ShowString(10,288,50,16,16,"pianyi:");
   LCD_ShowNum(59,288,(u32)hold_for,3,16);
   //LCD_Fast_DrawPoint(80,80,RED);
   LCD_ShowString(10,260,50,16,16,"fazhi:");
   LCD_ShowNum(59,260,(u32)hold_for_gray,3,16);
  }  
}
}


0条回答

一周热门 更多>