Spaces:
Sleeping
Sleeping
msi
commited on
Commit
·
197a58a
1
Parent(s):
18265ed
first commit
Browse files- .gitignore +1 -0
- Dockerfile +16 -0
- app.py +44 -0
- pdf_generator.py +20 -0
- requirements.txt +8 -0
- result/receipt.pdf +74 -0
.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
.env
|
Dockerfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
|
| 2 |
+
# you will also find guides on how best to write your Dockerfile
|
| 3 |
+
|
| 4 |
+
FROM python:3.11-slim
|
| 5 |
+
|
| 6 |
+
RUN useradd -m -u 1000 user
|
| 7 |
+
USER user
|
| 8 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 9 |
+
|
| 10 |
+
WORKDIR /app
|
| 11 |
+
|
| 12 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 13 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
| 14 |
+
|
| 15 |
+
COPY --chown=user . /app
|
| 16 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
app.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, UploadFile, File, HTTPException
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from PIL import Image
|
| 5 |
+
import io
|
| 6 |
+
import os
|
| 7 |
+
import google.generativeai as genai
|
| 8 |
+
from fastapi.responses import FileResponse
|
| 9 |
+
from pdf_generator import create_receipt
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
genai.configure(api_key=os.environ.get("GOOGLE_API_KEY"))
|
| 13 |
+
|
| 14 |
+
app = FastAPI()
|
| 15 |
+
|
| 16 |
+
class OCRResponse(BaseModel):
|
| 17 |
+
extracted_text: str
|
| 18 |
+
|
| 19 |
+
@app.post("/ocr-image/", response_model=OCRResponse)
|
| 20 |
+
async def ocr_image(file: UploadFile = File(...)):
|
| 21 |
+
|
| 22 |
+
if not file.content_type.startswith("image/"):
|
| 23 |
+
raise HTTPException(status_code=400, detail="Uploaded file must be an image.")
|
| 24 |
+
|
| 25 |
+
try:
|
| 26 |
+
image_data = await file.read()
|
| 27 |
+
image = Image.open(io.BytesIO(image_data))
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
model = genai.GenerativeModel('gemini-2.0-flash')
|
| 31 |
+
|
| 32 |
+
prompt = "Extract and Identify all text from this image and generate a receipt without any additional information."
|
| 33 |
+
contents = [prompt, image]
|
| 34 |
+
|
| 35 |
+
response = model.generate_content(contents)
|
| 36 |
+
|
| 37 |
+
extracted_text = response.text
|
| 38 |
+
|
| 39 |
+
create_receipt(extracted_text, file_name="result/receipt.pdf")
|
| 40 |
+
return FileResponse(path="result/receipt.pdf", filename="receipt.pdf", media_type='application/pdf')
|
| 41 |
+
|
| 42 |
+
except Exception as e:
|
| 43 |
+
raise HTTPException(status_code=500, detail=f"OCR failed: {str(e)}")
|
| 44 |
+
|
pdf_generator.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from reportlab.lib.pagesizes import A5
|
| 2 |
+
from reportlab.pdfgen import canvas
|
| 3 |
+
|
| 4 |
+
def create_receipt(text, file_name):
|
| 5 |
+
pdf = canvas.Canvas(file_name, pagesize=A5)
|
| 6 |
+
width, height = A5
|
| 7 |
+
|
| 8 |
+
pdf.setFont("Helvetica-Bold", 16)
|
| 9 |
+
pdf.drawCentredString(width / 2, height - 50, "Receipt Summary")
|
| 10 |
+
|
| 11 |
+
pdf.setFont("Helvetica", 12)
|
| 12 |
+
text_object = pdf.beginText(50, height - 100)
|
| 13 |
+
|
| 14 |
+
for line in text.split("\n"):
|
| 15 |
+
text_object.textLine(line.strip())
|
| 16 |
+
|
| 17 |
+
pdf.drawText(text_object)
|
| 18 |
+
|
| 19 |
+
pdf.save()
|
| 20 |
+
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
google-generativeai
|
| 2 |
+
requests==2.31.0
|
| 3 |
+
Pillow==10.4.0
|
| 4 |
+
fastapi==0.100.0
|
| 5 |
+
uvicorn==0.23.2
|
| 6 |
+
python-multipart==0.0.6
|
| 7 |
+
pydantic==2.11.4
|
| 8 |
+
reportlab
|
result/receipt.pdf
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
%PDF-1.3
|
| 2 |
+
%���� ReportLab Generated PDF document http://www.reportlab.com
|
| 3 |
+
1 0 obj
|
| 4 |
+
<<
|
| 5 |
+
/F1 2 0 R /F2 3 0 R
|
| 6 |
+
>>
|
| 7 |
+
endobj
|
| 8 |
+
2 0 obj
|
| 9 |
+
<<
|
| 10 |
+
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
| 11 |
+
>>
|
| 12 |
+
endobj
|
| 13 |
+
3 0 obj
|
| 14 |
+
<<
|
| 15 |
+
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
| 16 |
+
>>
|
| 17 |
+
endobj
|
| 18 |
+
4 0 obj
|
| 19 |
+
<<
|
| 20 |
+
/Contents 8 0 R /MediaBox [ 0 0 419.5276 595.2756 ] /Parent 7 0 R /Resources <<
|
| 21 |
+
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
| 22 |
+
>> /Rotate 0 /Trans <<
|
| 23 |
+
|
| 24 |
+
>>
|
| 25 |
+
/Type /Page
|
| 26 |
+
>>
|
| 27 |
+
endobj
|
| 28 |
+
5 0 obj
|
| 29 |
+
<<
|
| 30 |
+
/PageMode /UseNone /Pages 7 0 R /Type /Catalog
|
| 31 |
+
>>
|
| 32 |
+
endobj
|
| 33 |
+
6 0 obj
|
| 34 |
+
<<
|
| 35 |
+
/Author (anonymous) /CreationDate (D:20251105143021+01'00') /Creator (ReportLab PDF Library - www.reportlab.com) /Keywords () /ModDate (D:20251105143021+01'00') /Producer (ReportLab PDF Library - www.reportlab.com)
|
| 36 |
+
/Subject (unspecified) /Title (untitled) /Trapped /False
|
| 37 |
+
>>
|
| 38 |
+
endobj
|
| 39 |
+
7 0 obj
|
| 40 |
+
<<
|
| 41 |
+
/Count 1 /Kids [ 4 0 R ] /Type /Pages
|
| 42 |
+
>>
|
| 43 |
+
endobj
|
| 44 |
+
8 0 obj
|
| 45 |
+
<<
|
| 46 |
+
/Filter [ /ASCII85Decode /FlateDecode ] /Length 374
|
| 47 |
+
>>
|
| 48 |
+
stream
|
| 49 |
+
GarW5>t`'h(kqGQ/'a\hUaDpXRs2G<;#D0a95e;:%PsQN]P3,tpSMNN;'[E?PNSI+&.&r(*7iO>G6P/;-"Ma>".?&IMC5K_ae3:.f7Q7_ZTh_:,%R:AE]0ISjXSNP.\[^ADcDm641kf62=E1pCf)ImOoJd2N)TlSr$3gb%WP'\%-hKT?b%B#;Km5H,UcoopEO,ZI-5=!?F1`G8(%j4Tlj'g6>ro^anm-:m5PY,6@H<=-JR*nM5_+S@'/,WOn57k44mrl?`o6%ksA*qd5]$#U=X3R65r"o-GHN>AkIG]6B&]+eRh=amg8H7LVhUGp2FH\qQm&=O+h@-L99m&CO4GcEG7&1V:]E?+]ocZnP>U2:-JiF+4Q4.DZ~>endstream
|
| 50 |
+
endobj
|
| 51 |
+
xref
|
| 52 |
+
0 9
|
| 53 |
+
0000000000 65535 f
|
| 54 |
+
0000000073 00000 n
|
| 55 |
+
0000000114 00000 n
|
| 56 |
+
0000000221 00000 n
|
| 57 |
+
0000000333 00000 n
|
| 58 |
+
0000000536 00000 n
|
| 59 |
+
0000000604 00000 n
|
| 60 |
+
0000000900 00000 n
|
| 61 |
+
0000000959 00000 n
|
| 62 |
+
trailer
|
| 63 |
+
<<
|
| 64 |
+
/ID
|
| 65 |
+
[<03cbf99983fa0b0281f96429a1239e03><03cbf99983fa0b0281f96429a1239e03>]
|
| 66 |
+
% ReportLab generated PDF document -- digest (http://www.reportlab.com)
|
| 67 |
+
|
| 68 |
+
/Info 6 0 R
|
| 69 |
+
/Root 5 0 R
|
| 70 |
+
/Size 9
|
| 71 |
+
>>
|
| 72 |
+
startxref
|
| 73 |
+
1423
|
| 74 |
+
%%EOF
|