File indexing completed on 2024-05-12 15:55:07
0001 /*************************************************************************** 0002 kadmosocr.cpp - Kadmos cpp interface 0003 ------------------- 0004 begin : Fri Jun 30 2000 0005 0006 (c) 2002 re Recognition AG Hafenstrasse 50b CH-8280 Kreuzlingen 0007 Switzerland Phone: +41 (0)71 6780000 Fax: +41 (0)71 6780099 0008 Website: www.reRecognition.com E-mail: info@reRecognition.com 0009 0010 Author: Tamas Nagy (nagy@rerecognition.com) 0011 Klaas Freitag <freitag@suse.de> 0012 Heike Stuerzenhofecker <heike@freisturz.de> 0013 ***************************************************************************/ 0014 0015 /*************************************************************************** 0016 * * 0017 * This file may be distributed and/or modified under the terms of the * 0018 * GNU General Public License version 2 as published by the Free Software * 0019 * Foundation and appearing in the file COPYING included in the * 0020 * packaging of this file. * 0021 * 0022 * As a special exception, permission is given to link this program * 0023 * with any version of the KADMOS ocr/icr engine of reRecognition GmbH, * 0024 * Kreuzlingen and distribute the resulting executable without * 0025 * including the source code for KADMOS in the source distribution. * 0026 * 0027 * As a special exception, permission is given to link this program * 0028 * with any edition of Qt, and distribute the resulting executable, * 0029 * without including the source code for Qt in the source distribution. * 0030 * * 0031 ***************************************************************************/ 0032 0033 /* Kadmos CPP object oriented interface */ 0034 0035 #include <qimage.h> 0036 #include <qpainter.h> 0037 #include <qstring.h> 0038 #include <qrect.h> 0039 #include <qstringlist.h> 0040 0041 #include <assert.h> 0042 0043 #include <string.h> 0044 #include <stdlib.h> 0045 #include <memory.h> 0046 #include <QDebug> 0047 0048 #include "kadmosocr.h" 0049 #include "ocrword.h" 0050 0051 #ifdef HAVE_KADMOS 0052 0053 using namespace Kadmos; 0054 0055 /* -------------------- CRep -------------------- */ 0056 CRep::CRep() 0057 : QObject() 0058 { 0059 memset(&m_RepData, 0, sizeof(m_RepData)); 0060 m_Error = RE_SUCCESS; 0061 m_undetectChar = QChar('_'); 0062 } 0063 0064 CRep::~CRep() 0065 { 0066 } 0067 0068 RelGraph *CRep::getGraphKnode(int line, int offset) 0069 { 0070 Kadmos::RepResult *res = getRepResult(line); 0071 if (res) { 0072 return (&(getRepResult(line)->rel_graph[0]) + offset); 0073 } else { 0074 return 0L; 0075 } 0076 0077 } 0078 0079 RepResult *CRep::getRepResult(int line) 0080 { 0081 if (line < 0 || line >= m_RepData.rep_result_len) { 0082 return 0L; 0083 } 0084 return &(m_RepData.rep_result[line]); 0085 } 0086 0087 RelResult *CRep::getRelResult(int line, RelGraph *graph, int alternative) 0088 { 0089 if (!(graph && getRepResult(line))) { 0090 return 0L; 0091 } 0092 int offset = graph->result_number[alternative]; 0093 return (&(getRepResult(line)->rel_result[0]) + offset); 0094 } 0095 0096 KADMOS_ERROR CRep::Init(const char *ClassifierFilename) 0097 { 0098 /* prepare RepData structure */ 0099 m_RepData.init.rel_grid_maxlen = GRID_MAX_LEN; 0100 m_RepData.init.rel_graph_maxlen = GRAPH_MAX_LEN; 0101 m_RepData.init.rel_result_maxlen = CHAR_MAX_LEN; 0102 m_RepData.init.rep_memory_size = LINE_MAX_LEN * sizeof(RepResult) + 0103 (long)LINE_MAX_LEN * CHAR_MAX_LEN * (sizeof(RelGraph) + 0104 sizeof(RelResult)); 0105 m_RepData.init.rep_memory = malloc(m_RepData.init.rep_memory_size); 0106 if (!m_RepData.init.rep_memory) { 0107 ChecqCritical(); 0108 return m_Error; 0109 } 0110 strcpy(m_RepData.init.version, INC_KADMOS); 0111 0112 m_Error = rep_init(&m_RepData, (char *)ClassifierFilename); 0113 ChecqCritical(); 0114 return m_Error; 0115 } 0116 0117 void CRep::run() // KADMOS_ERROR CRep::Recognize() 0118 { 0119 kdDebug(28000) << "ooo Locked and ocr!" << endl; 0120 m_Error = rep_do(&m_RepData); 0121 ChecqCritical(); 0122 } 0123 0124 KADMOS_ERROR CRep::End() 0125 { 0126 m_Error = rep_end(&m_RepData); 0127 ChecqCritical(); 0128 return m_Error; 0129 } 0130 0131 int CRep::GetMaxLine() 0132 { 0133 return m_RepData.rep_result_len; 0134 } 0135 0136 const char *CRep::RepTextLine(int nLine, unsigned char RejectLevel, int RejectChar, long Format) 0137 { 0138 m_Error = rep_textline(&m_RepData, nLine, m_Line, 0139 2 * CHAR_MAX_LEN, RejectLevel, RejectChar, Format); 0140 ChecqCritical(); 0141 return m_Line; 0142 } 0143 0144 /** 0145 * This method handles the given line. It takes repRes and goes through the 0146 * kadmos result tree structures recursively. 0147 */ 0148 ocrWordList CRep::getLineWords(int line) 0149 { 0150 ocrWordList repWords; 0151 bool ok = true; 0152 0153 Kadmos::RepResult *repRes = getRepResult(line); 0154 0155 if (! repRes) { 0156 kdDebug(28000) << "repRes-Pointer is null" << endl; 0157 ok = false; 0158 } 0159 0160 if (ok) { 0161 int nextKnode = 0; 0162 0163 do { 0164 QString resultWord; 0165 QRect boundingRect; 0166 0167 int newNextKnode = nextBestWord(line, nextKnode, resultWord, boundingRect); 0168 boundingRect.moveBy(repRes->left, repRes->top); 0169 0170 ocrWord newWord; 0171 newWord = resultWord; 0172 newWord.setKnode(nextKnode); 0173 newWord.setLine(line); 0174 newWord.setRect(boundingRect); 0175 repWords.push_back(newWord); 0176 0177 /* set nextKnode to the next Knode */ 0178 nextKnode = newNextKnode; 0179 0180 // Alternativen: 0181 // partStrings( line, nextKnode, QString()); // fills m_parts - list with alternative words 0182 // nextKnode = newNextKnode; 0183 // kdDebug(28000) << "NextKnodeWord: " << resultWord << endl; 0184 } while (nextKnode > 0); 0185 } 0186 return repWords; 0187 } 0188 0189 /* This fills theWord with the next best word and returns the 0190 * next knode or 0 if there is no next node 0191 */ 0192 int CRep::nextBestWord(int line, int knode, QString &theWord, QRect &brect) 0193 { 0194 0195 Kadmos::RelGraph *relg = getGraphKnode(line, knode); 0196 // kdDebug(28000) << "GraphKnode is " << knode << endl; 0197 int nextKnode = knode; 0198 0199 while (relg) { 0200 Kadmos::RelResult *relr = getRelResult(line, relg, 0); // best alternative 0201 if (relr) { 0202 // kdDebug(28000) << "Leading Blanks: " << relg->leading_blanks << 0203 // " und Knode " << knode << endl; 0204 char c = relr->rec_char[0][0]; 0205 QChar newChar = c; 0206 if (c == 0) { 0207 kdDebug(28000) << "Undetected char found !" << endl; 0208 newChar = m_undetectChar; 0209 } 0210 0211 if ((nextKnode != knode) && (relg->leading_blanks > 0)) { 0212 /* this means the word ends here. */ 0213 // kdDebug(28000) << "----" << theWord << endl; 0214 relg = 0L; /* Leave the loop. */ 0215 } else { 0216 /* append the character */ 0217 theWord.append(newChar); 0218 0219 /* save the bounding rect */ 0220 // kdDebug(28000) << "LEFT: " << relr->left << " TOP: " << relr->top << endl; 0221 QRect r(relr->left, relr->top, relr->width, relr->height); 0222 0223 if (brect.isNull()) { 0224 brect = r; 0225 } else { 0226 brect = brect.unite(r); 0227 } 0228 0229 /* next knode */ 0230 if (relg->next[0] > 0) { 0231 nextKnode = relg->next[0]; 0232 relg = getGraphKnode(line, nextKnode); 0233 } else { 0234 /* end of the line */ 0235 nextKnode = 0; 0236 relg = 0L; 0237 } 0238 } 0239 } 0240 } 0241 return (nextKnode); 0242 } 0243 0244 void CRep::partStrings(int line, int graphKnode, QString soFar) 0245 { 0246 /* The following knodes after a word break */ 0247 Kadmos::RelGraph *relg = getGraphKnode(line, graphKnode); 0248 // kdDebug(28000) << "GraphKnode is " << graphKnode << endl; 0249 0250 QString theWord = ""; 0251 for (int resNo = 0; resNo < SEG_ALT; resNo++) { 0252 // kdDebug(28000) << "Alternative " << resNo << " is " << relg->result_number[resNo] << endl; 0253 if (relg->result_number[resNo] == -1) { 0254 /* This means that there is no other alternative. Go out here. */ 0255 break; 0256 } 0257 0258 Kadmos::RelResult *relr = getRelResult(line, relg, resNo); 0259 theWord = QChar(relr->rec_char[0][0]); 0260 0261 if (!soFar.isEmpty() && relg->leading_blanks) { 0262 /* this means the previous words end. */ 0263 // TODO: This forgets the alternatives of _this_ first character of the new word. 0264 0265 kdDebug(28000) << "---- " << soFar << endl; 0266 m_parts << soFar; 0267 break; 0268 } else { 0269 /* make a QString from this single char and append it. */ 0270 soFar += theWord; 0271 } 0272 0273 if (relg->next[resNo] > 0) { 0274 /* There is a follower to this knode. Combine the result list from a recursive call 0275 * to this function with the follower knode. 0276 */ 0277 partStrings(line, relg->next[resNo], soFar); 0278 } else { 0279 /* There is no follower */ 0280 kdDebug(28000) << "No followers - theWord is " << soFar << endl; 0281 m_parts << soFar; 0282 break; 0283 } 0284 } 0285 } 0286 0287 void CRep::drawCharBox(QPixmap *pix, const QRect &r) 0288 { 0289 drawBox(pix, r, QColor(Qt::red)); 0290 } 0291 0292 void CRep::drawLineBox(QPixmap *pix, const QRect &r) 0293 { 0294 drawBox(pix, r, QColor(Qt::blue)); 0295 } 0296 0297 void CRep::drawBox(QPixmap *pix, const QRect &r, const QColor &color) 0298 { 0299 QPainter p; 0300 p.begin(pix); 0301 0302 p.setPen(color); 0303 p.drawRect(r); 0304 } 0305 0306 KADMOS_ERROR CRep::SetImage(const QString file) 0307 { 0308 ReImageHandle image_handle; 0309 image_handle = re_readimage(file.latin1(), &m_RepData.image); 0310 if (! image_handle) { 0311 kdDebug(28000) << "Can not load input file" << endl; 0312 } 0313 ChecqCritical(); 0314 return RE_SUCCESS; 0315 0316 } 0317 0318 KADMOS_ERROR CRep::SetImage(QImage *Image) 0319 { 0320 // memcpy(&m_RepData.image, Image.bits(), Image.numBytes()); 0321 if (!Image) { 0322 return RE_PARAMETERERROR; 0323 } 0324 0325 kdDebug(28000) << "Setting image manually." << endl; 0326 m_RepData.image.data = (void *)Image->bits(); 0327 m_RepData.image.imgtype = IMGTYPE_PIXELARRAY; 0328 m_RepData.image.width = Image->width(); 0329 m_RepData.image.height = Image->height(); 0330 m_RepData.image.bitsperpixel = Image->depth(); 0331 m_RepData.image.alignment = 1; 0332 m_RepData.image.fillorder = FILLORDER_MSB2LSB; 0333 // color 0334 if (Image->depth() == 1 || (Image->numColors() == 2 && Image->depth() == 8)) { 0335 m_RepData.image.color = COLOR_BINARY; 0336 kdDebug(28000) << "Setting Binary" << endl; 0337 } else if (Image->isGrayscale()) { 0338 m_RepData.image.color = COLOR_GRAY; 0339 kdDebug(28000) << "Setting GRAY" << endl; 0340 0341 } else { 0342 m_RepData.image.color = COLOR_RGB; 0343 kdDebug(28000) << "Setting Color RGB" << endl; 0344 } 0345 // orientation 0346 m_RepData.image.orientation = ORIENTATION_TOPLEFT; 0347 m_RepData.image.photometric = PHOTOMETRIC_MINISWHITE; 0348 m_RepData.image.resunit = RESUNIT_INCH; 0349 m_RepData.image.xresolution = 200; 0350 m_RepData.image.yresolution = 200; 0351 0352 ChecqCritical(); 0353 0354 return RE_SUCCESS; 0355 } 0356 0357 void CRep::SetNoiseReduction(bool bNoiseReduction) 0358 { 0359 if (bNoiseReduction) { 0360 m_RepData.parm.prep |= PREP_AUTO_NOISEREDUCTION; 0361 } else { 0362 m_RepData.parm.prep &= !PREP_AUTO_NOISEREDUCTION; 0363 } 0364 } 0365 0366 void CRep::SetScaling(bool bScaling) 0367 { 0368 if (bScaling) { 0369 m_RepData.parm.prep |= PREP_SCALING; 0370 } else { 0371 m_RepData.parm.prep &= !PREP_SCALING; 0372 } 0373 } 0374 0375 void CRep::ChecqCritical() 0376 { 0377 if (kadmosError()) { 0378 kdDebug(28000) << "KADMOS ERROR: " << getErrorText() << endl; 0379 } 0380 } 0381 0382 /* returns a QString containing the string describing the kadmos error */ 0383 QString CRep::getErrorText() const 0384 { 0385 re_ErrorText Err; 0386 re_GetErrorText(&Err); 0387 return QString::fromLocal8Bit(Err.text); 0388 } 0389 0390 bool CRep::kadmosError() 0391 { 0392 return m_Error != RE_SUCCESS; 0393 } 0394 0395 #endif /* HAVE_KADMOS */ 0396 0397 // } /* End of Kadmos namespace */