Download rizeh.py from Reza2kn/Bina-0.4-Rizeh: direct link, hf CLI and curl.
- Browser
- Download file 3.69 kB
-
https://huggingface.co/Reza2kn/Bina-0.4-Rizeh/resolve/main/rizeh.py
- Command line
-
hf download hf://Reza2kn/Bina-0.4-Rizeh/rizeh.py
-
curl -L -o rizeh.py https://huggingface.co/Reza2kn/Bina-0.4-Rizeh/resolve/main/rizeh.py
3.69 kB
| #!/usr/bin/env python3 | |
| """Bina 0.4 Rizeh: Persian page OCR (Surya layout + 95k Indra CTC student + printed/table/numeric experts and assembly). | |
| usage: python rizeh.py page.jpg [more.png doc.pdf ...] [--out results] [--device cuda|cpu] | |
| """ | |
| import argparse,json,os,sys,time,importlib.util | |
| from pathlib import Path | |
| ROOT=Path(__file__).resolve().parent;ST=ROOT/'stallion';MARK=ROOT/'.bina-root' | |
| LAYOUT_REPO,LAYOUT_REV='datalab-to/surya_layout2','0aee81d5fd9275c0582e545bf3a56944b1e75679' | |
| TEXT=('.py','.json','.yml','.yaml','.txt','.jsonl') | |
| def setup(): | |
| """Point every bundled path at this checkout (idempotent; reruns after a move) and fetch the pinned layout model.""" | |
| here=str(ROOT);old=MARK.read_text().strip()if MARK.exists()else'__BINA_ROOT__' | |
| if old!=here: | |
| n=0 | |
| for p in ST.rglob('*'): | |
| if p.is_file()and p.suffix in TEXT: | |
| s=p.read_text(encoding='utf-8') | |
| if old in s:p.write_text(s.replace(old,here),encoding='utf-8');n+=1 | |
| MARK.write_text(here);print(f'[rizeh] bound {n} files to {here}',file=sys.stderr) | |
| snap=ST/'indra-scale/hf/hub/models--datalab-to--surya_layout2/snapshots'/LAYOUT_REV | |
| if not(snap/'rfdetr_layout.pth').exists(): | |
| from huggingface_hub import snapshot_download | |
| print('[rizeh] downloading layout model',LAYOUT_REPO,LAYOUT_REV,file=sys.stderr) | |
| snapshot_download(LAYOUT_REPO,revision=LAYOUT_REV,cache_dir=str(ST/'indra-scale/hf/hub')) | |
| return snap | |
| def pages(path): | |
| p=Path(path) | |
| if p.suffix.lower()=='.pdf': | |
| import pypdfium2 as pdfium | |
| doc=pdfium.PdfDocument(str(p)) | |
| for i in range(len(doc)):yield f'{p.stem}-p{i+1:03d}',doc[i].render(scale=200/72).to_pil().convert('RGB') | |
| else: | |
| from PIL import Image | |
| yield p.stem,Image.open(p).convert('RGB') | |
| class Rizeh: | |
| def __init__(self,device='cuda'): | |
| snap=setup() | |
| os.environ.setdefault('GATE_DEVICE',device);os.environ.setdefault('FAST_DETECTOR_DEVICE','cpu');os.environ.setdefault('DETECTOR_IMAGE_CHUNK_HEIGHT','1400');os.environ['FAST_ORDER_MODEL_CHECKPOINT']=str(snap/'order') | |
| P=ST/'indra-scale';sys.path[:0]=[str(P),str(ST/'bina04-pagepath-v3-round3-clean-20261031'),str(P/'scoringTT')] | |
| spec=importlib.util.spec_from_file_location('bina04_rizeh_runtime',ST/'bina04-ink-loss-guard-95k-20261104/production.py');m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m) | |
| self.engine=m.Runtime(device) | |
| from surya.fast_layout.server import LayoutEngine | |
| self.layout=LayoutEngine(checkpoint=str(snap)) | |
| def __call__(self,image,name='page'): | |
| raw=self.layout.run_batch([image],[dict(threshold=None,use_order=True)])[0].model_dump(mode='json') | |
| out=self.engine(image,dict(raw_layout=raw),'page',name) | |
| lines=[dict(text=l.get('text',''),layer=l.get('layer'),box=[round(float(v),1)for v in l['box']],confidence=l.get('confidence'))for l in out.get('lines',[])if l.get('box')] | |
| return dict(text=out['text'],lines=lines) | |
| def close(self):self.engine.close() | |
| def main(): | |
| ap=argparse.ArgumentParser(description=__doc__,formatter_class=argparse.RawDescriptionHelpFormatter);ap.add_argument('inputs',nargs='+');ap.add_argument('--out',default='rizeh-out');ap.add_argument('--device',default='cuda',choices=['cuda','cpu']);a=ap.parse_args() | |
| O=Path(a.out);O.mkdir(parents=True,exist_ok=True);r=Rizeh(a.device) | |
| for src in a.inputs: | |
| for name,im in pages(src): | |
| t=time.perf_counter();res=r(im,name);res.update(source=str(src),seconds=round(time.perf_counter()-t,2),model='Bina-0.4-Rizeh') | |
| (O/f'{name}.json').write_text(json.dumps(res,ensure_ascii=False,indent=1),encoding='utf-8');(O/f'{name}.txt').write_text(res['text'],encoding='utf-8') | |
| print(f'{name}: {len(res["lines"])} lines, {res["seconds"]}s -> {O/name}.txt',flush=True) | |
| r.close() | |
| if __name__=='__main__':main() | |