I’m facing an issue with my web app when using the Roboflow Inference API after deployment. Locally, the endpoint returns the expected JSON response, but once deployed, it occasionally returns an HTML response (e.g., <!DOCTYPE html>
), which causes a SyntaxError: Unexpected token '<'
. This happens despite the endpoint responding with a 200 OK
status.
- Project Type:Parking Management System with license plate detection (ALPR).
- Operating System & Browser: Chrome
- Project Universe Link or Workspace/Project ID:
- API Endpoint Used: Roboflow Inference API
- Problem Details:
- The web app fetches frames from a video feed and sends them to the
/detect
endpoint in my Flask server. - The Flask server calls the Roboflow model inference API and should return the detected license plate text and vehicle type as JSON.
- The server logs show a
200 OK
response, but the client sometimes receives unexpected HTML instead of JSON.**
Additional Note: This is deploy on Render.
This is the related codes below.
Load the model
print(“Loading model…”)
model = inference.get_model(“plate-number-recognition-prqx4/2”)
print(“Model successfully loaded.”)
import easyocr
from PIL import Image
import numpy as np
from flask import request, jsonify
Initialize the easyocr reader
reader = easyocr.Reader([‘en’])
@parking.route(‘/detect’, methods=[‘POST’])
def detect():
if ‘image’ not in request.files:
print(“No image uploaded”)
return jsonify({‘error’: ‘No image uploaded’}), 400
try:
# Get the image from the request
file = request.files['image']
img = Image.open(file.stream)
img_np = np.array(img) # Convert PIL Image to numpy array for processing
# Run inference
print("Running inference...")
result = model.infer(image=img_np)
print("Inference result:", result)
if len(result) > 0:
response = result[0]
detected_text = ""
vehicle_type_detected = None
for prediction in response.predictions:
x1 = prediction.x - (prediction.width / 2)
x2 = prediction.x + (prediction.width / 2)
y1 = prediction.y - (prediction.height / 2)
y2 = prediction.y + (prediction.height / 2)
# Crop the license plate from the image
license_plate = img_np[int(y1):int(y2), int(x1):int(x2)]
license_plate_image = Image.fromarray(license_plate)
# Use easyocr to extract text from the cropped license plate
extracted_text = reader.readtext(np.array(license_plate_image), detail=0, paragraph=True)
if extracted_text:
# Clean and validate the extracted text
cleaned_text = extracted_text[0].strip().replace(" ", "").upper()
validated_text, vehicle_type = validate_vehicle_plate(cleaned_text, vehicle_type='both')
if validated_text != "Invalid plate format":
detected_text += validated_text + " "
vehicle_type_detected = vehicle_type # Set the detected vehicle type
print("Detected text:", detected_text.strip())
print("Vehicle type detected:", vehicle_type_detected)
return jsonify({
'text': detected_text.strip(),
'vehicle_type': vehicle_type_detected
})
else:
print("No plates detected")
return jsonify({'text': 'No plates detected', 'vehicle_type': 'Unknown'}), 200
except Exception as e:
print("Error during inference or processing:", e)
return jsonify({'error': 'Inference error'}), 500
javascript
function processVideo() {
const canvas = document.createElement(‘canvas’);
const context = canvas.getContext(‘2d’);
setInterval(() => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
context.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob((blob) => {
const formData = new FormData();
formData.append('image', blob, 'frame.jpg');
fetch('/parking/detect', {
method: 'POST',
body: formData
})
.then(response => {
// Log the content type to verify JSON
console.log('Response content type:', response.headers.get('Content-Type'));
return response.json(); // Attempt to parse as JSON
})
.then(data => {
console.log('Received data:', data); // Log the response
if (data.text) {
detectedText.value = data.text; // Display detected plate number
}
if (data.vehicle_type) {
detectedVehicleType.value = data.vehicle_type; // Display vehicle type
}
})
.catch(error => console.error("Error processing the frame or invalid JSON response: ", error));
}, 'image/jpeg');
}, 2000); // Process every 2 seconds
}