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

How to get a rotated rectangle from serverless api? #6891

Closed
WilliamKyle opened this issue Sep 22, 2023 · 5 comments · Fixed by #6961
Closed

How to get a rotated rectangle from serverless api? #6891

WilliamKyle opened this issue Sep 22, 2023 · 5 comments · Fixed by #6961
Assignees
Labels
enhancement New feature or request

Comments

@WilliamKyle
Copy link
Contributor

here is the raw output of rectangle from https://github.com/opencv/cvat/blob/develop/serverless/onnx/WongKinYiu/yolov7/nuclio/model_handler.py

 results.append({
                        "confidence": str(score),
                        "label": self.labels.get(label, "unknown"),
                        "points": [xtl, ytl, xbr, ybr],
                        "type": "rectangle",
                    })

I try to add rotation and it's not work

 results.append({
                        "confidence": str(score),
                        "label": self.labels.get(label, "unknown"),
                        "points": [xtl, ytl, xbr, ybr],
                        "type": "rectangle",
                        "rotation": "30",
                    })

I try to add rotation in attributes and it's also not work

 results.append({
                        "confidence": str(score),
                        "label": self.labels.get(label, "unknown"),
                        "points": [xtl, ytl, xbr, ybr],
                        "type": "rectangle",
                        "attributes": [
                            {"name": "rotation", "value": "30"},
                        ],
                    })

how can I get a rotated rectangle ?

@zhiltsov-max
Copy link
Contributor

Hi, you will probably need to modify the server code to enable support for this. Please check the module source code here.

@jaffe-fly
Copy link

when use yolo obb model,

def handler(context, event):
    context.logger.info('Run custom yolo model')
    data = event.body
    threshold = data.get('threshold', 0.55)

    region = data.get('region', [700, 250, 1050, 720])  # Expected format: [x, y, width, height]
    # region = data.get('region', None)
    image_buffer = io.BytesIO(base64.b64decode(data['image']))
    image = cv2.imdecode(np.frombuffer(image_buffer.getvalue(), np.uint8), cv2.IMREAD_COLOR)

    # Process region if specified
    if region:
        x, y, w, h = map(int, region)
        # Ensure coordinates are within image bounds
        x = max(0, min(x, image.shape[1]))
        y = max(0, min(y, image.shape[0]))
        w = max(0, min(w, image.shape[1] - x))
        h = max(0, min(h, image.shape[0] - y))

        # Crop image to region
        roi = image[y:y + h, x:x + w]
    else:
        roi = image
        x, y = 0, 0

    results = context.user_data.model_handler(image, device=0, half=True, imgsz=1024, conf=threshold, iou=0.3)
    result = results[0]

    boxes = result.obb.xyxy
    rotations = result.obb.data[:, 4]
    confs = result.obb.conf
    clss = result.obb.cls
    class_name = result.names

    detections = []
    for box, conf, cls, r in zip(boxes, confs, clss, rotations):
        label = class_name[int(cls)]
        transformed_box = box.tolist()
        if region:
            # Adjust x coordinates
            transformed_box[0] += x
            transformed_box[2] += x
            # Adjust y coordinates
            transformed_box[1] += y
            transformed_box[3] += y

        detect = {
            'confidence': str(float(conf)),
            'label': label,
            'points': box.tolist(),
            'type': 'rectangle',
            'rotation': float(r),
        }
        context.logger.info(f'model predict: {detect}')
        # must be in this format
        detections.append(detect)

    return context.Response(body=json.dumps(detections), headers={},
                            content_type='application/json', status_code=200)

but the result in cvat, the rotatios seems not very good !!

why?

@jaffe-fly
Copy link

by my test obb.xyxyxyxy still not get a rotate box, could any one give a example, when set type is polygon , will acroding xyxyxyxy draw a rotate box, but cant convert to rectangle

@zhiltsov-max
Copy link
Contributor

zhiltsov-max commented Dec 30, 2024

@jaffe-fly, there must be a rotation (the angle in degrees) in the rotation attribute. It's only supported for rectangles and ellipses. Your code seems to be correct, but maybe the angles have to be converted to degrees? It's parsed like this: https://github.com/cvat-ai/cvat/blob/develop/cvat/apps/lambda_manager/views.py#L730-L731.

@jaffe-fly
Copy link

jaffe-fly commented Jan 2, 2025

def normalize_angle(width, height, angle):
    angle_deg = math.degrees(angle)
    angle_deg = angle_deg % 360

    if 75 <= angle_deg <= 105:
        return angle_deg - 90

    if angle_deg > 270:
        return angle_deg - 360  
    elif angle_deg > 180:
        return angle_deg - 360  
    return angle_deg  


def handler(context, event):
    context.logger.info('Run custom yolo model')
    data = event.body
    threshold = data.get('threshold', 0.55)

    region = data.get('region', [700, 250, 1260, 720])  # Expected format: [x, y, width, height]
    # region = data.get('region', None)
    image_buffer = io.BytesIO(base64.b64decode(data['image']))
    image = cv2.imdecode(np.frombuffer(image_buffer.getvalue(), np.uint8), cv2.IMREAD_COLOR)

    # Process region if specified
    if region:
        x, y, w, h = map(int, region)
        # Ensure coordinates are within image bounds
        x = max(0, min(x, image.shape[1]))
        y = max(0, min(y, image.shape[0]))
        w = max(0, min(w, image.shape[1] - x))
        h = max(0, min(h, image.shape[0] - y))

        # Crop image to region
        roi = image[y:y + h, x:x + w]
    else:
        roi = image
        x, y = 0, 0

    results = context.user_data.model_handler(roi, device=0, half=True, imgsz=1024, conf=threshold, iou=0.3)
    result = results[0]

    boxes = result.obb.xyxy
    boxes_angle = result.obb.xywhr
    confs = result.obb.conf
    clss = result.obb.cls
    class_name = result.names

    detections = []
    for box, conf, cls, r in zip(boxes, confs, clss, boxes_angle):
        center_x, center_y, boxw, boxh, angle = r
        orientation = normalize_angle(boxw, boxh, angle)
        label = class_name[int(cls)]

        transformed_box = box.tolist()

        if region:
            transformed_box[0] += x
            transformed_box[1] += y
            transformed_box[2] += x
            transformed_box[3] += y

        detect = {
            'confidence': str(float(conf)),
            'label': label,
            'points': transformed_box,
            'type': 'rectangle',
            'rotation': float(orientation),
            'w': float(boxw),
            'h': float(boxh),
            'r': float(angle),
        }
        context.logger.info(f'model predict: {detect}')
        # must be in this format
        detections.append(detect)

    return context.Response(body=json.dumps(detections), headers={},
                            content_type='application/json', status_code=200)

here is my code for reference

Hope someone can provide a better solution

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

Successfully merging a pull request may close this issue.

4 participants