Utilisateur:Alex brollo/djvu text to hOCR
Apparence
# -*- coding: utf-8 -*-
# by Alex brollo - 2013
import os
import re
import json
'''Schemi livelli
<span class='ocrx_word' id='word_2' title='bbox 1743 931 1971 981'>TEORIA</span>
<span class='ocr_line' id='line_1' title="bbox 1502 918 3625 982">...</span>
<p class='ocr_par' dir='ltr' id='par_1' title="bbox 1502 918 3625 982">...</p>
<div class='ocr_carea' id='block_1_1' title="bbox 1502 917 3625 983">...</div>
<div class='ocr_page' id='page_1' title='image \'tiff/opere_2 - 0099.tif\'; bbox 0 0 5186 7330; ppageno 0'>...</div>
Gli id di ogni livello sono numerati progressivamente: word_1, word_2...
L'id del livello area è anomalo: block_1_1, block_2_2....
Nel title c'è sempre "bbox numero numero numero numero" tranne che in
livello pagina dove c'è "nome file; bbox numero numero numero numero"
'''
lista=type([])
stringa=type("")
s_unicode=type(u"")
tuple=type(())
dic={"word":"<span class='ocrx_word' id='word_%numero' title='bbox %coordinate'>%testo</span>\n",\
"line":"<span class='ocr_line' id='line_%numero' title='bbox %coordinate'>\n",\
"para":"<p class='ocr_par' dir='ltr' id='par_%numero' title='bbox %coordinate'>\n",\
"region":"<div class='ocr_carea' id='block_%numero_%numero' title='bbox %coordinate'>\n",\
"column":"",
"page":"<div class='ocr_page' id='page_1' title='image \'immagine.tif\'; bbox %coordinate; ppageno 0'>\n"}
def djvu2hOCR (page,djvu="Opere matematiche (Cremona) III.djvu"):
# calls leggiPaginaDjvu and gets hCR transform of mapped text layer
# Please consider
# 1. these are test scripts
# 2. DjvuLibre routines need to be called by a os.system() call
# 3. put a IA djvu into the same folder of this script
# 4. by now it's tested interactively into a Idle interface
#
#
pyObject=leggiPagDjvu(page,djvu)
hocrText=hOCR(pyObject)
return hocrText
# extracts djvu-lisp code form a IA djvu file
# pagina: no. of the page
# djvu: djvu file name (in same directory)
# dependancies: DjvuLibre routines
def leggiPagDjvu(pagina,djvu):
command='djvused "#file" -e "select #pagina;print-txt" > out.txt'\
.replace("#file",djvu)\
.replace("#pagina",str(pagina))
print "Comando:",command
os.system(command)
testo=unicode(open("out.txt").read(),"utf-8")
oggetto=json.loads(json.dumps(pageObj(testo)))
return oggetto
# gets a python object containing djvu mapped text data
# returns a hOCR htlm (body html content only) that can be uploaded into a wiki page
def hOCR(pagina):
vuota=False
testo=u""
nword=nline=npara=nregion=ncolumn=npage=1
lclose=[]
for i1 in range(len(pagina)): #livello pagina
if i1==0:
testo+=dic["page"].replace("%coordinate",pagina[0].split(" ",1)[1])
#print pagina[0],testo
lclose.insert(0,"</div>")
continue
for i2 in range(len(pagina[i1])): #livello colonna
if i2==0:
x=""
if pagina[i1][1]=="":
vuota=True
continue
if pagina[i1][1]!="":
for i3 in range(len(pagina[i1][i2])): #livello regione
if i3==0:
#print i1,i2
testo+=dic["region"].replace("%coordinate",pagina[i1][i2][0].split(" ",1)[1]).replace("%numero",str(nregion))
#print pagina[i1][i2][0],testo
nregion+=1
lclose.insert(0," </div>\n")
continue
for i4 in range(len(pagina[i1][i2][i3])): #livello paragrafo
if i4==0:
#print i1,i2,i3
testo+=dic["para"].replace("%coordinate",pagina[i1][i2][i3][0].split(" ",1)[1]).replace("%numero",str(npara))
#print pagina[i1][i2][i3][0],testo
npara+=1
lclose.insert(0," </p>\n")
continue
for i5 in range(len(pagina[i1][i2][i3][i4])): #livello linea
if i5==0:
#print i1,i2,i3,i4
testo+=dic["line"].replace("%coordinate",pagina[i1][i2][i3][i4][0].split(" ",1)[1]).replace("%numero",str(nline))
#print pagina[i1][i2][i3][i4][0],testo
nline+=1
lclose.insert(0," </span>\n")
continue
testo+=dic["word"].replace("%coordinate",pagina[i1][i2][i3][i4][i5][0].split(" ",1)[1])\
.replace("%numero",str(nword))\
.replace("%testo",pagina[i1][i2][i3][i4][i5][1])
nword+=1
testo+=lclose.pop(0) #chiusura linea
testo+=lclose.pop(0)
testo+=lclose.pop(0)
testo+=lclose.pop(0) #chiusura pagina
return testo
# riceve un elemento oggetto python lo trasforma in elemento hOCR
def hOCR1(oggetto):
if type(oggetto[1]) in (stringa,s_unicode):
tipo,coordinate=oggetto[0].split(" ",1)
oggetto=dic[tipo][0].replace("%testo",oggetto[1]).replace("%coordinate",coordinate)
return oggetto
# data una pagina djvu-lisp la trasforma in oggetto python (tuple annidata)
def pageObj(testo):
p=re.compile("(page|column|region|para|line|word)\s\d+\s\d+\s\d+\s\d+")
iteratore=p.finditer(testo)
for i in iteratore:
testo=testo.replace(i.group(),'"'+i.group()+'",',1)
testo=testo.split("\n")
for i in range(len(testo)):
testo[i]=testo[i].strip()
testo="\n".join(testo)
testo=testo.replace(")\n(","),(\n").replace("\n","")
oggetto=eval(testo)
return oggetto
# lancia tesseract su una serie di pagine e ottiene hOCR modificato (solo html interno a body)
def tess(ini,fin,lang="ita",base="opere_2 - #pag.tif",hocr=True,inDir="tiff/",outDir="hOCR/"):
for i in range(ini,fin):
pagina=str(i).zfill(4)
pagIn='"'+inDir+base.replace("#pag",pagina)+'"'
pagOut=pagIn.replace(inDir,outDir).replace(".tif","")
command="tesseract #pagin -l #lang tessOut hocr"\
.replace("#lang",lang)\
.replace("#pagin",pagIn)
print command
os.system(command)
testo=open("tessOut.html").read()
header=find_stringa(testo,"<?xml","<body>\n",1)
footer=find_stringa(testo,"</body>","</html>",1)
if header!="":
testo=testo.replace(header,"")
if footer!="":
testo=testo.replace(footer,"")
pagOut=pagIn[1:-1].replace(inDir,outDir).replace(".tif",".html")
print pagOut
open(pagOut,"w").write(testo)
return
def djvuTxt(pagina, djvu="numi.djvu", base="Rivista italiana di numismatica 1892.djvu"):
nomePagina=wikipedia.Page("it","Pagina:"+base+"/"+str(pagina))
os.system("djvutxt -page=#pagina numi.djvu pagina.txt".replace("#pagina",str(pagina)))
testo=unicode(open("pagina.txt").read(),"utf-8")\
.replace(u"\x1f\x1d\x0b","\n").replace(u"\x0c","").replace(u"\x1f","\n")
#print testo
if not nomePagina.exists():
nomePagina.put(testo,comment="caricamento OCR via bot")
return #testo
def x():
trattino=u'\u2015'
return "―"
# Nuova versione, gestisce i tag annidati; x e' la parte "aspecifica" del
# tag di apertura (es: {{ cercando {{Intestazione| )
def find_stringa(stringa,idi,idf,dc=0,x=None,side="left"):
if side=="right":
idip=stringa.rfind(idi)
else:
idip=stringa.find(idi)
idfp=stringa.find(idf,idip+len(idi))+len(idf)
if idip>-1 and idfp>0:
if x!=None:
while stringa[idip:idfp].count(x)>stringa[idip:idfp].count(idf):
if stringa[idip:idfp].count(x)>stringa[idip:idfp].count(idf):
idfp=stringa.find(idf,idfp)+len(idf)
if dc==0:
vvalore=stringa[idip+len(idi):idfp-len(idf)]
else:
vvalore=stringa[idip:idfp]
else:
vvalore=""
return vvalore
def produci_lista(testo,idi,idf,dc=1,inizio=None):
t=testo[:]
lista=[]
while not find_stringa(t,idi,idf,1,inizio)=="":
el=find_stringa(t,idi,idf,1,inizio)
t=t.replace(el,"",1)
if dc==0:
el=find_stringa(el,idi,idf,0,inizio)
lista.append(el)
return lista
# for others uses
def djvudump(djvu):
comando="djvudump \"#djvu\" > \"#dump\""\
.replace("#djvu",djvu)\
.replace("#dump",djvu.replace(".djvu",".dump"))
print comando
os.system(comando)
return