UnboundLocalError

I ran the code on Ubuntu 20.04, khadas vim3 and the UnboundLocalError is not resolved.

import cv2
import numpy as np
import ksnn.api
import os
from ksnn.api import output_format

npu = ksnn.api.KSNN('VIM3')
model_path = "/home/khadas/Downloads/MoveNet_TFLite_NPU.nb"

if not os.path.exists(model_path):
    raise ValueError(f"path Error: {model_path}")

npu.nn_init(library='/home/khadas/libnn_MoveNet_TFLite_NPU.so', model=model_path, level=0)

KEYPOINT_DICT = {
    'nose': 0,
    'left_eye': 1,
    'right_eye': 2,
    'left_ear': 3,
    'right_ear': 4,
    'left_shoulder': 5,
    'right_shoulder': 6,
    'left_elbow': 7,
    'right_elbow': 8,
    'left_wrist': 9,
    'right_wrist': 10
}


KEYPOINT_EDGE_INDS_TO_COLOR = {
    (0, 1): (255, 0, 255),
    (0, 2): (0, 255, 255),
    (1, 3): (255, 0, 255),
    (2, 4): (0, 255, 255),
    (0, 5): (255, 0, 255),
    (0, 6): (0, 255, 255),
    (5, 7): (0, 0, 255),  # 왼팔 (빨간색)
    (7, 9): (0, 0, 255),  # 왼팔 (빨간색)
    (6, 8): (255, 0, 0),  # 오른팔 (파란색)
    (8, 10): (255, 0, 0),  # 오른팔 (파란색)
    (5, 6): (255, 255, 0)
}

def _keypoints_and_edges_for_display(keypoints_with_scores, height, width, keypoint_threshold=0.11):
    keypoints_all = [ ]
    keypoint_edges_all = []
    edge_colors = []

    num_instances, _, _, _ = keypoints_with_scores.shape
    for idx in range(num_instances):
        kpts_x = keypoints_with_scores[0, idx, :, 1]
        kpts_y = keypoints_with_scores[0, idx, :, 0]
        kpts_scores = keypoints_with_scores[0, idx, :, 2]

        kpts_absolute_xy = np.stack([width * np.array(kpts_x[:11]), height * np.array(kpts_y[:11])], axis=-1)
        kpts_above_thresh_absolute = kpts_absolute_xy[kpts_scores[:11] > keypoint_threshold, :]
        keypoints_all.append(kpts_above_thresh_absolute)

        for edge_pair, color in KEYPOINT_EDGE_INDS_TO_COLOR.items():
            if kpts_scores[edge_pair[0]] > keypoint_threshold and kpts_scores[edge_pair[1]] > keypoint_threshold:
                x_start = kpts_absolute_xy[edge_pair[0], 0]
                y_start = kpts_absolute_xy[edge_pair[0], 1]
                x_end = kpts_absolute_xy[edge_pair[1], 0]
                y_end = kpts_absolute_xy[edge_pair[1], 1]
                line_seg = np.array([[x_start, y_start], [x_end, y_end]])
                keypoint_edges_all.append(line_seg)
                edge_colors.append(color)

    if keypoints_all:
        keypoints_xy = np.concatenate(keypoints_all, axis=0)
    else:
        keypoints_xy = np.zeros((0, 17, 2))

    if keypoint_edges_all:
        edges_xy = np.stack(keypoint_edges_all, axis=0)
    else:
        edges_xy = np.zeros((0, 2, 2))
    
    return keypoints_xy, edges_xy, edge_colors

def draw_prediction_on_image(image, keypoints_with_scores):
    height, width, _ = image.shape
    keypoints_xy, edges_xy, edge_colors = _keypoints_and_edges_for_display(keypoints_with_scores, height, width)

    for keypoint in keypoints_xy:
        cv2.circle(image, (int(keypoint[0]), int(keypoint[1])), 4, (0, 255, 0), -1)

    for edge, color in zip(edges_xy, edge_colors):
        p1 = tuple(edge[0].astype(int))
        p2 = tuple(edge[1].astype(int))
        cv2.line(image, p1, p2, color, 2)

    keypoints_dict = {k: (int(keypoints_xy[KEYPOINT_DICT[k]][0]), int(keypoints_xy[KEYPOINT_DICT[k]][1])) for k in KEYPOINT_DICT.keys() if len(keypoints_xy) > KEYPOINT_DICT[k]}

    if 'left_wrist' in keypoints_dict and 'left_shoulder' in keypoints_dict and keypoints_dict['left_wrist'][1] < keypoints_dict['left_shoulder'][1]:
        cv2.putText(image, "Raise Right Arm", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)

    if 'right_wrist' in keypoints_dict and 'right_shoulder' in keypoints_dict and keypoints_dict['right_wrist'][1] < keypoints_dict['right_shoulder'][1]:
        cv2.putText(image, "Raise Left Arm", (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)

    return image


cap = cv2.VideoCapture(0)

while cap.isOpened():
    ret, frame = cap.read()
    
    if not ret:
        break

    # 좌우 반전
    frame = cv2.flip(frame, 1)

    input_image = cv2.resize(frame, (256, 256))
    input_image = input_image.astype(np.float32)

   
    input_image /= 255.0
    input_image = input_image.transpose(2, 0, 1)  # (H, W, C) -> (C, H, W)
    input_list = [input_image]

    output = npu.nn_inference(cv_img=input_list, platform='TFLITE', reorder='0 1 2', input_tensor=1, output_tensor=1, output_format=output_format.OUT_FORMAT_FLOAT32)

    keypoints_with_scores = np.array(output[0]) 
    output_overlay = draw_prediction_on_image(frame, keypoints_with_scores)
    
    cv2.imshow('MoveNet', output_overlay)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
khadas@Khadas:~/ksnn$ /bin/python3 /home/khadas/MoveNet_TFL_NPU_KSNN.py
Traceback (most recent call last):
  File "/home/khadas/MoveNet_TFL_NPU_KSNN.py", line 126, in <module>
    output = npu.nn_inference(cv_img=input_list, platform='TFLITE', reorder='0 1 2', input_tensor=1, output_tensor=1, output_format=output_format.OUT_FORMAT_FLOAT32)
  File "/home/khadas/.local/lib/python3.8/site-packages/ksnn/api.py", line 228, in nn_inference
    res = self.nn_set_inputs(cv_img, platform=platform, reorder=reorder, tensor=input_tensor)
  File "/home/khadas/.local/lib/python3.8/site-packages/ksnn/api.py", line 149, in nn_set_inputs
    del pixel_data
UnboundLocalError: local variable 'pixel_data' referenced before assignment
1 Like

Helo @afa1414

@Louis-Cheng-Liu will help you later.

Hello @afa1414 ,

Could you provide your model and your convert demo?

khadas vim3 , ubuntu20.02
model : MoveNet single pose Thunder TFLite ver
I used convert tool in python file

Hello @afa1414 ,

Sorry, i do not describe clearly. We can not reproduce your problem by using our model, so we need your model and your convert parameters when you convert to help us find the cause of problem.

Are you talking about this?
./convert --model-name MoveNet_TFLite_NPU --platform tflite --model /home/ss/movenet/TFlite_model/movenet_singlepose_thunder.tflite --mean-values ‘127.5 127.5 127.5 0.007843137’ --quantized-dtype dynamic_fixed_point --qtype int8 --kboard VIM3 --print-level 1 --source-files dataset.txt

Hello @afa1414 ,

Yes, and your original model.

import tensorflow as tf
import tensorflow_hub as hub
import os

model_url = “Google | movenet | Kaggle
model_path = “/home/ss/movenet/TFlite_model/movenet_singlepose_thunder”

os.makedirs(model_path, exist_ok=True)

model = hub.load(model_url)

class Movenet(tf.Module):
def init(self, model):
self.model = model

@tf.function(input_signature=[tf.TensorSpec(shape=[1, 256, 256, 3], dtype=tf.int32)])
def serve(self, inputs):
    return self.model.signatures["serving_default"](inputs)

movenet = Movenet(model)

tf.saved_model.save(movenet, model_path, signatures={“serving_default”: movenet.serve})

converter = tf.lite.TFLiteConverter.from_saved_model(model_path)
tflite_model = converter.convert()

tflite_model_path = “/home/ss/movenet/TFlite_model/movenet_singlepose_thunder.tflite”
with open(tflite_model_path, “wb”) as f:
f.write(tflite_model)

I converted it to a TFLite model through this code.

@Louis-Cheng-Liu plz checking this reply

The error you’re encountering, “UnboundLocalError: local variable ‘pixel_data’ referenced before assignment,” indicates that the nn_set_inputs function in the ksnn.api library is trying to delete a variable pixel_data that hasn’t been assigned a value yet.

  • Check nn_set_inputs function: Look at the implementation of the nn_set_inputs function in the ksnn.api library (line 149 as mentioned in the error). See if there’s a scenario where pixel_data is used before being assigned. This might involve conditional statements or early returns.
  • Review input preparation: Ensure your input_list is formatted correctly for the nn_set_inputs function. The documentation for ksnn.api.nn_inference might specify the expected format for the cv_img argument. It might require conversion to a specific format or additional preprocessing before being passed to the function.

Hello @afa1414 ,

Your model input type is int32. Now KSNN does not support int32.

I guess convert tool does not convert input from int32 to int8. So pixel_data does not be declared in KSNN. Suggest you to remove this structure and use float16 input directly. This structure only the normalization of input. You can do it in python code.

1 Like

So this model cannot be converted to int8? Are the tools the problem?
I tried training the model again, but it wasn’t converted to int8.

Also, when converting, I used only Durant from the example dataset photo file. Did this have an impact? And when converting the model, I don’t know which dataset to use or how much to use.
@Louis-Cheng-Liu

1 Like

Hello @afa1414 ,

Dataset images only affect the accuracy of model after conversion. It can not cause converting fail. The images have better that are actual using scenarios. The number of images are about 200.

I tried to convert your model into int8, also fail. Your model is the open source model. For ease of use in python, most of them will add preprocess and postprocess in model. But almost all of them are not supported on NPU. So suggest you try to remove the preprocess structure and postprocess structure in model and then try again. Or try to change another model like yolopose.

If you need, i can ask our engineer for help. It will take about a week. Maybe they have better way to solve.

Thank you very much kind your reply

I want to run and compare several human pose estimation models on a Khadas VIM3 board. Have you run any models on it? I would appreciate it if you could provide any models or code that are compatible.
@Louis-Cheng-Liu

I would appreciate it if you could provide information about YOLOv8 pose models along with related code.

Hello @afa1414 ,

Sorry, we do not have YOLOv8 pose demo now. You can try to reflect our YOLOv8n demo codes and change it by yourself.
YOLOv8n KSNN Demo - 2 [Khadas Docs]

Is there a human pose estimation model compatible with this board?
Or, could I know about models that are not compatible?
@Louis-Cheng-Liu