void GLogicProcessor::LoadFontMap(map<string,uniRecord>&fMap,string &fileName){ ifstream TibetanFontMap(fileName.c_str()); if( !TibetanFontMap ){ cout<<fileName<<" not found"<<END; return; } vector<string> srcStrings; string tString; vector<string>lineStrings; //short i=0; uniRecord record; vector<string> value; vector<string>::size_type d; wstring wstr; unsigned short data; //cout_<<"load map "<<fileName<<END; maxUniRecord=0; while (getline(TibetanFontMap, tString,'\n')){ srcStrings.push_back(tString); //cout<<"vector count="<<srcStrings.size()<<endl; lineStrings=explode(":|:",tString); //for(int i=0;i<lineStrings.size();i++)cout<<lineStrings[i]<<" "; wstr=L""; wstr+=UTF_to_Unicode(lineStrings[0]); //cout<<"lineStrings="<<tString<<" wstr.size()="<<wstr.size()<<" wstr="<<Unicode_to_UTF(wstr)<<END; record.OCRKey=lineStrings[0]; record.Wylie=lineStrings[1]; if(lineStrings.size()>2){ //cout_<<"lineStrings.size()="<<lineStrings.size()<<" v="<<lineStrings[2]<<endl; record.keyUTF=lineStrings[2]; if(record.keyUTF.size()/3>maxUniRecord)maxUniRecord=(int)record.keyUTF.size()/3; //cout_<<" wstr="<<Unicode_to_UTF(wstr)<<" value.size()="<<value.size()<<END; //cout_<<" str="<<record.keyUTF<<" hex="<<lineStrings[0]<<"key="<<record.OCRKey<<"//"<<END; } if(lineStrings.size()>3){ //cout_<<"lineStrings.size()="<<lineStrings.size()<<" v="<<lineStrings[3]<<"/"<<endl; record.letterUTF=lineStrings[3]; //cout_<<" wstr="<<Unicode_to_UTF(wstr)<<END; } fMap[record.OCRKey]=record; //cout<<"fMap["<<record.OCRKey<<"]="<<fMap[record.OCRKey].keyUTF<<"//"<<END; exit(0); } //cout_<<"fontMap[str][letter].OCRKey"<<fontMap["Dederis-a"][" "].keyUTF<<"//"<<END; //cout_<< "fMap.size()="<<fMap.size()<<" maxUniRecord="<<maxUniRecord<<endl; return; };//____________________________________________________________________________
void GLogicProcessor::buildOpenType(vector<OCRMatch>&line,vector<OCRMatch>&letterLine){ //формируем массив букв OpenType с координатами соответсвующими позиции элемента стековой буквы //относительно родительской буквы int print=0; for(int i=0;i<line.size();i++){ //cout<<"i="<<i<<" c="<<line[346].correlation<<endl; if(!line[i].correlation)continue; string name=line[i].name; line[i].setSize(); //print=0; if(i==112)print=1; if(!print)continue; DR("line["<<i<<"].name="<<line[i].name<<"/ OCRIndex="<<line[i].OCRIndex<<endl) wstring wName=UTF_to_Unicode(line[i].name); if(line[i].OCRIndex=='Z'||line[i].OCRIndex=='S'){ line[i].uni=wName[0]; line[i].status=0; line[i].Character=0; letterLine.push_back(line[i]); continue; } int index=fontGMap->getHKey(name,8); TString strT; fontTable->getTStr(index,&strT); DR("name="<<strT[8]<<" OCRIndex = "<<strT[4]<<endl) if(strT.size()<5||(strT[1]!="tib"&&strT[1]!="eng"&&strT[1]!="skt")){continue; } string OCRIndex=strT[4]; if(line[i].OCRIndex=='S')OCRIndex="S"; if(wName.size()==1||OCRIndex=="Z"){ //переводим все буквы в верхний регистр wName[0]=UniBigLetters[wName[0]]; line[i].name=Unicode_to_UTF(wName); DR("n="<<line[i].name<<" i="<<letterLine.size()<<endl) line[i].uni=wName[0]; line[i].status=0; line[i].Character=0; line[i].OCRIndex=OCRIndex[0]; letterLine.push_back(line[i]); }else{ for(int j=0;j<wName.size();j++){ OCRMatch match; wstring w; w=wName[j]; //переводим все буквы в верхний регистр w[0]=UniBigLetters[w[0]]; DR(" OCRLetter = "<<Unicode_to_UTF(w)<<" / "<<OCRIndex[j]) DR(" x0="<<line[i].x0<<" x1="<<line[i].x1<<" y0="<<line[i].y0<<" y1="<<line[i].y1<<endl) match.name=Unicode_to_UTF(w); match.correlation=line[i].correlation; match.letterIndex=line[i].letterIndex; match.OCRIndex=OCRIndex[j]; match.uni=w[0]; match.status=1; //помечаем букву как строительный элемент OpenType match.Character=100; //помечаем букву как строительный элемент OpenType if(wName.size()==1){match.status=0; match.Character=0;} //помечаем букву как одиночную if(OCRIndex[j]=='A'&&OCRIndex.size()==1){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; match.y0=line[i].yCenter-line[i].letterH/2; match.y1=line[i].yCenter+line[i].letterH/2; match.letterH=line[i].letterH; match.letterW=line[i].letterW; } if(OCRIndex=="S"){ //режим распознавания в котором стеки не разбираем на OpenType match.x0=line[i].x0; match.x1=line[i].x1; match.y0=line[i].y0; match.y1=line[i].y1; match.letterH=line[i].letterH; match.letterW=line[i].letterW; match.name=line[i].name; match.wName=wName; match.Character=0; match.OCRIndex='S'; match.status=0; for(int j=0;j<wName.size();j++){ wstring w; w=wName[j]; //переводим все буквы в верхний регистр w[0]=UniBigLetters[w[0]]; match.uni+=w[0]; } match.setSize(); letterLine.push_back(match); break; } if(OCRIndex[j]=='A'&&OCRIndex.size()>1){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; if(OCRIndex[OCRIndex.size()-1]=='V'){ match.y0=line[i].yCenter-line[i].letterH/2+line[i].letterW*0.75; match.y1=match.y0+line[i].letterH/(int)OCRIndex.size(); }else{ if((OCRIndex[1]=='W'||OCRIndex[1]=='R')&&OCRIndex.size()==2){ match.y0=line[i].yCenter-line[i].letterH/2; match.y1=match.y0+line[i].letterH-20; }else{ match.y0=line[i].yCenter-line[i].letterH/2; match.y1=match.y0+line[i].letterH/(int)OCRIndex.size(); } } match.letterH=line[i].letterW; match.letterW=line[i].letterW; } if(OCRIndex[j]=='B'|| OCRIndex[j]=='C'|| OCRIndex[j]=='D'|| OCRIndex[j]=='E'|| OCRIndex[j]=='F'|| OCRIndex[j]=='G'|| OCRIndex[j]=='H'){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; if(OCRIndex.size()>1){ match.y0=letterLine[letterLine.size()-1].y0+line[i].letterH/(int)OCRIndex.size(); }else{ match.y0=line[i].y0; } match.y1=match.y0+line[i].letterH/(int)OCRIndex.size(); match.letterH=match.y1-match.y0; match.letterW=line[i].letterW; } if(OCRIndex[j]=='R'){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; if(OCRIndex.size()>1){ if(OCRIndex[OCRIndex.size()-1]=='R'){ match.y0=line[i].y1-20; match.y1=match.y0+20; }else{ match.y0=letterLine[letterLine.size()-1].y1; match.y1=match.y0+20; } }else{ match.y0=line[i].y0; match.y1=line[i].y1; } match.letterH=match.y1-match.y0; match.letterW=line[i].letterW; } if(OCRIndex[j]=='W'){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; if(OCRIndex.size()>1){ if(OCRIndex[OCRIndex.size()-1]=='W'){ match.y0=line[i].y1-20; match.y1=match.y0+20; }else{ match.y0=letterLine[letterLine.size()-1].y1; match.y1=match.y0+20; } }else{ match.y0=line[i].y0; match.y1=line[i].y1; } match.letterH=match.y1-match.y0; match.letterW=line[i].letterW; } if(OCRIndex[j]=='V'||OCRIndex[j]=='Z'||OCRIndex[j]=='X'){ match.x0=line[i].xCenter-line[i].letterW/2; match.x1=line[i].xCenter+line[i].letterW/2; match.y0=line[i].yCenter-line[i].letterH/2; match.y1=match.y0+20; match.letterH=match.y1-match.y0; match.letterW=line[i].letterW; match.name=line[i].name; } DR(" x0="<<match.x0<<" x1="<<match.x1<<" y0="<<match.y0<<" y1="<<match.y1<<endl) DR(" letterLine.size()="<<letterLine.size()<<" @@@"<<match.name<<endl) match.setSize(); letterLine.push_back(match); //дополняем массив похожими по начертанию буквами /* if(match.name=="ཞ"){ OCRMatch match_=match; match_.name="ན"; match_.wName=UTF_to_Unicode("ན"); match_.uni=match_.wName[0]; match_.correlation-=5; letterLine.push_back(match_); } */ } } } }
void GLogicProcessor::renderDictSearch(map<vector<short>,int>&searchResult, vector<OCRMatch>&dLine, vector<OCRMatch>&originalMatch, vector<OCRMatch>&pageText){ int print=0; DR(" searchResult.size()="<<searchResult.size()<<" dLine()="<<dLine.size()) vector<OCRMatch>wordLine; //TIME_START //в dLine[] записаны пары букв из которых словарь собирал фразы //для окончательной сборки фразы нужны найденные с словаре фразы, составленные из оригинальных пар букв //также нужны сами пары букв для частей фразы на которые не найдены ответы словаря //каждый OCRMatch содержит два массива, в которые записана информация о парах букв, составляющих фразу. // .line[] содержит индекс пар букв и возвращается заполненным в searchResult как результат работы словаря // .letter[] содержит копию пары букв по индексу line[] из исходного массива dLine[] for(int i=0;i<originalMatch.size();i++){ originalMatch[i].setSize(); } map<vector<short>,int>::iterator it; for (it = searchResult.begin(); it != searchResult.end(); ++it) { OCRMatch word; int in=abs(it->first[0]); //знаком значения записано есть ли по мнению словаря разделитель слогов в этой паре word.x0=dLine[in].x0; word.y0=dLine[in].y0; word.xL0C=dLine[in].letter[0].xCenter; int d; int sizeStr=0; while(sizeStr<128){ d=it->first[sizeStr]; DR(d<<" ") if(d==32767)break; //32767 маркирует конец строки word.line.push_back(d); sizeStr++; } d=abs(word.line[word.line.size()-1]); word.x1=dLine[d].x1; word.y1=dLine[d].y1; word.xL1C=dLine[d].letter[1].xCenter; word.correlation=0; int n; for(int i=0;i<sizeStr;i++){ //DR(searchResult[i].line[j]<<" c="<<line[searchResult[i].line[j]].correlation; //DR(" searchResult["<<i<<"].line.size()="<<searchResult[i].line.size()<<" ind="<<searchResult[i].line[j]) n=abs(it->first[i]); word.wName+=dLine[n].wName[0]; word.correlation+=dLine[n].correlation; } word.wName+=dLine[n].wName[1]; word.correlation=word.correlation/sizeStr+(float)(sizeStr*100)/50+(float)(it->second)/5000; //учитываем длину и вероятность фразы //word.correlation+=it->second; //прибавляем к кореляции количество ответов словаря //word.correlation=word.line.size(); //if(word.correlation<70)continue; word.name=Unicode_to_UTF(word.wName); DR("Yagpo= "<<word.name<<" "<<endl) word.name=YagpoToUni(word.name); DR("xL0C="<<word.xL0C<<"xL1C="<<word.xL1C<<" n="<<word.name<<endl); DR(word.name<<"/"<<"c="<<word.correlation<<" x0="<<word.x0<<" x1="<<word.x1<<" y0="<<word.y0<<" y1="<<word.y1<<endl) wordLine.push_back(word); } //drawGrapeLine(wordLine); exit(0); //результаты словаря с записаными в разделители букв знаками препинания и расставленными слогами //drawGrapeLine(originalMatch); exit(0); //результаты распознавания //drawGrapeLine(dLine); exit(0); //пары букв с записанными в разделители букв знаками препинания //print=1; //добавляем распознанные пары букв for(int i=0;i<dLine.size();i++){ if(!dLine[i].correlation)continue; //значение уже записано OCRMatch word=dLine[i]; word.name=Unicode_to_UTF(word.wName); //DR("Yagpo= "<<word.name<<" ") word.name=YagpoToUni(word.name); word.line=dLine[i].line; word.line.push_back(i); wordLine.push_back(word); } for(int i=0;i<wordLine.size();i++){ wordLine[i].status=0; wordLine[i].allMatchCount=1; wordLine[i].setSize(); //DR(" wordLine[i]="<<wordLine[i].name<<" w="<<wordLine[i].letterW) } sort(wordLine.begin(),wordLine.end(),sortMatchX0); compressMatch(wordLine); //drawGrapeLine(wordLine); exit(0); //int count=(int)wordLine.size(); //int step=0; print=0; //проверяем ответы словаря на здравый смысл. Пары букв из которых составлен ответ словаря не должны отменять //уверенно распознанные буквы //также убираем пустые значения vector<OCRMatch>wLine; for(int i=0;i<wordLine.size();i++){ if(!wordLine[i].correlation)continue; wordLine[i].status=0; DR("wordLine["<<i<<"].name="<<wordLine[i].name<<endl); if(wordLine[i].line.size()>1){ //для полученных фраз удобнее хранить исходные пары букв внутри фразы for(int j=0;j<wordLine[i].line.size();j++){ DR(" ind="<<wordLine[i].line[j]<<" size="<<wordLine[i].line.size()) DR(" n="<<dLine[abs(wordLine[i].line[j])].name<<" d="<<dLine[abs(wordLine[i].line[j])].letter[0].delimeter<<endl) wordLine[i].letter.push_back(dLine[abs(wordLine[i].line[j])].letter[0]); //wordLine[i].letter.push_back(dLine[abs(wordLine[i].line[j])].letter[1]); if(wordLine[i].line[j]<0){ //если в паре по мнению словаря есть разделитель слога (минус маркирует такие пары) /@@@ wordLine[i].letter[wordLine[i].letter.size()-1].delimeter=dLine[abs(wordLine[i].line[j])].letter[0].delimeter; if(wordLine[i].letter[wordLine[i].letter.size()-1].delimeter=="")wordLine[i].letter[wordLine[i].letter.size()-1].delimeter="་"; } } wordLine[i].letter.push_back(dLine[abs(wordLine[i].line[wordLine[i].line.size()-1])].letter[1]); } //if(wordLine[i].letter.size()==1){ //нормализуем одиночные пары букв // wordLine[i].letter[0].delimeter=wordLine[i].delimeter; // } wLine.push_back(wordLine[i]); } //drawGrapeLine(wLine); exit(0); //полученные в результате подготовки в renderDictSearch части фразы собираем в целые фразы //на этом этапе фразы собираются вместе ограничителями слогов и знаками препинания и примечаниями внутри фразы. sentenceConstructur(wLine); //drawGrapeLine(wLine); exit(0); //расставляем ограничители слогов (точки) print=0; string str; wstring delimeter; for(int n=0;n<originalMatch.size();n++){ originalMatch[n].setSize(); } print=0; for(int i=0;i<wLine.size();i++){ if(!wLine[i].correlation)continue; DR(wLine[i].name<<endl) wLine[i].wName=L""; for(int n=0;n<wLine[i].letter.size();n++){ str=wLine[i].letter[n].delimeter; //cout<<"d="<<str; str=UnicodeToYagpo(str); delimeter=UTF_to_Unicode(str); wLine[i].wName+=wLine[i].letter[n].wName[0]+delimeter; DR(" n="<<wLine[i].letter[n].name<<"d="<<str<<"/"<<endl) } wLine[i].wName+=wLine[i].letter[wLine[i].letter.size()-1].wName[1]; wLine[i].name=Unicode_to_UTF(wLine[i].wName); wLine[i].name=YagpoToUni(wLine[i].name); DR(" n="<<wLine[i].name<<endl) wLine[i].correlation+=3; //создаем приоритет над парами без расставленных ограничителей слогов //добавляем результат к массиву исходных букв (результат распознавания включая все распознанные буквы и символы) //это позволит разобрать части фразы, не закрытые словарными ответами //x0=wLine[i].x0; x1=wLine[i].x1; //for(int n=0;n<dLine.size();n++){ // if(dLine[n].x0>=x0&&dLine[n].x1<=x1)dLine[n].correlation=0; //} //wLine[i].correlation=100; dLine.push_back(wLine[i]); //DR(wLine[i].name) } //добавляем все исходные графические элементы. Это нужно для распознования отдельно стоящих букв и знаков препинания for(int i=0;i<originalMatch.size();i++)dLine.push_back(originalMatch[i]); for(int i=0;i<dLine.size();i++)dLine[i].setSize(); sort(dLine.begin(),dLine.end(),sortMatchXCenter); //drawGrapeLine(dLine); exit(0); print=0; //убираем фразы внутри стыкованной фразы int limit; for(int n=0;n<dLine.size();n++){ if(!dLine[n].correlation)continue; if(dLine[n].y0>y1Base)dLine[n].correlation=0; //print=0;if(n==13)print=1; if(!print)continue; DR("@@@@"<<n<<" Collect n="<<dLine[n].name<<" d="<<dLine[n].delimeter<<endl) for(int m=0;m<dLine.size();m++){ if(!dLine[m].correlation)continue; //print=0;if(m==16)print=1; if(m==n)continue; limit=12; if(dLine[n].OCRIndex!='N'&&dLine[m].OCRIndex=='N')limit=0; if(dLine[n].OCRIndex!='Z'&&dLine[m].OCRIndex=='Z')limit=0; if(dLine[n].OCRIndex=='N'&&dLine[m].OCRIndex=='N')limit=0; if(dLine[n].OCRIndex=='Z'&&dLine[m].OCRIndex=='Z')limit=4; if(dLine[n].OCRIndex=='Z'&&dLine[m].OCRIndex!='Z')limit=0; if(dLine[n].OCRIndex=='S'&&dLine[m].OCRIndex=='S')limit=0; if(dLine[m].xCenter>dLine[n].x0-limit&&dLine[m].xCenter<dLine[n].x1+limit){ DR("n"<<n<<"="<<dLine[n].name<<" d="<<dLine[n].delimeter<<" c="<<dLine[n].correlation<<" m"<<m<<"="<<dLine[m].name <<" c="<<dLine[m].correlation<<" xmC="<<dLine[m].xCenter<<" xnC="<<dLine[n].xCenter<<" xnX0="<<dLine[n].x0<<" xnX1="<<dLine[n].x1<<" wM="<<dLine[m].letterW<<" wN="<<dLine[n].letterW<<endl); if(dLine[n].correlation>dLine[m].correlation){ if(dLine[n].letterW>dLine[m].letterW-limit||(dLine[n].letterW/dLine[m].letterW)>1.3){ DR(100) DR("REMOVE M "<<m<<" cM="<<dLine[m].correlation<<" wM="<<dLine[m].letterW<<" cN="<<dLine[n].correlation<<" wN="<<dLine[n].letterW<<endl) dLine[m].correlation=0; }else{ DR(200) if(dLine[n].correlation-dLine[m].correlation>5){ //предпочтение отдаем более широким буквам dLine[m].correlation=0; DR("REMOVE M1 "<<m<<" cN="<<dLine[n].correlation<<endl) }else{ DR("REMOVE N "<<m<<" cN="<<dLine[n].correlation<<endl) dLine[n].correlation=0; break; } } }else{ if(dLine[m].letterW>dLine[n].letterW-limit||(dLine[n].letterW/dLine[m].letterW)<1.3){
//новая версия грамматического анализатора. //текст реконструируется на основе вероятностного анализа результатов распознавания //с применением взаимной корреляции частей разных букв. Слоги и слова реконструируются //на основе вероятносного анализа корпуса тибетских текстов и правил построения тибетского шрифта. void GLogicProcessor::letterAssociation(vector<stringOCR>&strArray, vector<OCRMatch>&matchLine, vector<OCRMatch>&dLine, GBitmap* lineImg32, GBitmap* letterAImg, GBitmap* letterBImg, string &mainString, int sizeLine, int lineIndex){ int print=0; int OCRMode=inputData.OCRMode; TIME_START y0Base=strArray[lineIndex].LimY0; y1Base=strArray[lineIndex].LimY1; DR("@@@y0Base"<<y0Base<<" y1Base="<<y1Base<<" s="<<matchLine.size()) //for(int i=0;i<matchLine.size();i++)if(matchLine[i].letterIndex==15650){cout<<"@@@@@";exit(0);} //drawGrapeLine(matchLine); exit(0); if(!matchLine.size()||!strArray.size())return; // //для каждой буквы определяем количесво точек фокальных линий текста, совпадающих с областью ON всех масок буквы. //таким образом определем настолько область ON этой буквы совпадает с текстом. OCRBox s; for (int i=0;i<matchLine.size();i++){ if(!matchLine[i].correlation)continue; letterAImg->fillColumns32V(0, &matchLine[i].s); //стираем букву matchLine[i].drawPict32(letterAImg,0,0,XOR_MODE); matchLine[i].pCount=lineImg32->img32UnionLine(letterAImg, &matchLine[i].s); //if(i==518)cout<<i<<" "<< matchLine[i].name<<" pCount="<<matchLine[i].pCount<<endl; } compressMatch(matchLine); //drawGrapeLine(matchLine); exit(0); letterConstruction(matchLine,OCRMode); //drawGrapeLine(matchLine); exit(0); //#ifndef OCR_woodblock //на этом этапе в matchLine записано около 50 результатов на одну букву текста //заменяем одинаковые буквы на букву с наибольшей корреляцией и наибольшей общей площадью совпадающей с изображением на странице. //также для каждой гипотезы распознанной буквы проверяем перекрытие с соседними буквами //оставляем только те буквы, которые лучше описывают соответствующие площади буквы области изображения. // letterNeighborsNew(matchLine,lineImg32,letterAImg,letterBImg); //#else letterNeighborsNew(matchLine,lineImg32,letterAImg,letterBImg); //#endif //drawGrapeLine(matchLine); exit(0); for(int i=0;i<matchLine.size();i++){ if(matchLine[i].correlation){ matchLine[i].status=0; dLine.push_back(matchLine[i]); } } //компрессия. Все одинаковые буквы в пределах габарита буквы //заменяются на одну букву с макcмимальной корреляцией compressMatch(dLine); for(int i=0;i<dLine.size();i++){ if(!dLine[i].correlation||!dLine[i].name.size())continue; wstring w; w=UTF_to_Unicode(dLine[i].name); //переводим все буквы в верхний регистр w[0]=UniBigLetters[w[0]]; dLine[i].uni=w[0]; } //drawGrapeLine(dLine); exit(0); if(print){TIME_PRINT_ DR("STACK")}; //drawGrapeLine(dLine); exit(0); if(OCRMode==1){ collectStackLetter(strArray,dLine, matchLine,lineImg32,letterAImg,letterBImg,lineIndex); //cout<<"COLLECT"; TIME_PRINT_ //exit(0); //drawGrapeLine(matchLine);exit(0); compressMatch(matchLine); }else{ matchLine=dLine; return; } //drawGrapeLine(matchLine);exit(0); //#ifndef OCR_woodblock //анализ готовых стеков. //проверяем есть ли над или под одиночной буквой коренные буквы или огласовки с высокой корреляцией. //если есть, то букву считаем частью стека и убираем как строительный блок OpenType. // testStackLetter(matchLine,lineImg32,letterAImg,letterBImg); //#endif for(int i=0;i<dLine.size();i++){ if(!dLine[i].correlation||(dLine[i].OCRIndex!='Z'&&dLine[i].OCRIndex!='N'))continue; matchLine.push_back(dLine[i]); } //drawGrapeLine(matchLine); exit(0); if(print){TIME_PRINT_} return; }