OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3355|回复: 9

车牌边缘检测算法与程序,定位不准

[复制链接]

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
发表于 2018-5-31 00:43:53 | 显示全部楼层 |阅读模式
1金钱
网上查到的资料,实现车牌边缘检测,分割出车牌区域,再进行处理,现在是定位不准,老是不能检测到车牌边缘,现将全部算法贴出,[mw_shl_code=c,true]#include "RECOG.h"
#include "board.h"
#include "lcd.h"
#include "ov7671.h"
#include "delay.h"
#include "text.h"
#include "sys.h"
#include "stdio.h"
#define OV7725_WRST                PDout(6)                //写指针复位
#define OV7725_WREN                PBout(3)                //写入FIFO使能
//---------------------------------------------------------------------------------------------------------------------字符定义区
u32 a;
u32 b;

u16 AA,BB;

u16 Min_blue;
u16 Max_blue;//定义车牌蓝色区域的横向最大值和最小值

u8 TableChangePoint_240[240];//横向跳变点最大值240个
u8 TableChangePoint_320[320];//纵向跳变点最大值320个

u32 table[240][320]={0};

//u16 color,color_r,color_b,color_g;//灰度化处理变量

u16 color_save;//保存一个像素的值

u8 R_a=20,G_a=45,B_a=20;//阈值(二值化)

//u8 R_a,G_a,B_a;       

u8 R,G,B;//颜色分量

u8 Max_ChangePoint_240,Min_ChangePoint_240,Max_bChangePoint,Min_bChangePoint;//跳变点纵轴始、末坐标,跳变点横轴始、末坐标,用于确定车牌范围

u8 flag_MaxMinCompare;//完成最大值最小值比较的标志,Max_aChangePoint_reset_1和Max_aChangePoint_reset的标志


float V,S,H;//定义HSV值,用于HSV转换函数



u16 k1,kk1,k2,kk2,k3,kk3,k4,kk4,k5,kk5,k6,kk6,k7,kk7,k8,kk8;//八个字符边界

u8 table_picture[150];//定义保存图片的数组,储存摄像头返回的数据

extern u8 Table[6300];//所有字符集 (10+26)*150 = 5400 字节
extern u8 talble_0[150];//字符3,测试用
extern u8 table_yu[32];//渝字
extern u8 table_min[32];//闽字
extern u8 table_lu[32];//鲁字
extern u8 table_zhe[32];//浙字
extern u8 table_shan[32];//陕字
extern u8 table_cuan[32];//川字

u8 table_char[36]={0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',};

u8 table_cardMeasure[7];//测量的车牌结果

u8 table_card[5][8]={        //保存5个车牌的二维数组
{0,0,0,0,0,0,0,0},                //最后一位保存时间
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
};

#define OV7670_WRST                PDout(6)                //写指针复位
#define OV7670_WREN                PBout(3)                //写入FIFO使能       

//----------------------------------------------------------------------------------------------------------240方向跳变点显示函数(纵)
void ChangePoint_Show_240()//240方向跳变点显示
{
        u16 a,b;
       
        for(a=0;a<240;a++)//显示对应的横向跳变点                                                               
        {
                for(b=0;b<320;b++)
           {
                  
                TableChangePoint_240[a]=LCD_ReadPoint(a,b);
                POINT_COLOR=RED;
                LCD_DrawPoint(TableChangePoint_240[a],a);//跳变点显示,红色标记
                if(TableChangePoint_240[a]>=15)                                        //跳变点个数(阈值)设定       阈值调节3-(1)
                {
                        for(b=35;b<40;b++)                                                //显示达到阈值标准的点
                        {
                                POINT_COLOR=GREEN;                  //暂时无用操作,后期修改
                                LCD_DrawPoint(b,a);//绿色标记               
                        }
                }
        }
}

//----------------------------------------------------------------------------------------------------------240方向车牌定位函数
void ChangePoint_Analysis_240()//240跳变点分析,即分析出车牌的纵向边界和高度
{
        Min_ChangePoint_240=240;Max_ChangePoint_240=0;
       
        for(a=0;a<240;a++)//240扫描        ,获取上下限值        :Min_ChangePoint_240,Max_ChangePoint_240                               
        {
                while(TableChangePoint_240[a]<=15)                                                                        //阈值调节3-(2)
                {
                        a++;
                }
                Min_ChangePoint_240=a;
                while(TableChangePoint_240[a]>15)                                                                        //阈值调节3-(3)
                {
                        a++;
                }
                Max_ChangePoint_240=a;
                if(Max_ChangePoint_240-Min_ChangePoint_240>=20) a=240;//连续性阈值           //阈值调节2-(1)
        }
        Min_ChangePoint_240=Min_ChangePoint_240-3;//向上微调3像素
        Max_ChangePoint_240=Max_ChangePoint_240+2;//向下微调2像素
       
        for(a=30;a<280;a++)//显示上界限                蓝色定位                 
        {
                POINT_COLOR=BLUE;
                LCD_DrawPoint(a,Max_ChangePoint_240);
        }
        for(a=30;a<280;a++)//显示下界限                                               
        {
                POINT_COLOR=BLUE;
                LCD_DrawPoint(a,Min_ChangePoint_240);
        }
        for(a=30;a<280;a++)//显示50,参考50像素位置处,车牌位置不能过红线,否则不能字符的归一化处理                                               
        {
                POINT_COLOR=RED;
                LCD_DrawPoint(a,Min_ChangePoint_240+50);
        }
        flag_MaxMinCompare=1;
        if(Min_ChangePoint_240>Max_ChangePoint_240)//判断合法性1:最小值>最大值
        {
                flag_MaxMinCompare=0;
        }
        if(Min_ChangePoint_240==240||Max_ChangePoint_240==0)//判断合法性2:值没有重新赋值
        {
                flag_MaxMinCompare=0;
        }
        if(Max_ChangePoint_240-Min_ChangePoint_240<15)                //判断合法性3:                        //阈值调节2-(2)
        {
                flag_MaxMinCompare=0;
        }
}

//-------------------------------车牌区域二值化显示-------------------------------------------------------------------
void Card_101Show()//车牌二值化显示函数
{
        u16 a,b,num_color;
        u8 R1,G1,B1;
        u8 Mid_ChangePoint_240;
        u8 max_R,max_G,max_B,min_R,min_G,min_B;
        u8 mid_R,mid_G,mid_B;
       
        max_R=0;max_G=0;max_B=0;
        min_R=30;min_G=60;min_B=30;
       
        Mid_ChangePoint_240=(Min_ChangePoint_240+Max_ChangePoint_240)/2;
        for(b=Min_blue;b<Max_blue;b++)
        {
                num_color=LCD_ReadPoint(b,Mid_ChangePoint_240);//读取像素点
                R1=num_color>>11;
                G1=(num_color>>5)&0x3F;
                B1=num_color&0x1F;
                if( (R1>10) && (G1>25) && (B1>15) && (R1<=30) && (G1<=60) && (B1<=30) )//
                {
                        if(max_R<R1) max_R=R1;//
                        if(max_G<G1) max_G=G1;
                        if(max_B<B1) max_B=B1;
                       
                        if(min_R>R1) min_R=R1;
                        if(min_G>G1) min_G=G1;
                        if(min_B>B1) min_B=B1;               
                }
        }
        mid_R=(max_R+min_R)/2;
        mid_G=(max_G+min_G)/2;
        mid_B=(max_B+        min_B)/2;
       
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)                                                               
        {
                for(b=Min_blue;b<Max_blue;b++)
                {
                        num_color=LCD_ReadPoint(b,a);//?áè?????£?′ú??ó??ˉ?ù?èóD′yìáéy £?é¨?è·?·¨ò2?éó??ˉ£?ò?ìáéy?ù?è
                        R1=num_color>>11;
                        G1=(num_color>>5)&0x3F;
                        B1=num_color&0x1F;
                        if((R1>=mid_R) && (G1>=mid_G) && (B1>=mid_B))//?t?μ?ˉ,???D?μ£o25.55.25£???o?êê?D?죨21,47,21£?
                        {
                                POINT_COLOR=0xffff;
                                LCD_DrawPoint(b,a);
                        }
                        else
                        {
                                POINT_COLOR=0x0000;
                                LCD_DrawPoint(b,a);
                        }
                }
        }
        delay_ms(20000);
}
//-------------------------------------------------------------------------------------------------------------



//------------------------------------------------------------------------------------------------颜色转换函数,为下面的车牌蓝色区域识别做准备

void RGB_HSV(u16 num)//RGB565转HSV  方便用于区分色相、饱和度、和VALUE
{
        float max,min;
        u8 r,g,b;
        r=(num>>11)*255/31;g=((num>>5)&0x3f)*255/63;b=(num&0x1f)*255/31;
       
        max=r;min=r;
        if(g>=min)max=g;
        if(b>=max)max=b;
        if(g<=max)min=g;
        if(b<=min)min=b;
       
        V=100*max/255;//转换为百分比
        S=100*(max-min)/max;//扩大100倍显示
        if(max==r) H=(g-b)/(max-min)*60;
        if(max==g) H=120+(b-r)/(max-min)*60;
        if(max==b) H=240+(r-g)/(max-min)*60;
        if(H<0) H=H-360;
}


//--------------------------------------------------------------------------------------------------------320方向蓝色区域的车牌定位函数
void ChangePoint_Analysis_Blue()//320蓝色区域分析,采用读取像素,得结果Min_blue,Max_blue
{                                                                                                                                 //目的是分析出车牌的左右边界,即车牌的横向宽度。
        u16 a,b,num_color;
        u16 min_320,max_320;//各行的最小、最大值
       
        Min_blue=0;Max_blue=320;
        min_320=320;max_320=0;
       
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)                                                               
        {
                for(b=30;b<320;b++)//不用到320    for(b=30;b<320;b++)
                {
                        num_color=LCD_ReadPoint(b,a);//读取像素,代码优化速度有待提升    扫描方法也可优化,以提升速度
                        RGB_HSV(num_color);//RGB565转HSV
                        if( 250>H && H>190 && 60>S && S>15 && 100>V && V>45)//HSV 阈值
                        {
                                if(b<min_320)//获得横轴的Min和Max值,即蓝色车牌的左右边界
                                {
                                        min_320=b;
                                }
                                if(b>max_320)
                                {
                                        max_320=b;
                                }
                        }
                }
        }
        Min_blue=min_320;//获取各行的最大值//修正一点
        Max_blue=max_320-5;//获取各行的最小值//修正一点
       
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)//显示左界限                               
        {
                POINT_COLOR=RED;
                LCD_DrawPoint(Min_blue,a);//LCD_DrawPoint(Min_blue,a,0xf800);
        }
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)//显示右界限                                       
        {
                POINT_COLOR=RED;
                LCD_DrawPoint(Max_blue,a);
        }
//         delay_ms(6000);
}
//-----------------------------------------------------------------------------------------------------蓝色区域的跳变点分析函数

void ChangePoint_Analysis_320()//蓝色区域中,320跳变点分析,获得TableChangePoint_320结果
{                                                                //(先二值化,再判断白点个数,=0则是分割线)
        u16 a,b,num_color;
        u8 R1,G1,B1;
        u8 Mid_ChangePoint_240;
        u8 max_R,max_G,max_B,min_R,min_G,min_B;
        u8 mid_R,mid_G,mid_B;
       
        max_R=0;max_G=0;max_B=0;
        min_R=30;min_G=60;min_B=30;
       
        Mid_ChangePoint_240=(Min_ChangePoint_240+Max_ChangePoint_240)/2;
        for(b=Min_blue;b<Max_blue;b++)
        {
                num_color=LCD_ReadPoint(b,Mid_ChangePoint_240);//读取像素,代码优化速度有待提升 ?扫描方法也可优化,以提升速度
               
                R1=num_color>>11;
                G1=(num_color>>5)&0x3F;
                B1=num_color&0x1F;

                R1=color&0xf800;
                color >>=5;
                G1=color&0x07e0;
                B1=color>>11;
               
                color_r = color&0xf800;
                                        color_b = color>>11;
                                        color >>=5;
                                        color_g =color&0x07e0;
               
                if( (R1>10) && (G1>25) && (B1>15) && (R1<=30) && (G1<=60) && (B1<=30) )//二值化,高阈值:25.55.25,较合适阈值(21,47,21)
                {
                        if(max_R<R1) max_R=R1;//获得最大值和最小值
                        if(max_G<G1) max_G=G1;
                        if(max_B<B1) max_B=B1;
                       
                        if(min_R>R1) min_R=R1;
                        if(min_G>G1) min_G=G1;
                        if(min_B>B1) min_B=B1;               
                }
        }
        mid_R=(max_R+min_R)/2;
        mid_G=(max_G+min_G)/2;
        mid_B=(max_B+        min_B)/2;


        for(b=0;b<320;b++)//各行跳变点计数,数组清零
        {
                TableChangePoint_320=0;
        }
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)                                                               
        {
                for(b=Min_blue+1;b<Max_blue;b++)
                {
                        num_color=LCD_ReadPoint(b,a);//读取像素,代码优化速度有待提升 ?扫描方法也可优化,以提升速度
                       
//                        R1=color&0xf800;
//                   color >>=5;
//                   G1=color&0x07e0;
//                   B1=color>>11;
                       
                        R1=num_color>>11;
                        G1=(num_color>>5)&0x3F;
                        B1=num_color&0x1F;
                        if((R1>=mid_R) && (G1>=mid_G) && (B1>=mid_B))//二值化,高阈值:25.55.25,较合适阈值(21,47,21)
                        {
                                POINT_COLOR=WHITE;
                                LCD_DrawPoint(b,a);
                                TableChangePoint_320++;//白色,跳变点+1
                        }
                        else
                        {
                                POINT_COLOR=BLACK;
                                LCD_DrawPoint(b,a);
                        }
                }
        }
}

//------------------------------------------------------------------------------------------------------------横向跳变点显示函数

void ChangePoint_Show_320()//320方向跳变点显示
{
        for(a=0;a<320;a++)//显示对应的横向跳变点                                                               
        {
                POINT_COLOR=RED;
                if(TableChangePoint_320[a]==0)
                {
                        LCD_DrawPoint(a,0);//跳变点显示,红色标记
                }
                else
                {
                        LCD_DrawPoint(a,TableChangePoint_320[a]);//跳变点显示,红色标记
                }
               
        }
}

//-------------------------------------------------------------------------------------------------------------字符分割函数

u8 ZhiFuFenGe()//字符分割,返回分割的字符个数,用于判断合法性
{
        u16 b;
        u8 i;//统计分割的字符个数,不为9说明分割有误
        i=0;//必须置0一下,不然会有错
        for(b=Max_blue;b>Min_blue;b--)
        {
                if(TableChangePoint_320==0)//间隙分割
                {
                        i--;b++;
                        while(TableChangePoint_320==0)
                        {
                                b--;
                                if(b<=Min_blue) break;
                        }
                }
        }
        i--;
        LCD_ShowNum(30,220,i,2,24);//显示分割的字符个数+1,8是正常值
        return i;
}

//-------------------------------------------------------------------------------------------------------------归一化处理函数 统一25*50

void GuiYi(u16 k,u16 kk)//归一化 25*50
{
        u16 a,b;
        u16 num;//保存读取像素
        u8 Mo,Yu;//取整和取模
        u8 num2,num3;
        u8 Mo_1;//
        u8 Min_240,Max_240;//框紧字符后的上下限
       
        if((k-kk)<25)
        {
                //框紧字符
                Min_240=Min_ChangePoint_240+1;
                Max_240=Max_ChangePoint_240-1;
                while(Min_240++)//框紧后,得到: Min_240
                {
                        for(b=kk-10;b<k;b++)//kk1→k1                                
                        {
                                num=LCD_ReadPoint(b,Min_240);
                                if(num) break;
                        }
                        if(num) break;
                }
                while(Max_240--)//框紧后,得到: Max_240
                {
                        for(b=kk+1;b<k;b++)//kk1→k1                                
                        {
                                num=LCD_ReadPoint(b,Max_240);
                                if(num) break;
                        }
                        if(num) break;
                }
                Min_240-=1;
                Max_240+=2;
                POINT_COLOR=WHITE;
                LCD_DrawPoint(kk,Min_240);//显示复制的图片
                LCD_DrawPoint( k,Max_240);//显示复制的图片
                //显示复制的图片
                num3=0;
                for(a=Min_240+1;a<Max_240;a++)
                {
                        num2=10;
                        for(b=kk+1;b<k;b++)//kk1→k1                                   +1
                        {
                                num=LCD_ReadPoint(b,a);
                                POINT_COLOR=num;
                                LCD_DrawPoint(271-(k-kk-1)+num2,191+num3);//复制像素值
                                num2++;
                        }
                        num3++;
                }
                num3=0;
                Mo=(24-(k-kk-1))/(k-kk-1);//取模
                Yu=(24-(k-kk-1))%(k-kk-1);//取余
                if(Yu!=0)
                {
                        Mo_1=24/Yu;//平均Mo_1个像素,插有一个像素,机7+1
                }

                for(a=Min_240+1;a<Max_240;a++)//宽放大为25像素  =??
                {//↓
                        num2=10;
                        Yu=(24-(k-kk-1))%(k-kk-1);//取余
                       
                        for(b=kk+1;b<k;b++)//kk1→k1                                   +1
                        {
                                num=LCD_ReadPoint(b,a);
                                POINT_COLOR=num;
                                LCD_DrawPoint(271+num2,191+num3);
                                num2++;
                                Mo=(24-(k-kk-1))/(k-kk-1);//取模
                                while(Mo)
                                {
                                        POINT_COLOR=num;
                                        LCD_DrawPoint(271+num2,191+num3);
                                        Mo--;
                                        num2++;
                                }
                                if(Yu!=0)//横轴拉长
                                {       
                                        if(((num2+1)%Mo_1==0) && (num2!=1))//改插入的地方7+1
                                        {
                                                POINT_COLOR=num;
                                                LCD_DrawPoint(271+num2,191+num3);
                                                Yu--;
                                                num2++;
                                        }
                                }
                        }
                        num3--;
                }
                POINT_COLOR=GREEN;
                LCD_DrawPoint(271,191);//标记点,4个顶角,绿色
                LCD_DrawPoint(271,240);
                LCD_DrawPoint(295,191);
                LCD_DrawPoint(295,240);
//纵轴拉长
                if((Max_240-Min_240)<50)
                {
                        Mo=(50-(Max_240-Min_240+1))/(Max_240-Min_240+1);//取模
                        Yu=(50-(Max_240-Min_240+1))%(Max_240-Min_240+1);//取余
                        Mo_1=50/Yu;
                       
//                         LCD_ShowNum(30,170,Mo,3);//                                        <调试用>
//                         LCD_ShowNum(70,170,Yu,3);//
//                         LCD_ShowNum(100,170,Max_ChangePoint_240-Min_ChangePoint_240,3);//
                        num2=0;
                        for(a=0;a<(Max_240-Min_240);a++)//复制图像,考虑范围是否需要进行修正?
                        {//↓
                                for(b=271;b<=295;b++)//271开始复制,295才结束
                                {
                                        num=LCD_ReadPoint(b,a+191);
                                        POINT_COLOR=num;
                                        LCD_DrawPoint(b+25,191+num2);//复制像素值
                                }
                                num2++;
                                while(Mo)
                                {
                                        for(b=271;b<=295;b++)//271开始复制,295才结束
                                        {
                                                num=LCD_ReadPoint(b,a+191);
                                                POINT_COLOR=num;
                                                LCD_DrawPoint(b+25,191+num2+a);//复制像素值
                                        }
                                        Mo--;
                                        num2++;
                                }
                                if(Yu!=0)
                                {
                                        if((((num2+1) % Mo_1)==0)&& (num2!=1))
                                        {
                                                for(b=271;b<=295;b++)//271开始复制,295才结束
                                                {
                                                        num=LCD_ReadPoint(b,a+191);
                                                        POINT_COLOR=num;
                                                        LCD_DrawPoint(b+25,191+num2);//复制像素值
                                                }
                                                Yu--;
                                                num2++;
                                        }
                                }                                       
                        }
                }
                POINT_COLOR=RED;
                LCD_DrawPoint(320,191);//标记点,1个顶角
                printf("正常");
        }
}

//------------------------------------------------------------------------------------------------------图片->数组table_picture  待修改  
void Picture_String()//图片->数组table_picture      有个BUG
{
        u16 a,b,num1;
        for(a=0;a<150;a++)//归零
        {
                table_picture[a]=0x00;       
        }       
        for(a=0;a<50;a++)//50排
        {
                for(b=0;b<24;b++)//24行
                {
                        num1=LCD_ReadPoint(b+296,a+191);
                        if(num1==0xffff)
                        {
                                table_picture[b/8+a*3]|=(1<<(7-b%8));
                        }
                }                               
        }
}

//-------------------------------------------------------------------------------------------------------------进行字符匹配

u8 MoShiShiBie_All(u8 begin,u8 end)//字符匹配,模式识别,选择性匹配begin-end
{
        u16 num_save;
        u8 a,b,e,a_save,st1,st2,s1,s2;
        int num1;
        for(a=begin;a<end;a--)                                        //36
        {
                num1=0;
                for(b=0;b<110;b++)
                {
                        st1=table_picture;
                        st2=Table[150*a+b];
                        for(e=0;e<8;e++)
                        {
                                s1=st1&(1<<e);
                                s2=st2&(1<<e);
                                if(s1==s2) num1++;
                                if(s1!=s2) num1--;
                        }
                }
                if(num_save<num1)
                {
                        num_save=num1;
                        a_save=a;
                }
//                LCD_ShowNum(50,220,a,2,24);//显示匹配的字符是"a"                        <调试用>
                LCD_ShowNum(70,220,num1,4,24);//显示匹配的正确像素数
                LCD_ShowNum(120,220,num_save,4,24);//匹配的最大值显示                                       
        }
        return a_save;
}

//--------------------------------------------------------------------------------------------------------------显示16X16的汉字

void WordShow(u8 num,u16 x,u16 y)//显示汉字16*16
{
        u16 a,b,num1;
        u8 table1[32];
        if(num==1)
        {
                for(a=0;a<32;a++)
                {
                        table1[a]=table_yu[a];       
                }               
        }
        if(num==2)
        {
                for(a=0;a<32;a++)
                {
                        table1[a]=table_min[a];       
                }               
        }
        if(num==3)
        {
                for(a=0;a<3;a++)
                {
                        table1[a]=table_lu[a];       
                }               
        }
        if(num==4)
        {
                for(a=0;a<32;a++)
                {
                        table1[a]=table_zhe[a];       
                }               
        }
        if(num==5)
        {
                for(a=0;a<32;a++)
                {
                        table1[a]=table_shan[a];       
                }               
        }
        if(num==6)
        {
                for(a=0;a<32;a++)
                {
                        table1[a]=table_cuan[a];       
                }               
        }
        for(a=0;a<16;a++)
        {
                for(b=0;b<16;b++)
                {
                        if(table1[b/8+a*2]&(1<<(7-b%8)))
                        {
                                num1=0xffff;
                        }
                        else
                        {
                                num1=0x0000;
                        }
                        POINT_COLOR=num1;
                        LCD_DrawPoint(b+x,a+y);//画点
                }                               
        }       
}

//-------------------------------------------------------------------------------------------------------------显示第几组车牌

void Show_Card(u8 i)//显示第几组车牌
{
        u16 t0;
//显示汉字
        if(table_card[0]!=0)
        {
                WordShow(table_card[0],9,i*16+50);//
        }
       
        if(table_card[1]<10)
        {
                LCD_ShowNum(25,i*16+50,table_char[table_card[1]],1,24);
        }
        else
        {
                LCD_ShowChar(25,i*16+50,table_char[table_card[1]],24,0);
        }
        LCD_ShowChar(33,i*16+50,'.',24,0);                                                                                                                //点
        if(table_card[2]<10)
        {
                LCD_ShowNum(41,i*16+50,table_char[table_card[2]],1,24);
        }
        else
        {
                LCD_ShowChar(41,i*16+50,table_char[table_card[2]],24,0);
        }
        if(table_card[3]<10)
        {
                LCD_ShowNum(49,i*16+50,table_char[table_card[3]],1,24);
        }
        else
        {
                LCD_ShowChar(49,i*16+50,table_char[table_card[3]],24,0);
        }
        if(table_card[4]<10)
        {
                LCD_ShowNum(57,i*16+50,table_char[table_card[4]],1,24);
        }
        else
        {
                LCD_ShowChar(57,i*16+50,table_char[table_card[4]],24,0);
        }
        if(table_card[5]<10)
        {
                LCD_ShowNum(65,i*16+50,table_char[table_card[5]],1,24);
        }
        else
        {
                LCD_ShowChar(65,i*16+50,table_char[table_card[5]],24,0);
        }
        if(table_card[6]<10)
        {
                LCD_ShowNum(73,i*16+50,table_char[table_card[6]],1,24);
        }
        else
        {
                LCD_ShowChar(73,i*16+50,table_char[table_card[6]],24,0);
        }
        t0=table_card[7];
        LCD_ShowNum(100,i*16+50,t0,6,24);//显示时间

        if(t0<60)
        {
                LCD_ShowNumPoint(168,i*16+50,t0*8);
        }
        else
        {
                LCD_ShowNumPoint(168,i*16+50,t0/60*500+t0%60*8);
        }
       
}

//-------------------------------------------------------------------------------------------------------------字符识别函数

void ZhiFuShiBie()//字符识别
{
        u16 a,b,u,i;
        u8 Result;//识别结果

        for(b=Max_blue-1;b>Min_blue;b--)//由右至左识别,获取各个字符的 K KK值, 即字符边界
        {
                while(TableChangePoint_320==0) b--;//取第1个字符
                k1=b+1;//+1
                while(TableChangePoint_320>0) b--;
                kk1=b;
                if((k1-kk1)<4)//省略低于三个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k1=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk1=b;
                }
                while(TableChangePoint_320==0) b--;//取第2个字符
                k2=b+1;
                while(TableChangePoint_320>0) b--;
                kk2=b;
                if((k2-kk2)<4)//省略低于3个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k2=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk2=b;
                }
                while(TableChangePoint_320==0) b--;//取第3个字符
                k3=b+1;//+1
                while(TableChangePoint_320>0) b--;
                kk3=b;
                if((k3-kk3)<4)//省略低于3个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k3=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk3=b;
                }
                while(TableChangePoint_320==0) b--;//取第4个字符
                k4=b+1;
                while(TableChangePoint_320>0) b--;
                kk4=b;
                if((k4-kk4)<4)//省略低于3个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k4=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk4=b;
                }
                while(TableChangePoint_320==0) b--;//取第5个字符
                k5=b+1;//+1
                while(TableChangePoint_320>0) b--;
                kk5=b;
                if((k5-kk5)<4)//省略低于3个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k5=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk5=b;
                }
                while(TableChangePoint_320==0) b--;//取第6个字符
                k6=b+1;
                while(TableChangePoint_320>0) b--;
                kk6=b;
                while(TableChangePoint_320==0) b--;//取第7个字符
                k7=b+1;//+1
                while(TableChangePoint_320>0) b--;
                kk7=b;
                if((k7-kk7)<4)//省略低于3个像素的位置
                {
                        while(TableChangePoint_320==0) b--;//
                        k7=b+1;//+1
                        while(TableChangePoint_320>0) b--;
                        kk7=b;
                }
                while(TableChangePoint_320==0) b--;//取第8个字符
                k8=b+1;
                while(TableChangePoint_320>0)
                {
                        if(b<=Min_blue)
                        {
                                break;
                        }
                        b--;
                }
                kk8=b;
                b=Min_blue;//以防万一,还满足for循环条件
        }
        for(a=Min_ChangePoint_240;a<Max_ChangePoint_240;a++)//划线
        {
                POINT_COLOR=BLUE;
                LCD_DrawPoint(k1,a+1);
                LCD_DrawPoint(kk1,a+1);
                LCD_DrawPoint(k2,a+1);
                LCD_DrawPoint(kk2,a+1);
                LCD_DrawPoint(k3,a+1);
                LCD_DrawPoint(kk3,a+1);
                LCD_DrawPoint(k4,a+1);
                LCD_DrawPoint(kk4,a+1);
                LCD_DrawPoint(k5,a+1);
                LCD_DrawPoint(kk5,a+1);
                LCD_DrawPoint(k6,a+1);
                LCD_DrawPoint(kk6,a+1);
                LCD_DrawPoint(k7,a+1);
                LCD_DrawPoint(kk7,a+1);
                LCD_DrawPoint(k8,a+1);
                LCD_DrawPoint(kk8,a+1);
        }
//归一化处理:大小为25*50
       
//第1个字符:
        GuiYi(k1,kk1);//归一化 24*24
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(0,36);//字符匹配,模式识别,返回a,0<= a <36
        if(Result<10)
        {
                LCD_ShowNum(240,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(240,220,table_char[Result],24,0);
        }
        table_cardMeasure[6]=Result;//保存识别的车牌结果
       
//第2个字符:
        GuiYi(k2,kk2);//归一化 25*50
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(0,36);//字符匹配,模式识别
        if(Result<10)
        {
                LCD_ShowNum(230,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(230,220,table_char[Result],24,0);
        }
        table_cardMeasure[5]=Result;//保存识别的车牌结果
       
        GuiYi(k3,kk3);//归一化 25*50
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(0,36);//字符匹配,模式识别
        if(Result<10)
        {
                LCD_ShowNum(220,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(220,220,table_char[Result],24,0);
        }
        table_cardMeasure[4]=Result;//保存识别的车牌结果
       
        GuiYi(k4,kk4);//归一化 25*50
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(0,36);//字符匹配,模式识别
        if(Result<10)
        {
                LCD_ShowNum(210,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(210,220,table_char[Result],24,0);
        }
        table_cardMeasure[3]=Result;//保存识别的车牌结果
       
        GuiYi(k5,kk5);//归一化 25*50
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(0,36);//字符匹配,模式识别
        if(Result<10)
        {
                LCD_ShowNum(200,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(200,220,table_char[Result],24,0);
        }
        table_cardMeasure[2]=Result;//保存识别的车牌结果
        LCD_ShowChar(190,220,'.',24,0);

        GuiYi(k7,kk7);//归一化 25*50
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(10,36);//字符匹配,模式识别,只匹配字母
        if(Result<10)
        {
                LCD_ShowNum(180,220,table_char[Result],1,24);
        }
        else
        {
                LCD_ShowChar(180,220,table_char[Result],24,0);
        }
        table_cardMeasure[1]=Result;//保存识别的车牌结果
       
        GuiYi(k8,kk8);//归一化 25*50                                        最后一个汉字,不做识别
        Picture_String();//图片->数组
        Result=MoShiShiBie_All(36,42);//字符匹配,匹配汉字
        WordShow(Result-35,160,220);//显示汉字
        table_cardMeasure[0]=Result-35;//保存识别的车牌结果
        //识别结束
        //        while(1);
        //先匹配已保存的车牌号

        //---------------------------------------------------------------------------------------车牌匹配区

        for(u=0;u<5;u++)
        {
                for(i=0;i<7;i++)
                {
                        if(table_card!=table_cardMeasure) i=8;//退出for循环
                       
                }       
                if(i==7)//匹配成功
                {
                        LCD_Clear(0x00);//黑屏
                        Show_Card(u);//显示第几组车牌                       
                        delay_ms(15000);
                        u=5;
                }
        }
        if(i==9)//无匹配车牌,则保存车牌
        {
                i=0;
                while(1)
                {
                        if(GPIO_ReadInputDataBit(KEY1_PORT,KEY1_PIN)==0) break;
                        LCD_ShowNum(30,220,i/100,2,24);
                        if(i==300)                                                                                                                //保存数据
                        {
                                for(u=0;u<5;u++)
                                {
                                        if(table_card[0]==0)
                                        {
                                                for(i=0;i<7;i++)
                                                {
                                                        table_card=table_cardMeasure;
                                                }                                       
                                                u=5;//退出循环
                                        }
                                }
                                LCD_Clear(0x00);//黑屏
                                Show_Card(0);//显示第几组车牌
                                Show_Card(1);
                                Show_Card(2);
                                Show_Card(3);
                                Show_Card(4);
                                delay_ms(10000);
                                break;
                        }
                        delay_ms(1);
                        i++;
                }
        }
       
}


//------------------------------------------------------------------------------------------------------------车牌扫描函数体
extern u8 ov_sta;        //在exit.c里面定义
extern u8 ov_frame;        //在timer.c里面定义         

void Data_LCD_ColorChange()
{
        u8 i;
        u16 x,y;
        u32 table[240][320]={0};
        for(a=0;a<240;a++)//各行跳变点计数,数组清零
        {
                TableChangePoint_240[a]=0;
        }
//        for(x=0;x<320;x++)
//        {
//                for(y=0;y<240;y++)
//                {
//                        LCD_ReadPoint(x,y);
//                        table[x][y]=LCD_ReadPoint(x,y);
//                }
//        }
        Min_blue=320;//初始化记录蓝色车牌区域的值
        Max_blue=0;
        if(ov_sta)
        {
        LCD_Scan_Dir(R2L_U2D);
                if(lcddev.id==0X1963)LCD_Set_Window((lcddev.width-240)/2,(lcddev.height-320)/2,240,320);//将显示区域设置到屏幕中央
                else if(lcddev.id==0X5510||lcddev.id==0X5310)LCD_Set_Window((lcddev.width-320)/2,(lcddev.height-240)/2,320,240);//将显示区域设置到屏幕中央
                LCD_WriteRAM_Prepare();     //开始写入GRAM       
            PGout(0)=1;
                while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==1);
       
//                OV7725_RRST=0;                                //开始复位读指针
//                OV7725_RCK_L;
//                OV7725_RCK_H;
//                OV7725_RCK_L;
//                OV7725_RRST=1;                                //复位读指针结束
//                OV7725_RCK_H;
//       
        PDout(6)=0;  //先写入
        PDout(6)=1;           
        PBout(3)=1;  //写使能
       
       
        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==0);         //等待第二个同步信号
        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)==1);        
        PBout(3)=0;  //写禁止           
  
                OV7725_RRST=0;                                //开始复位读指针
                OV7725_RCK_L;
                OV7725_RCK_H;
                OV7725_RCK_L;
                OV7725_RRST=1;                                //复位读指针结束
                OV7725_RCK_H;
       
        for (a=0;a<320;a++)  //屏幕是320X240   这里是一行一行的扫描, 扫描240行
        {
                for(b=0;b<240;b++)                   //一列一列扫描,扫描320列
                {
                        OV7725_RCK_L;           //拉低电平  GPIOB->BRR=1<<4        //设置读数据时钟低电平
                        color=GPIOC->IDR&0xFF;            //读数据                高八位                               
                        OV7725_RCK_H;           //拉高电平  GPIOB->BSRR=1<<4//设置读数据时钟高电平  PB4
                        color<<=8;
                        OV7725_RCK_L;
                        color|=GPIOC->IDR&0xFF;            //读数据                低八位                                       
                        OV7725_RCK_H;         //拉高
                       
//                        color=(AA<<8)|BB;

                        R=color>>11;
                        G=(color>>5)&0x3f;
                        B=color&0x1f;
                       
                        if((R>R_a) && (G>=G_a) && (B>=B_a))//二值化,高阈值:25.55.25,较合适阈值(21,47,21)
                        {
                                color=0xffff;
                        }
                        else
                        {
                                color=0x0000;
                        }
                       
                        if(color!=color_save)//跳变点
                        {
                                TableChangePoint_240[a]++;                //该行跳变点计数+1
                        }
                        color_save=color;//保存像素值,供下一次判断和比较
                       
//                        color=(AA<<8)|BB;//还原色彩
                                       
                        LCD->LCD_RAM = color;     //ODR 数据输出寄存器---------------------------------------------------------------卡在了这里
                                //   LCD->LCD_REG时,A0=0.RS=0,相当于写命令,LCD->LCD_RAM,A0=0,RS=1,相当于写数据
                        ov_sta=0;                                        //清零帧中断标记
                       
                       
//                OV7725_WRST=0;                    //复位写指针                                   
//                OV7725_WRST=1;        //有问题!!!!!!!
                       
                }
        }
                
                  ov_frame++;
                  LCD_Scan_Dir(DFT_SCAN_DIR);        //恢复默认扫描方向
       
//        ChangePoint_Show_240();//240方向跳变点显示
//        ChangePoint_Analysis_240();        //跳变点分析
                                                        //返回flag_MaxMinCompare,Min_ChangePoint_240,Max_ChangePoint_240
        if(flag_MaxMinCompare==1)//跳变点筛选成功
        {
//                ChangePoint_Analysis_Blue();//320蓝色区域分析,采用读取像素,得结果Min_blue,Max_blue
                if(Min_blue>Max_blue) flag_MaxMinCompare=0;//进行合理性判断1
                if((Min_blue>290)||(Max_blue>290)) flag_MaxMinCompare=0;//进行合理性判断2
        }
        if(flag_MaxMinCompare==1)//跳变点筛选成功
        {
//                ChangePoint_Analysis_Blue();//320蓝色区域分析,采用读取像素,得结果Min_blue,Max_blue
//                 Card_101Show();//车牌区域二值化显示
//                ChangePoint_Analysis_320();//蓝色区域中,320跳变点分析,获得:TableChangePoint_320结果
//                ChangePoint_Show_320();//320方向跳变点显示
                i=ZhiFuFenGe();
               
                if(i==3)//字符分割,返回分割的字符个数,用于判断合法性
        while(1)
                {
                        ZhiFuShiBie();//字符识别
             
                }
                else
                {
                        LCD_Clear(0x0000);//黑屏,显示Measure Faill
                        LCD_ShowChar(8*1,200,'M',24,0);
                        LCD_ShowChar(8*2,200,'e',24,0);
                        LCD_ShowChar(8*3,200,'a',24,0);
                        LCD_ShowChar(8*4,200,'s',24,0);
                        LCD_ShowChar(8*5,200,'u',24,0);
                        LCD_ShowChar(8*6,200,'r',24,0);
                        LCD_ShowChar(8*7,200,'e',24,0);
                       
                        LCD_ShowChar(8*9,200,'F',24,0);
                        LCD_ShowChar(8*10,200,'a',24,0);
                        LCD_ShowChar(8*11,200,'i',24,0);
                        LCD_ShowChar(8*12,200,'l',24,0);
                        LCD_ShowChar(8*13,200,'l',24,0);

//delay_ms(800);
                }
        }
}
        }


[/mw_shl_code]请大家帮我看看,哪里不对啊,

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-5-31 01:13:55 | 显示全部楼层
回复

使用道具 举报

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
 楼主| 发表于 2018-5-31 06:55:10 | 显示全部楼层
正点原子 发表于 2018-5-31 01:13
楼主搞到啥程度了?

灰度化,二值化,都搞定了,现在卡在了边缘检测上。求帮忙啊,原子哥
回复

使用道具 举报

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
 楼主| 发表于 2018-5-31 21:39:25 | 显示全部楼层
原子哥,今天有解决了字符分割,就差字符匹配了
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-6-1 01:27:00 | 显示全部楼层
13969873363 发表于 2018-5-31 21:39
原子哥,今天有解决了字符分割,就差字符匹配了

牛。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

15

主题

406

帖子

0

精华

高级会员

Rank: 4

积分
795
金钱
795
注册时间
2015-3-26
在线时间
151 小时
发表于 2018-6-1 11:31:01 | 显示全部楼层
单片机么
回复

使用道具 举报

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
 楼主| 发表于 2018-6-2 00:16:35 | 显示全部楼层
对的,f1
回复

使用道具 举报

9

主题

141

帖子

1

精华

高级会员

Rank: 4

积分
606
金钱
606
注册时间
2017-1-3
在线时间
65 小时
发表于 2018-6-2 09:14:21 | 显示全部楼层
车牌是哪里来的,摄像头输入还是怎么的?
F1会不会吃不消啊,矩阵运算什么的
回复

使用道具 举报

16

主题

84

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
208
金钱
208
注册时间
2018-4-9
在线时间
111 小时
 楼主| 发表于 2018-6-2 10:09:00 | 显示全部楼层
车牌摄像头采集来的,f1立即处理,处理完再显示
回复

使用道具 举报

0

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
71
金钱
71
注册时间
2019-3-2
在线时间
14 小时
发表于 2019-4-26 12:33:42 | 显示全部楼层
13969873363 发表于 2018-6-2 10:09
车牌摄像头采集来的,f1立即处理,处理完再显示

lz现在进展如何了?

支持!
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 12:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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