Search code examples
pythonrestfastapidarknetyolov4

API Integration: IndexError: invalid index to scalar variable


I am trying to integrate my Yolov4 darknet customed trained model using fast api but am getting an IndexError: invalid index to scalar variable on console and Internal Server Error on Fastapi local server. Following is my code to run the API:

import cv2
import numpy as np
import tensorflow as tf

# Load YOLO v4 model
model = cv2.dnn.readNetFromDarknet("yolov4_test.cfg", "yolov4_train_final.weights")

from fastapi import FastAPI, File, UploadFile
from typing import List, Tuple

app = FastAPI()

@app.post("/detect_objects")
async def detect_objects(image: UploadFile = File(...)) -> List[Tuple[str, Tuple[int, int, int, int]]]:
    # Read image file
    image_bytes = await image.read()
    nparr = np.frombuffer(image_bytes, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

    # Run YOLO v4 model on image
    blob = cv2.dnn.blobFromImage(img, 1/255.0, (608, 608), swapRB=True, crop=False)
    model.setInput(blob)
    layer_names = model.getLayerNames()
    output_layers = [layer_names[i[0] - 1] for i in model.getUnconnectedOutLayers()]
    outputs = model.forward(output_layers)

    # Extract bounding boxes and class labels
    boxes = []
    for output in outputs:
        for detection in output:
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.5:
                center_x = int(detection[0] * img.shape[1])
                center_y = int(detection[1] * img.shape[0])
                width = int(detection[2] * img.shape[1])
                height = int(detection[3] * img.shape[0])
                left = int(center_x - width / 2)
                top = int(center_y - height / 2)
                boxes.append((class_id, (left, top, width, height)))

    # Map class IDs to class labels
    classes = ["Gun"]
    results = []
    for box in boxes:
        class_label = classes[box[0]]
        bbox = box[1]
        results.append((class_label, bbox))
        
    return results

Following is the error i am getting in console:

Traceback (most recent call last):
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 428, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\fastapi\applications.py", line 276, in __call__
    await super().__call__(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\applications.py", line 122, in __call__
    await self.middleware_stack(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
    raise exc
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\middleware\exceptions.py", line 79, in __call__
    raise exc
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\middleware\exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
    raise e
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\routing.py", line 718, in __call__
    await route.handle(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\starlette\routing.py", line 66, in app
    response = await func(request)
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\fastapi\routing.py", line 237, in app
    raw_response = await run_endpoint_function(
  File "c:\users\raafeh\desktop\fyp\envfast\lib\site-packages\fastapi\routing.py", line 163, in run_endpoint_function
    return await dependant.call(**values)
  File "C:\Users\Raafeh\Desktop\FYP\main.py", line 27, in detect_objects
    output_layers = [layer_names[i[0] - 1] for i in model.getUnconnectedOutLayers()]
  File "C:\Users\Raafeh\Desktop\FYP\main.py", line 27, in <listcomp>
    output_layers = [layer_names[i[0] - 1] for i in model.getUnconnectedOutLayers()]
IndexError: invalid index to scalar variable.

I am trying get the bounding boxes and Label out as the server response


Solution

  • Based on a quick search, this has nothing to do with FastAPI but rather is caused by trying to index a NumPy scalar, an integer or float for example.

    A quick look at the code would suggest that the i on the following line is an integer, and that causes the error:

    output_layers = [layer_names[i[0] - 1] for i in model.getUnconnectedOutLayers()]
    

    Maybe replacing layer_names[i[0] - 1] with layer_names[i - 1] might solve this.