最近在用主控STM32H743与摄像头MT9V034做数字识别,今天刚解决数字识别中的字符切割。效果能用,但还需完善。
原理:主要用了投影法,先进行垂直投影,找出多个字符的左右边框,再对每个字符单独水平投影,捕获该字符的上下边框。原理很简单,下面是程序流程图:
下面是程序源码:
typedef struct{
uint16_t UpLine;
uint16_t DownLine;
uint16_t LeftLine;
uint16_t RightLine;
}CharPosInfTypeDef;
typedef struct{
uint16_t VerHisGram[IMAGEW]; // 垂直方向投影
uint16_t HorHisGram[IMAGEH]; // 水平方向投影
uint16_t VerStartIndex;
uint16_t VerEndIndex;
uint8_t VerFlag; //进入字符区标志位
uint16_t HorStartIndex;
uint16_t HorEndIndex;
uint8_t HorFlag;
uint16_t SumChar;
CharPosInfTypeDef X_PosInf[50];
CharPosInfTypeDef CharPosInf[100]; //字符信息
uint8_t *Pro_Pixels; // 框中字符区域的像素
}NumberSegTypeDef2;
CharPosInfTypeDef* SegmentionChar2(uint8_t *pixels,int height,int width)
{
uint8_t HorIndex=0,VerIndex=0,i=0;
step1:
for(uint16_t y=0;y<height;y++){
for(uint16_t x=0;x<width;x++){
if(pixels[y*width+x]==0xff){
NumberSeg.VerHisGram[x]++;
}
}
}
//VerFlag=0:空白区 VerFlag=1:字符区
for(uint16_t x=0;x<width;x++){
if(NumberSeg.VerHisGram[x]!=0&&NumberSeg.VerFlag==0){ //进入字符区
NumberSeg.VerFlag=1;
NumberSeg.VerStartIndex=x;
}
else if(NumberSeg.VerHisGram[x]==0&&NumberSeg.VerFlag==1){ //退出字符区
NumberSeg.VerEndIndex=x;
NumberSeg.VerFlag=0;
NumberSeg.X_PosInf[VerIndex].LeftLine=NumberSeg.VerStartIndex;
NumberSeg.X_PosInf[VerIndex++].RightLine=NumberSeg.VerEndIndex;
}
}
step2:
for(uint16_t y=0;y<height;y++){
for(uint16_t x=NumberSeg.X_PosInf[HorIndex].LeftLine;x<NumberSeg.X_PosInf[HorIndex].RightLine;x++){
if(pixels[y*width+x]==0xff){
NumberSeg.HorHisGram[y]++;
}
}
}
for(uint16_t y=0;y<height;y++){
if(NumberSeg.HorHisGram[y]!=0&&NumberSeg.HorFlag==0){
NumberSeg.HorFlag=1;
NumberSeg.HorStartIndex=y;
}
else if(NumberSeg.HorHisGram[y]==0&&NumberSeg.HorFlag==1){
NumberSeg.HorEndIndex=y;
NumberSeg.HorFlag=0;
NumberSeg.CharPosInf[i].LeftLine=NumberSeg.X_PosInf[HorIndex].LeftLine;
NumberSeg.CharPosInf[i].RightLine=NumberSeg.X_PosInf[HorIndex].RightLine;
NumberSeg.CharPosInf[i].UpLine=NumberSeg.HorStartIndex;
NumberSeg.CharPosInf[i++].DownLine=NumberSeg.HorEndIndex;
}
}
step3:
if(HorIndex==VerIndex){
NumberSeg.SumChar=i;
return NumberSeg.CharPosInf;
}
else{
HorIndex++;
memset(NumberSeg.HorHisGram,0,sizeof(NumberSeg.HorHisGram));
goto step2;
}
}
返回的指针是指向存储字符位置信息的数组地址。