找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4851|回复: 10
打印 上一主题 下一主题
收起左侧

stm32源码 ov7725二值化并能返回圆的圆心

  [复制链接]
跳转到指定楼层
楼主
ID:250245 发表于 2018-6-3 15:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这是我自己写的ov7725二值化程序并能返回圆的圆心,不喜勿喷,希望有大佬有更好的程序分享过来

单片机源程序如下:
  1. #include "led.h"
  2. #include "delay.h"
  3. #include "key.h"
  4. #include "sys.h"
  5. #include "lcd.h"
  6. #include "usart.h"         
  7. #include "string.h"
  8. #include "ov7725.h"
  9. #include "ov7670.h"
  10. #include "tpad.h"
  11. #include "timer.h"
  12. #include "exti.h"
  13. #include "usmart.h"

  14. //由于OV7725传感器安装方式原因,OV7725_WINDOW_WIDTH相当于LCD的高度,OV7725_WINDOW_HEIGHT相当于LCD的宽度
  15. //注意:此宏定义只对OV7725有效
  16. #define  OV7725_WINDOW_WIDTH                320 // <=320
  17. #define  OV7725_WINDOW_HEIGHT                240 // <=240


  18. const u8*LMODE_TBL[6]={"Auto","Sunny","Cloudy","Office","Home","Night"};//6种光照模式            
  19. const u8*EFFECTS_TBL[7]={"Normal","Negative","B&W","Redish","Greenish","Bluish","Antique"};        //7种特效
  20. extern u8 ov_sta;        //在exit.c里 面定义
  21. extern u8 ov_frame;        //在timer.c里面定义

  22. //更新LCD显示(OV7725)
  23. void OV7725_camera_refresh(void)
  24. {
  25.         u32 i,j;
  26.          u16 color;         
  27.         double X_FLAG=0.0,Y_FLAG=0.0;
  28.         int        NUM_X=0,NUM_Y=0;
  29.         char FlagStatus;
  30.         if(ov_sta)//有帧中断更新
  31.         {
  32. //                u8 R=0x00,G=0x00,B=0x00;
  33. //        u16 RGB_Color=0x0000;
  34. //        float Max=0,Min=0;
  35. //        float Rhsv=0,Ghsv=0,Bhsv=0;
  36. //        float H=0,S=0,V=0;
  37. //               
  38. //               
  39. //        volatile u16 gray;
  40. //        u8 gm_red,gm_green,gm_blue;
  41.                 LCD_Scan_Dir(U2D_L2R);//从上到下,从左到右
  42.                 LCD_Set_Window((lcddev.width-OV7725_WINDOW_WIDTH)/2,(lcddev.height-OV7725_WINDOW_HEIGHT)/2,OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT);//将显示区域设置到屏幕中央
  43.                 if(lcddev.id==0X1963)
  44.                         LCD_Set_Window((lcddev.width-OV7725_WINDOW_WIDTH)/2,(lcddev.height-OV7725_WINDOW_HEIGHT)/2,OV7725_WINDOW_HEIGHT,OV7725_WINDOW_WIDTH);//将显示区域设置到屏幕中央
  45.                 LCD_WriteRAM_Prepare();     //开始写入GRAM        
  46. /*******/               
  47.                 OV7725_RRST=0;                                //开始复位读指针
  48.                 OV7725_RCK_L;
  49.                 OV7725_RCK_H;
  50.                 OV7725_RCK_L;
  51.                 OV7725_RRST=1;                                //复位读指针结束
  52.                 OV7725_RCK_H;
  53.                 for(i=0;i<240;i++,FlagStatus=0)
  54.                 {
  55.                         for(j=0;j<OV7725_WINDOW_WIDTH;j++)
  56.                         {
  57. //                                OV7725_RCK_L;
  58. //                                color=GPIOC->IDR&0XFF;        //读数据
  59. //                                OV7725_RCK_H;
  60. //                                color<<=8;  
  61. //                                OV7725_RCK_L;
  62. //                                color|=GPIOC->IDR&0XFF;        //读数据
  63. //                                OV7725_RCK_H;
  64. //                                R=color&0x001f;
  65. //                                G=(color&0x0770)>>5;
  66. //                                B=(color&0xf800)>>11;
  67. //                        gm_red = (color & 0xF800) >> 8;
  68. //                        gm_green = (color & 0x07E0) >> 3;
  69. //                        gm_blue = (color & 0x001F) << 3;
  70. //                        gray =(gm_red*77+gm_green*150+gm_blue*29+128)/256;
  71. //                        gray=gray/8;
  72. //                        color=(0x001f&gray)<<11;
  73. //                        color=color|(((0x003f)&(gray*2))<<5);
  74. //                        color=color|(0x001f&gray);
  75.                                 /*********/
  76.             if((i>=20&&i<220)&&(j>=20&&j<220))//100*100               
  77.                                                         {                OV7725_RCK_L;
  78.                                                         color=GPIOC->IDR&0XFF;        //YUYV输出读数据  不读第二个字节
  79.                                                         OV7725_RCK_H;
  80.                                                         //color<<=8;  
  81.                                                         OV7725_RCK_L;
  82.                                                         //color|=GPIOC->IDR&0XFF;        //读数据
  83.                                                         OV7725_RCK_H;                                                
  84.                                                                         if(color>0x5F)
  85.                                                                         {
  86.                                                                         color=0xffff;//白色  
  87.                                                                         }                                                                                
  88.                                                                         else
  89.                                                                         {
  90.                                                                         FlagStatus=1;
  91.                                                                         NUM_Y++;
  92.                                                                         Y_FLAG+=j;
  93.                                                                         color=0x0000;//黑色               
  94.                                                                         }                                                                                
  95.                                                      LCD->LCD_RAM=color;  
  96.                                                         }
  97.                                                         else
  98.                                                         {
  99.                                                         OV7725_RCK_L;
  100.                                                         OV7725_RCK_H;
  101.                                                         OV7725_RCK_L;
  102.                                                         OV7725_RCK_H;
  103.                                                         LCD->LCD_RAM=0xffff;
  104.                                                         }
  105.                                                            
  106.                
  107.                                 
  108.                                 
  109. //                                LCD->LCD_RAM=color;  
  110. //                                /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓RGB转HSV算法↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
  111. //                Rhsv = (float) R/25/10;        //RGB转换成0,1.
  112. //                Ghsv = (float) G/25/10;         
  113. //                Bhsv = (float) B/25/10;

  114. //                Max = (Rhsv>Ghsv)?Rhsv:Ghsv;        
  115. //                Max = (Max>Bhsv)?Max:Bhsv;                //取RGB最大值                                 
  116. //                Min = (Rhsv<Ghsv)?Rhsv:Ghsv;                                                                  
  117. //                Min = (Min<Bhsv)?Min:Bhsv;                //去RGB最小值                                         
  118. //                                                               
  119. //                if(Rhsv==Max) H = (Ghsv-Bhsv)/(Max-Min);                                                  
  120. //                if(Ghsv==Max) H = 2+(Bhsv-Rhsv)/(Max-Min);                                                         
  121. //                if(Bhsv==Max) H = 4+(Rhsv-Ghsv)/(Max-Min);                                                        
  122. //                H =(int) (H*60);                                //取H的数值                                                                                          
  123. //                if(H<0) H = H+360;                                                                                                                                                                                                                                                                        
  124. //                V = (Rhsv>Ghsv)?Rhsv:Ghsv;                                                                                                
  125. //                V = (V>Bhsv)?V:Bhsv;                //取V的数值                                                                                                                                                                                                                                          
  126. //                S = (Max-Min)/Max;                        //取S的数值                                                                                                                                                                                                                                                
  127. //                V = (int) (V*100);                                                                                                                        
  128. //                S = (int) (S*100);
  129. //                /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑RGB转HSV算法↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/               
  130.                         }
  131.                         if(FlagStatus==1)
  132.                         {
  133.                         NUM_X++;
  134.                         X_FLAG+=i;
  135.                         }
  136.                 }
  137.                 Y_FLAG/=NUM_Y;
  138.                 X_FLAG/=NUM_X;
  139.                  ov_sta=0;                                        //清零帧中断标记
  140.                 ov_frame++;
  141.                 /****/
  142.                 LCD_Scan_Dir(DFT_SCAN_DIR);        //恢复默认扫描方向
  143.                 printf("X=%dY=%d\r\n",(int)X_FLAG,(int)Y_FLAG);        //打印帧率
  144.                 POINT_COLOR=WHITE;
  145.                 LCD_Draw_Circle((int)X_FLAG,(int)Y_FLAG,2);
  146.         }
  147. }

  148. int main(void)
  149. {         
  150.         u8 lightmode=0,effect=0;
  151.         s8 saturation=0,brightness=0,contrast=0;
  152.          
  153.         delay_init();                             //延时函数初始化         
  154.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
  155.         LCD_Init();                                           //初始化LCD  
  156.         uart_init(115200);
  157.         OV7725_Init();
  158.         OV7725_Window_Set(OV7725_WINDOW_WIDTH,OV7725_WINDOW_HEIGHT,0);//VGA模式输出
  159.         OV7725_Light_Mode(lightmode);
  160.         OV7725_Color_Saturation(saturation);
  161.         OV7725_Brightness(brightness);
  162.         OV7725_Contrast(contrast);
  163.         OV7725_Special_Effects(effect);
  164.         OV7725_CS=0;
  165.         SCCB_WR_Reg(0xa6, 0x26);
  166.         SCCB_WR_Reg(0x60, 0x80);
  167.         SCCB_WR_Reg(0x61, 0x80);//黑白
  168.         TIM6_Int_Init(10000,7199);
  169.         
  170.         EXTI8_Init();                                //使能定时器捕获                                
  171.          while(1)
  172.         {        
  173.                 OV7725_camera_refresh();//更新显示
  174.          }   
  175. }
复制代码

所有资料51hei提供下载:
(库函数版本,适合战舰STM32F1开发板)实验35 摄像头实验.rar (447.82 KB, 下载次数: 124)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

来自 2#
ID:250245 发表于 2018-6-4 13:58 | 只看该作者
得到圆形坐标部分我的想法是计算出LCD屏上的所有黑点的位置的平均值,这样能够得到准确的坐标,但是缺点就是这样做由于运算量大会降低摄像头的帧率,而且如果屏幕上出现了其他地方有黑点就会造成圆心坐标的误
网上有一个用于处理黑线的算法,我觉得可以在这里用到。以下是我从网上找来的:

6.  对一行中的数据,进行提取黑线的算法使用:边沿提取法。该算法对黑线反应灵敏、准确度高、抗干扰能力强。
7.  边沿提取算法步骤:对于每一行的像素,从左往右,检测高电平到低电平的负跳变,那么这时就检测到了左边的黑线边界,接着继续开始往右检测,出现低电平到高电平的跳变时,就出现了正跳变(1111000)的时候,就检测到了右边黑线的边界。(这里的高电平和低电平分别指代白色和黑色像素值)。  这时候就可以通过黑线的位置比较与摄像头轴线的偏离,那么就可以将相对的偏离计算出来。
8.  图像帧的处理:虽然边沿提取算法可以粗略的控制小车,但是当出现其他干扰信号时,可能会影响控制信号。那么解决办法就是将上面获取的每一行像素中黑色点位置进行干扰滤波,也就是帧处理。
9.  在帧数据的处理中,采用的算法是:提取连续段的方法,去掉图像中无用的错误数据。
10.           连续段提取算法的大致流程:1)提取以行为标准,如果隔着某些行,各个黑点之间的垂直距离是某种固定或者接近固定的阀值,那么这些连续的点,就构成了一段连续段。最好提取三个连续段。2)提取三个端中,再在其中最为可靠的端,例如上图中的连续段3,也就是这个段中,所包含的连续点越多越可靠。3)然后将可用端连起来,成为一个大段。可以将不可靠段使用插补的方法归算到大段中。
 差很大;


我的想法是这样的,由于摄像头的图像是从上往下再从左往右扫描的,我们可以一列一列的来对像素点进行处理,先看第一列,检测是否有负跳变(00001111白为0黑为1)那么就有可能检车到了圆,那么在检测正跳变,记录下坐标,这样我们就将第一行像素点的圆形部分得出来了。那么依次类推就可得出圆形的边界位置,在这个过程中肯定是有误判的;那么根据网友的说法,可以将偏离其他边界很远的坐标去掉酒可以得到圆形大致的边界了,最后就是圆心的计算,这也可以采用计算平均值的方法,当然还可以随即采取三个点因此我们要求的就是这三个点构成三角形的外接圆球心,从几何来说三角形外心是三角形三条边垂直平分线的交点,具体求法可以用两边的乘积除以第三边上的高(这样求出来是外接圆直径),直径出来了圆心就好求了。

评分

参与人数 1黑币 +100 收起 理由
admin + 100 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:341045 发表于 2018-6-4 08:05 | 只看该作者
正在作OV7725的东东, 参考下, 谢谢分享
回复

使用道具 举报

地板
ID:353347 发表于 2018-6-21 13:00 | 只看该作者
本帖最后由 17190187950 于 2018-6-21 13:24 编辑

谢谢分享
请问圆心坐标是什么,怎么输出?
回复

使用道具 举报

5#
ID:7922 发表于 2018-6-21 13:14 | 只看该作者
参考下, 谢谢分享
回复

使用道具 举报

6#
ID:250245 发表于 2018-6-23 20:21 | 只看该作者
lzts88 发表于 2018-6-4 08:05
正在作OV7725的东东, 参考下, 谢谢分享

用串口接收
回复

使用道具 举报

7#
ID:367587 发表于 2018-7-9 00:01 | 只看该作者
你好,这个源码有吗,能不能分享下
回复

使用道具 举报

8#
ID:367587 发表于 2018-7-9 00:02 | 只看该作者
wangxianlong 发表于 2018-6-4 13:58
得到圆形坐标部分我的想法是计算出LCD屏上的所有黑点的位置的平均值,这样能够得到准确的坐标,但是缺点就 ...

你好,这个源码能给我们提供下吗?
回复

使用道具 举报

9#
ID:379752 发表于 2018-7-27 10:30 | 只看该作者
楼主好厉害
回复

使用道具 举报

10#
ID:530797 发表于 2019-5-11 11:37 | 只看该作者
mini版可以用吗
回复

使用道具 举报

11#
ID:585168 发表于 2019-7-16 15:44 | 只看该作者
为什么我用了这个程序下载到32里面,复位或者重启以后程序就不能运行了呢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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