From dc8a05d76aab1bbf9ce3db9d2bf806ca9f5ade8e Mon Sep 17 00:00:00 2001 From: Anshul Maheshwari Date: Sun, 8 Jun 2014 01:15:32 +0530 Subject: [PATCH] optical character recognisation --- docs/OCR.txt | 55 +++++++++++++++++ linux/Makefile | 5 ++ src/dvb_subtitle_decoder.c | 121 ++++++++++++++++++++++++------------- src/dvb_subtitle_decoder.h | 1 + src/ocr.c | 54 +++++++++++++++++ src/ocr.h | 6 ++ 6 files changed, 199 insertions(+), 43 deletions(-) create mode 100644 docs/OCR.txt create mode 100644 src/ocr.c create mode 100644 src/ocr.h diff --git a/docs/OCR.txt b/docs/OCR.txt new file mode 100644 index 00000000..841fa83b --- /dev/null +++ b/docs/OCR.txt @@ -0,0 +1,55 @@ + +Overview +======== +OCR (Optical Character Recognisation ) is an technique used to +extract text from images. In the World of Subtile, subtitle stored +in bitmap format are common and even neccassary. for converting subtile +in bitmap format to subtilte in text format ocr is used. + +Dependecy +========= +Tesseract (OCR library by google) +Leptonica (image processing library) + +How to compile ccextractor on linux with OCR +============================================= + +Download and Install Leptonnica. +------------------------------- +This package is available, you need liblept-devel library. + +If Leptonica isn't available for your distribution, or you want to use a newer version + than they offer, you can compile your own. + +you can download lib leptonica from http://www.leptonica.com/download.html + +Download and Install Tesseract. +------------------------------- +Tesseract is available directly from many Linux distributions. The package is generally + called 'tesseract' or 'tesseract-ocr' - search your distribution's repositories to + find it. Packages are also generally available for language training data (search the + repositories,) but if not you will need to download the appropriate training data, + unpack it, and copy the .traineddata file into the 'tessdata' directory, probably + /usr/share/tesseract-ocr/tessdata or /usr/share/tessdata. + +If Tesseract isn't available for your distribution, or you want to use a newer version + than they offer, you can compile your own. + +If you compile Tesseract then following command in its source code are enough +./autogen.sh +./configure +make +sudo make install +sudo ldconfig + + Note: +1) CCExtractor is tested with Tesseract 3.02.02 version. + +you can download tesseract from https://drive.google.com/folderview?id=0B7l10Bj_LprhQnpSRkpGMGV2eE0&usp=sharing + + + +Compile CCextractor passing flags like following +------------------------------------------------- +make ENABLE_OCR=yes + diff --git a/linux/Makefile b/linux/Makefile index 9d39241d..f95446d1 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -35,6 +35,11 @@ INSTLALL = cp -f -p INSTLALL_PROGRAM = $(INSTLALL) DESTDIR = /usr/bin +ifeq ($(ENABLE_OCR),yes) +CFLAGS+=-I/usr/local/include/tesseract -I/usr/local/include/leptonica +CFLAGS+=-DENABLE_OCR +LDFLAGS+= $(shell pkg-config --libs tesseract) +endif .PHONY: all all: objs_dir $(TARGET) diff --git a/src/dvb_subtitle_decoder.c b/src/dvb_subtitle_decoder.c index 3076032c..4e29db58 100644 --- a/src/dvb_subtitle_decoder.c +++ b/src/dvb_subtitle_decoder.c @@ -33,6 +33,7 @@ #include "dvb_subtitle_decoder.h" #include "spupng_encoder.h" +#include "ocr.h" #define DEBUG #ifdef DEBUG @@ -255,9 +256,17 @@ int mapclut_paletee(png_color *palette, png_byte *alpha, uint32_t *clut, } return 0; } - +/* + * @param alpha out + * @param intensity in + * @param palette out should be already initialized + * @param bitmap in + * @param size in size of bitmap + * @param max_color in + * @param nb_color in + */ int quantize_map(png_byte *alpha, uint8_t *intensity, png_color *palette, - uint8_t *bitmap, int h, int w, int max_color, int nb_color) + uint8_t *bitmap, int size, int max_color, int nb_color) { /* * occurrence of color in image @@ -301,12 +310,9 @@ int quantize_map(png_byte *alpha, uint8_t *intensity, png_color *palette, memset(mcit, 0, nb_color * sizeof(uint32_t)); /* calculate histogram of image */ - for (int i = 0; i < h; i++) + for (int i = 0; i < size; i++) { - for (int j = 0; j < w; j++) - { - histogram[bitmap[i * w + (j)]]++; - } + histogram[bitmap[i]]++; } sort_intensity_wise((uint8_t*) alpha, (uint8_t*) intensity, iot, nb_color); @@ -365,8 +371,53 @@ int quantize_map(png_byte *alpha, uint8_t *intensity, png_color *palette, freep(&iot); return ret; } + + +static int pre_process_bitmap(png_color **palette, png_byte **alpha, int size, + uint32_t *clut, uint8_t *luit, uint8_t *bitmap, uint8_t depth) +{ + /*local pointer to palette */ + png_color *lpalette = NULL; + /* local pointer to alpha */ + png_byte *lalpha = NULL; + int nb_color = (1<< depth); + int ret = 0; + + + lpalette = (png_color*) malloc(nb_color * sizeof(png_color)); + if(!lpalette) + { + ret = -1; + goto end; + } + lalpha = (png_byte*) malloc(nb_color * sizeof(png_byte)); + if(!lalpha) + { + ret = -1; + goto end; + } + if(clut) + mapclut_paletee(lpalette, lalpha, clut, nb_color); + else + { + /* initialize colors with white */ + memset(palette,0xff,sizeof(nb_color * sizeof(*lpalette))); + + /* initialize transparency as complete transparent */ + memset(lalpha,0,sizeof(nb_color * sizeof(*lalpha))); + } + + if(bitmap) + { + quantize_map(lalpha, luit, lpalette, bitmap, size, 3, nb_color); + } + *palette = lpalette; + *alpha = lalpha; +end: + return ret; +} static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h, - uint32_t *clut, uint8_t *luit,uint8_t depth) + png_color *palette, png_byte *alpha, int nb_color) { FILE *f = NULL; png_structp png_ptr = NULL; @@ -374,43 +425,11 @@ static int save_spupng(const char *filename, uint8_t *bitmap, int w, int h, png_bytep* row_pointer = NULL; int i, j, ret; int k = 0; - - png_color *palette = NULL; - png_byte *alpha = NULL; - int nb_color = (1<< depth); - if(!h) h = 1; if(!w) w = 1; - palette = (png_color*) malloc(nb_color * sizeof(png_color)); - if(!palette) - { - ret = -1; - goto end; - } - alpha = (png_byte*) malloc(nb_color * sizeof(png_byte)); - if(!alpha) - { - ret = -1; - goto end; - } - - - if(clut) - mapclut_paletee(palette, alpha, clut, nb_color); - else - { - /* initialize colors with white */ - memset(palette,0xff,sizeof(nb_color * sizeof(*palette))); - - /* initialize transparency as complete transparent */ - memset(alpha,0,sizeof(nb_color * sizeof(*alpha))); - } - - if(bitmap) - quantize_map(alpha, luit, palette, bitmap, h, w, 3, nb_color); f = fopen(filename, "wb"); if (!f) @@ -791,6 +810,11 @@ static void save_display_set(DVBSubContext *ctx) if (x_pos >= 0) { + png_color *palette = NULL; + png_byte *alpha = NULL; +#ifdef ENABLE_OCR + char*str = NULL; +#endif filename = get_spupng_filename(sp); inc_spupng_fileindex(sp); @@ -821,17 +845,28 @@ static void save_display_set(DVBSubContext *ctx) } } - save_spupng(filename, pbuf, width, height, - clut->clut16, clut->ilut16,region->depth); + pre_process_bitmap(&palette,&alpha,width*height,clut->clut16, clut->ilut16,pbuf,region->depth); +#ifdef ENABLE_OCR + str = ocr_bitmap(palette,alpha,pbuf,width,height); + if(str) + { + write_spucomment(sp,str); + } +#endif + save_spupng(filename, pbuf, width, height, palette, alpha,(1 << region->depth)); free(pbuf); + freep(&palette); + freep(&alpha); } else if(!ctx->prev_start) { + png_color palette = {0,0,0}; + png_byte alpha = 0; filename = get_spupng_filename(sp); inc_spupng_fileindex(sp); /* save dummy frame */ - save_spupng(filename,NULL,1,1,NULL,NULL,0); + save_spupng(filename,NULL,1,1,&palette,&alpha,1); } diff --git a/src/dvb_subtitle_decoder.h b/src/dvb_subtitle_decoder.h index ed0f4e19..01abd3ea 100644 --- a/src/dvb_subtitle_decoder.h +++ b/src/dvb_subtitle_decoder.h @@ -86,6 +86,7 @@ int parse_dvb_description(struct dvb_config* cfg, unsigned char*data, * */ void dvbsub_set_write(void *dvb_ctx, struct ccx_s_write *out); + #ifdef __cplusplus } #endif diff --git a/src/ocr.c b/src/ocr.c new file mode 100644 index 00000000..458523fb --- /dev/null +++ b/src/ocr.c @@ -0,0 +1,54 @@ +#include "png.h" +#ifdef ENABLE_OCR +#include "capi.h" +#include "allheaders.h" + +char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h) +{ + TessBaseAPI* api; + PIX *pix; + char*text_out= NULL; + int i,j,index,ret; + unsigned int wpl; + unsigned int *data,*ppixel; + api = TessBaseAPICreate(); + + pix = pixCreate(w, h, 32); + if(pix == NULL) + { + return NULL; + } + wpl = pixGetWpl(pix); + data = pixGetData(pix); + pixSetSpp(pix, 4); + for (i = 0; i < h; i++) + { + ppixel = data + i * wpl; + for (j = 0; j < w; j++) + { + index = indata[i * w + (j)]; + composeRGBPixel(palette[index].red, palette[index].green,palette[index].blue, ppixel); + SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL,alpha[index]); + ppixel++; + } + } + + ret = TessBaseAPIInit3(api,"", "eng"); + if(ret < 0) + { + return NULL; + } + + //text_out = TessBaseAPIProcessPages(api, "/home/anshul/test_videos/dvbsubtest.d/sub0018.png", 0, 0); + text_out = TessBaseAPIProcessPage(api, pix, 0, NULL, NULL, 1000); + if(!text_out) + printf("\nsomething messy\n"); + return text_out; +} +#else +char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,unsigned char d,int w, int h) +{ + mprint("ocr not supported without tesseract\n"); + return NULL; +} +#endif diff --git a/src/ocr.h b/src/ocr.h new file mode 100644 index 00000000..032d640c --- /dev/null +++ b/src/ocr.h @@ -0,0 +1,6 @@ +#ifndef OCR_H +#define OCR_H +#include +char* ocr_bitmap(png_color *palette,png_byte *alpha, unsigned char* indata,int w, int h); + +#endif