Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ml studio not receive the predictions #460

Open
chathurach opened this issue Mar 22, 2024 · 1 comment
Open

ml studio not receive the predictions #460

chathurach opened this issue Mar 22, 2024 · 1 comment

Comments

@chathurach
Copy link

I'm trying to run the ml backend without docker. I have setup the server with some effort. The model seems to working fine and predict the result as expected. But I can't see any predections in the label-studio. Since I'm bit new for programming, am I doing something wrong? Here is my flask server:

import requests
from PIL import Image
from io import BytesIO
from flask import Flask, request, jsonify
from ultralytics import YOLO
from label_studio_ml.model import LabelStudioMLBase
from label_studio_ml.utils import get_single_tag_keys
import xml.etree.ElementTree as ET

app = Flask(__name__)

LS_URL = "http://localhost:8080"
LS_API_TOKEN = "0a1eb952a1fc99f77c8434c34ee82cea06e95674"

class YOLOv8Backend(LabelStudioMLBase):
    def __init__(self,**kwargs):
       # Call base class constructor
        super(YOLOv8Backend, self).__init__(**kwargs)
      
        self.labels = ['colony']
        # Load model
        self.model = YOLO("best.pt")
    def parse_xml_to_dict(self, xml_string):
        root = ET.fromstring(xml_string)
        parsed_dict = {}
        
        for child in root:
            
            if child.tag == 'Image':
                view_info = {}
                view_info['from_name'] = child.attrib['name']
                view_info['inputs'] = [{
                    'type': 'image',
                    'value': child.attrib['value']
                }]
                parsed_dict['items'] = view_info
            elif child.tag == 'RectangleLabels':
                if 'items' not in parsed_dict:
                    parsed_dict['items'] = {}
                parsed_dict['items']['type'] = child.tag
                parsed_dict['items']['to_name'] = [child.attrib['toName']]
                labels = [label.attrib['value'] for label in child.findall('Label')]
                parsed_dict['items']['labels'] = labels
        
        return parsed_dict
    
    def predict(self, data, **kwargs):
        """
        Returns the list of predictions based on input list of tasks for 1 image
        """
        tasks = data.get('tasks')
        task = tasks[0]
        label_config = data.get('label_config')
        parsed_config = self.parse_xml_to_dict(label_config)
        image_url = task['data']['image']
        self.from_name, self.to_name, self.value, self.classes = get_single_tag_keys(parsed_config, 'RectangleLabels', 'image')
        # Getting URL of the image
        full_url = LS_URL + image_url
        # Header to get request
        header = {
            "Authorization": "Token " + LS_API_TOKEN}
        # Getting URL and loading image
        image = Image.open(BytesIO(requests.get(
            full_url, headers=header).content))
        # Height and width of image
        original_width, original_height = image.size
        # Creating list for predictions and variable for scores
        predictions = []
        score = 0
        i = 0

        # Getting prediction using model
        results = self.model.predict(image)
        # Getting mask segments, boxes from model prediction
        for result in results:
            for i, prediction in enumerate(result.boxes):
                xyxy = prediction.xyxy[0].tolist()
                predictions.append({
                    "id": str(i),
                    "from_name": self.from_name,
                    "to_name": self.to_name,
                    "type": "rectanglelabels",
                    "score": prediction.conf.item(),
                    "original_width": original_width,
                    "original_height": original_height,
                    "image_rotation": 0,
                    "value": {
                        "rotation": 0,
                        "x": xyxy[0] / original_width * 100,
                        "y": xyxy[1] / original_height * 100,
                        "width": (xyxy[2] - xyxy[0]) / original_width * 100,
                        "height": (xyxy[3] - xyxy[1]) / original_height * 100,
                        "rectanglelabels": [self.labels[int(prediction.cls.item())]]
                    }})
                score += prediction.conf.item()

        # print(f"Prediction Score is {score:.3f}.")

        # print(len(predictions))
        # Dict with final dicts with predictions
        final_prediction = [{
            "result": predictions,
            "score": score / (i + 1),
            "model_version": "v8n"
        }]

        return final_prediction
       

backend = YOLOv8Backend()

@app.route('/predict', methods=['POST'])
def predict():
    data = request.json
    results = backend.predict(data =data)
    return jsonify(results)
    

@app.route('/health', methods=['GET'])
def health():
    return jsonify({
        'status': 'UP',
        'model_class': 'YOLOv8'
    })

@app.route('/setup', methods=['POST'])
def setup():
    return jsonify({'model_version': 'Yolov8'})

if __name__ == '__main__':
    app.run(debug=True,host='localhost',port='9090')

Initially I got the error "in get_single_tag_keys assert len(parsed_label_config) == 1"
But I did some hacky job to avoid that. As I said, model is predicting the objects as intended since I can see the output in my server side. But strangely nothing is happening in the label-studio. And I don't see any errors.

This is my server side when sending the predictions
cmd2

this is the label-studio
cmd1

@niklub
Copy link
Contributor

niklub commented Apr 5, 2024

  1. It is recommended to follow the latest guide when creating and installing ML backend service - otherwise the prediction payload protocol might be incompatible with what expects Label Studio app
  2. Try to enable debug logging to see more logs in ML backend server (LOG_LEVEL=DEBUG)
  3. In Label Studio, open browser Console and Network, and check for possible errors there regarding what is retrieved in /api/tasks/{id} endpoint. Make sure the JSON structure follows the format for preannotations

Hope this helps, let me know if not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants