//новая версия грамматического анализатора. //текст реконструируется на основе вероятностного анализа результатов распознавания //с применением взаимной корреляции частей разных букв. Слоги и слова реконструируются //на основе вероятносного анализа корпуса тибетских текстов и правил построения тибетского шрифта. void GLogicProcessor::letterAssociation(vector<stringOCR>*strArray, vector<OCRMatch>&matchLine, vector<OCRMatch>&dLine, GBitmap* lineImg32, string &mainString, int sizeLine, int lineIndex, int OCRMode){ int print=0; TIME_START y0Base=strArray[0][lineIndex].LimY0; y1Base=strArray[0][lineIndex].LimY1; DR("@@@y0Base"<<y0Base<<" y1Base="<<y1Base<<" s="<<matchLine.size()) GBitmap *letterAImg=GBitmap::create(lineImg32->columns(),lineImg32->rows(),BITMAP_32); GBitmap *letterBImg=GBitmap::create(lineImg32->columns(),lineImg32->rows(),BITMAP_32); #ifdef MAIN_MODE //for(int i=0;i<matchLine.size();i++)if(matchLine[i].letterIndex==15650){cout<<"@@@@@";exit(0);} //drawGrapeLine(matchLine); exit(0); sort(matchLine.begin(),matchLine.end(),sortMatchX0); //cout<<"strArray[0].size()="<<strArray[0].size()<<" matchLine.size()="<<matchLine.size()<<endl; if(!matchLine.size()||!strArray[0].size())return; // int count=0; //int maxH=45; //int maxCor=97; for(int i=0;i<matchLine.size();i++){ matchLine[i].setSize(); count=0; matchLine[i].correlationNew=0; /* if((matchLine[i].OCRIndex=='A'&& abs(matchLine[i].y0-y0Base)>3&& matchLine[i].correlation>maxCor&& matchLine[i].letterH>maxH)|| (matchLine[i].OCRIndex=='A'&& matchLine[i].y0<y0Base-3&& matchLine[i].correlation>98) ){ maxH=matchLine[i].letterH; maxCor=matchLine[i].correlation; y0Base=matchLine[i].y0; y1Base=y0Base+32; } */ if(!matchLine[i].correlation)continue; matchLine[i].status=0; } //drawGrapeLine(matchLine); exit(0); compressMatch(matchLine); //drawGrapeLine(matchLine); exit(0); //на этом этапе в matchLine записано около 50 результатов на одну букву текста //заменяем одинаковые буквы на букву с наибольшей корреляцией и наибольшей общей площадью совпадающей с изображением на странице. //также для каждой гипотезы распознанной буквы проверяем перекрытие с соседними буквами //оставляем только те буквы, которые лучше описывают соответствующие площади буквы области изображения. letterNeighborsNew(matchLine,lineImg32,letterAImg,letterBImg); //drawGrapeLine(matchLine); exit(0); #ifdef STACK_MODE //saveMatch(matchLine,"/2_2.match"); #endif for(int i=0;i<matchLine.size();i++){ if(matchLine[i].correlation){ matchLine[i].status=0; if(matchLine[i].OCRIndex!=3&&matchLine[i].correlationNew)matchLine[i].correlation=matchLine[i].correlationNew; dLine.push_back(matchLine[i]); } } DR("done match processing line.size()="<<dLine.size()) sort(dLine.begin(),dLine.end(),sortMatchX0); DR("@@@@@ SAVE MATCH") #ifdef STACK_MODE //saveMatch(dLine,"/2.match"); #endif #endif #ifdef STACK_MODE //readMatch(dLine,"/2.match"); #endif //компрессия. Все одинаковые буквы в пределах габарита буквы //заменяются на одну букву с макcмимальной корреляцией compressMatch(dLine); //drawGrapeLine(dLine); exit(0); collectStackLetter(strArray,dLine, matchLine,lineImg32,letterAImg,letterBImg,lineIndex); //cout<<"COLLECT"; TIME_PRINT_ //exit(0); //drawGrapeLine(dLine);exit(0); compressMatch(dLine); //drawGrapeLine(dLine);exit(0); //анализ готовых стеков. //проверяем есть ли над или под одиночной буквой коренные буквы или огласовки с высокой корреляцией. //если есть, то букву считаем частью стека и убираем как строительный блок OpenType. testStackLetter(dLine,lineImg32,letterAImg,letterBImg); //drawGrapeLine(dLine); exit(0); letterAImg->destroy(); letterBImg->destroy(); #ifdef STACK_MODE //saveMatch(line,"/2_1.match"); #endif if(print){TIME_PRINT_} return; }
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::classification(vector<stringOCR>&strArray, vector<OCRMatch>&matchLine, GBitmap* lineImg32, string &mainString, int sizeLine, int lineIndex){ int print=0; vector<OCRMatch>dLine; TIME_START y0Base=strArray[lineIndex].LimY0; y1Base=strArray[lineIndex].LimY1; DR("@@@y0Base"<<y0Base<<" y1Base="<<y1Base<<" s="<<matchLine.size()) GBitmap *letterAImg=GBitmap::create(lineImg32->columns(),lineImg32->rows(),BITMAP_32); GBitmap *letterBImg=GBitmap::create(lineImg32->columns(),lineImg32->rows(),BITMAP_32); #ifdef MAIN_MODE //for(int i=0;i<matchLine.size();i++)if(matchLine[i].letterIndex==15650){cout<<"@@@@@";exit(0);} //drawGrapeLine(matchLine); exit(0); sort(matchLine.begin(),matchLine.end(),sortMatchX0); //cout<<"strArray.size()="<<strArray[0].size()<<" matchLine.size()="<<matchLine.size()<<endl; if(!matchLine.size()||!strArray.size())return; // for(int i=0;i<matchLine.size();i++){ matchLine[i].correlationNew=0; if(!matchLine[i].correlation)continue; matchLine[i].status=0; } //drawGrapeLine(matchLine); exit(0); compressMatch(matchLine); //drawGrapeLine(matchLine); exit(0); //на этом этапе в matchLine записано около 50 результатов на одну букву текста //заменяем одинаковые буквы на букву с наибольшей корреляцией и наибольшей общей площадью совпадающей с изображением на странице. //также для каждой гипотезы распознанной буквы проверяем перекрытие с соседними буквами //оставляем только те буквы, которые лучше описывают соответствующие площади буквы области изображения. letterNeighborsNew(matchLine,lineImg32,letterAImg,letterBImg); //drawGrapeLine(matchLine); exit(0); #ifdef STACK_MODE //saveMatch(matchLine,"/2_2.match"); #endif for(int i=0;i<matchLine.size();i++){ if(matchLine[i].correlation){ matchLine[i].status=0; if(matchLine[i].OCRIndex!=3&&matchLine[i].correlationNew)matchLine[i].correlation=matchLine[i].correlationNew; dLine.push_back(matchLine[i]); } } DR("done match processing line.size()="<<dLine.size()) sort(dLine.begin(),dLine.end(),sortMatchX0); DR("@@@@@ SAVE MATCH") #ifdef STACK_MODE //saveMatch(dLine,"/2.match"); #endif #endif #ifdef STACK_MODE //readMatch(dLine,"/2.match"); #endif //компрессия. Все одинаковые буквы в пределах габарита буквы //заменяются на одну букву с макcмимальной корреляцией compressMatch(dLine); //drawGrapeLine(dLine); exit(0); collectStackLetter(strArray,dLine, matchLine,lineImg32,letterAImg,letterBImg,lineIndex); //cout<<"COLLECT"; TIME_PRINT_ //exit(0); //drawGrapeLine(dLine);exit(0); compressMatch(dLine); //drawGrapeLine(dLine);exit(0); //анализ готовых стеков. //проверяем есть ли над или под одиночной буквой коренные буквы или огласовки с высокой корреляцией. //если есть, то букву считаем частью стека и убираем как строительный блок OpenType. //testStackLetter(dLine,lineImg32,letterAImg,letterBImg); //drawGrapeLine(dLine); exit(0); letterAImg->destroy(); letterBImg->destroy(); string strW; vector<uint>letterX; vector<OCRMatch>line; vector<OCRMatch>resultLine; map<vector<int>,ulong>searchResult; buildSearchString(dLine,line,letterX,strW); cout<<strW<<endl<<endl; //drawGrapeLine(line); exit(0); textCorpusGMap->getOCRStackKey(strW,letterX,searchResult, ANY_MATCH); //inputData.log<<" 2"<<endl;inputData.log.flush(); for (int i=0;i<line.size();i++){ if(!line[i].correlation)continue; //cout<<line[i].name; line[i].name=Unicode_to_UTF(line[i].wName); //cout<<" -- "<<line[i].name; line[i].name=YagpoToUni(line[i].name); //cout<<" -- "<<line[i].name<<endl; resultLine.push_back(line[i]); } //logicProcessor->drawGrapeLine(line); //exit(0); //inputData.log<<" 3"<<endl;inputData.log.flush(); //renderDictSearch(searchResult,line,resultLine,matchLine); //mainString+="<br>"+lineString+"original<br>"; if(print){ cout<<"RENDER "; TIME_PRINT_ } strArray[lineIndex].line=dLine; //сохраняем для вывода в HTML //logicProcessor->drawGrapeLine(dLine); //exit(0); //inputData.log<<" 4"<<endl;inputData.log.flush(); }
//новая версия грамматического анализатора. //текст реконструируется на основе вероятностного анализа результатов распознавания //с применением взаимной корреляции частей разных букв. Слоги и слова реконструируются //на основе вероятносного анализа корпуса тибетских текстов и правил построения тибетского шрифта. 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; }