barcode-scanner / app.py
dal4933's picture
Update app.py
7129810 verified
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import cv2
import zxingcpp
import numpy as np
from PIL import Image
import base64
import io
from typing import Dict, Any
app = FastAPI(title="Barcode Scanner API", version="1.0.0")
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # In production, specify your frontend domain
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class ImageRequest(BaseModel):
image: str # Base64 encoded image
class ScanResponse(BaseModel):
status: str
text: str = None
format: str = None
message: str = None
def decode_base64_image(base64_string: str) -> np.ndarray:
"""Decode base64 image to numpy array"""
try:
# Handle data URI format
if base64_string.startswith('data:image'):
# Remove the data:image/jpeg;base64, prefix
base64_string = base64_string.split(',')[1]
# Decode base64
image_bytes = base64.b64decode(base64_string)
# Convert to PIL Image
pil_image = Image.open(io.BytesIO(image_bytes))
# Convert to numpy array
image_array = np.array(pil_image)
return image_array
except Exception as e:
raise HTTPException(status_code=400, detail=f"Invalid image format: {str(e)}")
@app.get("/")
async def root():
return {"message": "Barcode Scanner API is running!"}
@app.get("/health")
async def health_check():
return {"status": "healthy"}
@app.post("/scan", response_model=ScanResponse)
async def scan_barcode(request: ImageRequest):
"""Scan barcode from base64 encoded image"""
try:
# Decode the base64 image
image_array = decode_base64_image(request.image)
# Convert RGB to BGR for OpenCV (if needed)
if len(image_array.shape) == 3 and image_array.shape[2] == 3:
bgr_image = cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR)
elif len(image_array.shape) == 3 and image_array.shape[2] == 4:
# Handle RGBA images
rgb_image = cv2.cvtColor(image_array, cv2.COLOR_RGBA2RGB)
bgr_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2BGR)
else:
bgr_image = image_array
# Scan for barcodes
results = zxingcpp.read_barcodes(bgr_image)
if results:
# Return the first barcode found
barcode = results[0]
return ScanResponse(
status="success",
text=barcode.text,
format=str(barcode.format)
)
else:
return ScanResponse(
status="error",
message="No barcode detected"
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Processing error: {str(e)}")
# For HuggingFace Spaces, you might need this
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)