Exemple #1
0
/*
** bmp8 must be grayscale
** (x1,y1) and (x2,y2) from top left of bitmap
*/
void jocr_single_word_from_bmp8(char *text,int maxlen,WILLUSBITMAP *bmp8,
                                int x1,int y1,int x2,int y2,int allow_spaces,
                                int std_proc)

    {
    job_t *job,_job;
    int i,w,h,dw,dh,bw;
    unsigned char *src,*dst;
    // static char *funcname="jocr_single_word_from_bmp8";
    char *buf;
    int pgm2asc(job_t *job);
    char *getTextLine(int);

    if (x1>x2)
        {
        w=x1;
        x1=x2;
        x2=w;
        }
    w=x2-x1+1;
    bw=w/40;
    if (bw<6)
        bw=6;
    dw=w+bw*2;
    if (y1>y2)
        {
        h=y1;
        y1=y2;
        y2=h;
        }
    h=y2-y1+1;
    dh=h+bw*2;
    job=&_job;
    job_init(job);
    job_init_image(job);
    // willus_mem_alloc_warn((void **)&job->src.p.p,w*h,funcname,10);
    /* Must use malloc since job_free_image counts on this. */
    job->src.p.p=malloc(dw*dh);
    job->src.p.x=dw;
    job->src.p.y=dh;
    job->src.p.bpp=1;
    src=bmp_rowptr_from_top(bmp8,y1)+x1;
    memset(job->src.p.p,255,dw*dh);
    dst=(unsigned char *)job->src.p.p + dw*bw + bw;
    for (i=y1;i<=y2;i++,dst+=dw,src+=bmp8->width)
        memcpy(dst,src,w);
    pgm2asc(job);
    buf=getTextLine(0);
    if (buf)
        {
        strncpy(text,buf,maxlen-1);
        text[maxlen-1]='\0';
        if (std_proc)
            ocr_text_proc(text,allow_spaces);
        }
    else
        text[0]='\0';
    // willus_mem_free((double **)&job->src.p.p,funcname);
    job_free_image(job);
    }
Exemple #2
0
/* -------------------------------------------------------------
// ------   MAIN - replace this by your own aplication! 
// ------------------------------------------------------------- */
int main(int argn, char *argv[]) {
  int multipnm=1;
  job_t job1, *job; /* fixme, dont want global variables for lib */
  job=OCR_JOB=&job1;

  setvbuf(stdout, (char *) NULL, _IONBF, 0);	/* not buffered */

  job_init(job); /* init cfg and db */

  process_arguments(job, argn, argv);
  
  /* load character data base (JS1002: now outside pgm2asc) */
  if ( job->cfg.mode & 2 ) /* check for db-option flag */
    load_db(job);
    /* load_db uses readpnm() and would conflict with multi images */
        
  while (multipnm==1) { /* multi-image loop */

    job_init_image(job); /* single image */

    mark_start(job);

    multipnm = read_picture(job);
    /* separation of main and rest for using as lib
       this will be changed later => introduction of set_option()
       for better communication to the engine  */
    if (multipnm<0) break; /* read error */
  
    /* call main loop */
    pgm2asc(job);

    mark_end(job);
  
    print_output(job);

    job_free_image(job);

  }

  return ((multipnm<0)?multipnm:0); /* -1=255 on error, 0 ok */
}
Exemple #3
0
char* gocr_main(job_t* job) {
  int multipnm=1;
  char* output;
  setvbuf(stdout, (char *) NULL, _IONBF, 0);	/* not buffered */

  /* load character data base (JS1002: now outside pgm2asc) */
  if ( job->cfg.mode & 2 ) /* check for db-option flag */
    load_db(job);
    /* load_db uses readpnm() and would conflict with multi images */

  while (multipnm==1) { /* multi-image loop */

    job_init_image(job); /* single image */

    mark_start(job);

    multipnm = read_picture(job);
    /* separation of main and rest for using as lib
       this will be changed later => introduction of set_option()
       for better communication to the engine  */
    if (multipnm<0) break; /* read error */

    /* call main loop */
    pgm2asc(job);

    mark_end(job);

    output = print_output(job);

    job_free_image(job);

  }

//  return ((multipnm<0)?multipnm:0); /* -1=255 on error, 0 ok */
    return output;
}
Exemple #4
0
char get_atom_label(const Magick::Image &image, const Magick::ColorGray &bg, int x1, int y1, int x2, int y2,
                    double THRESHOLD, int dropx, int dropy, bool no_filtering, bool verbose, bool numbers)
{
  char c = UNKNOWN_CHAR;

  const int width = x2 - x1 + 1;
  const int height = y2 - y1 + 1;

  unsigned char *pixmap = (unsigned char *) malloc(width * height);

  for (int i = y1; i <= y2; i++)
    for (int j = x1; j <= x2; j++)
      pixmap[(i - y1) * width + j - x1] = (unsigned char) (255 - 255 * get_pixel(image, bg, j, i, THRESHOLD));

  // Here we drop down from the top of the box, middle of x coordinate and extract connected component
  int t = 1;
  int y = dropy - y1 + 1;
  int x = dropx - x1;

  while ((t != 0) && (y < height))
    {
      t = pixmap[y * width + x];
      y++;
    }

  if (t != 0)
    {
      free(pixmap);
      return 0;
    }

  #pragma omp critical
  {
    y--;

    pixmap[y * width + x] = 2;

    list<int> cx;
    list<int> cy;

    cx.push_back(x);
    cy.push_back(y);

    while (!cx.empty())
      {
        x = cx.front();
        y = cy.front();
        cx.pop_front();
        cy.pop_front();
        pixmap[y * width + x] = 1;

        // this goes around 3x3 square touching the chosen pixel
        for (int i = x - 1; i < x + 2; i++)
          for (int j = y - 1; j < y + 2; j++)
            if (i < width && j < height && i >= 0 && j >= 0 && pixmap[j * width + i] == 0)
              {
                cx.push_back(i);
                cy.push_back(j);
                pixmap[j * width + i] = 2;
              }
      }

    // Flatten the bitmap. Note: the bitmap is inverted after this cycle (255 means "empty", 0 means "pixel").
    for (int i = 0; i < height; i++)
      for (int j = 0; j < width; j++)
        pixmap[i * width + j] = (pixmap[i * width + j] == 1 ? 0 : 255);

    job_t gocr_job;

    // The list of all characters, that can be recognised as atom label:
    string char_filter = RECOGNIZED_CHARS;
    if (numbers) char_filter = "1";
    if (no_filtering) char_filter.clear();

    job_init(&gocr_job);
    job_init_image(&gocr_job);

    //gocr_job.cfg.cs = 160;
    //gocr_job.cfg.certainty = 80;
    //gocr_job.cfg.dust_size = 1;
    gocr_job.src.p.x = width;
    gocr_job.src.p.y = height;
    gocr_job.src.p.bpp = 1;
    gocr_job.src.p.p = pixmap;
    if (char_filter.empty())
      gocr_job.cfg.cfilter = (char*)NULL;
    else
      gocr_job.cfg.cfilter = (char*) char_filter.c_str();

    struct OCRAD_Pixmap *ocrad_pixmap = new OCRAD_Pixmap();
    unsigned char *ocrad_bitmap = (unsigned char *) malloc(width * height);

    memset(ocrad_bitmap, 0, width * height);

    ocrad_pixmap->height = height;
    ocrad_pixmap->width = width;
    ocrad_pixmap->mode = OCRAD_bitmap;
    ocrad_pixmap->data = ocrad_bitmap;

    // Number of non-zero pixels on the bitmap, excluding the 1px border:
    int pixmap_pixels_count = 0;
    // Number of zero pixels on the bitmap, excluding the 1px border:
    int pixmap_zeros_count = 0;

    // The code below initialises "opix->data" buffer ("bitmap_data") for OCRAD from "tmp" buffer:
#ifdef HAVE_CUNEIFORM_LIB
    Magick::Image cuneiform_img(Magick::Geometry(2 * width + 2, height), "white");
    // From cuneiform_src/cli/cuneiform-cli.cpp::preprocess_image(Magick::Image&):168
    cuneiform_img.monochrome();
    cuneiform_img.type(Magick::BilevelType);
#endif
    for (int y = 0; y < height; y++)
      {
        for (int x = 0; x < width; x++)
          {
            if (pixmap[y * width + x] == 0)
              {
                ocrad_bitmap[y * width + x] = 1;
#ifdef HAVE_CUNEIFORM_LIB
                // Draw two identical samples that follow one another. We do so because Cuneiform has difficulties in recognizing single characters:
                cuneiform_img.pixelColor(x, y, "black");
                cuneiform_img.pixelColor(x + width + 2, y, "black");
#endif
                if (x > 0 && x < width - 1 && y > 0 && y < height - 1)
                  pixmap_pixels_count++;
              }
            else if (x > 0 && x < width - 1 && y > 0 && y < height - 1)
              pixmap_zeros_count++;
          }
      }

    if (verbose)
      {
        cout << "Box to OCR: " << x1 << "x" << y1 << "-" << x2 << "x" << y2 << " w/h: " << width << "x" << height << endl;
        for (int i = 0; i < height; i++)
          {
            for (int j = 0; j < width; j++)
              cout << (gocr_job.src.p.p[i * width + j] / 255 ? '#' : '.');
            cout << endl;
          }
      }

    if (pixmap_pixels_count <= MIN_CHAR_POINTS || pixmap_zeros_count <= MIN_CHAR_POINTS)
      goto FINALIZE;

    c = osra_gocr_ocr(gocr_job);

    if (verbose)
      cout << "GOCR: c=" << c << endl;

    //c = UNKNOWN_CHAR; // Switch off GOCR recognition

    // Character recognition succeeded for GOCR:
    if (c != UNKNOWN_CHAR)
      goto FINALIZE;

    // Character recognition failed for GOCR and we try OCRAD:
    c = osra_ocrad_ocr(ocrad_pixmap, char_filter);

    if (verbose)
      cout << "OCRAD: c=" << c << endl;

    //c = UNKNOWN_CHAR;  // Switch off OCRAD recognition

    // Character recognition succeeded for OCRAD:
    if (c != UNKNOWN_CHAR)
      goto FINALIZE;

#ifdef HAVE_TESSERACT_LIB
    c = osra_tesseract_ocr(gocr_job.src.p.p, width, height, char_filter);

    if (verbose)
      cout << "Tesseract: c=" << c << endl;

    //c = UNKNOWN_CHAR;  // Switch off Tesseract recognition

    // Character recognition succeeded for Tesseract:
    if (c != UNKNOWN_CHAR)
      goto FINALIZE;
#endif
#ifdef HAVE_CUNEIFORM_LIB
    // TODO: Why box width should be more than 7 for Cuneiform?
    if (width <= 7)
      goto FINALIZE;

    c = osra_cuneiform_ocr(cuneiform_img, char_filter);

    if (verbose)
      cout << "Cuneiform: c=" << c << endl;

    //c = UNKNOWN_CHAR; // Switch off Cuneiform recognition
#endif

FINALIZE:
    // "pixmap" is freed together with "gocr_job".
    job_free_image(&gocr_job);
    OCR_JOB = NULL;
    JOB = NULL;

    delete ocrad_pixmap; // delete OCRAD Pixmap
    free(ocrad_bitmap);

    // TODO: Why there are problems with "7" with a given box size? If the problem is engine-specific, it should be moved to appropriate section
    if (c == '7' && (width <= 10 || height <= 20))
      c = UNKNOWN_CHAR;
  } // #pragma omp critical

  return(c == UNKNOWN_CHAR ? 0 : c);
}