Convert script python to .json file

Hello
I wrote a scipt in python to detect distance between camera and object, i want to send the distance to an appli node red.
Is it possible to convert this script into a .json file and import it into node red to get the readed data into the debug node or into the dashboard ?
i've tried to exec the script automatically in node red but it didn"t work
Thanks.

Within node-red, no. Have you tried a google search? Try convert python to node.js

How exactly did you try this and what, if any, errors?

I'm pretty sure you mean convert python to JavaScript right?

How much code is it? It may be a simple translation (then there would be no need to spawn python)

Paste your python code in a reply - don't forget to use the code button (click it then paste python between the 3 backticks)

##########################

import numpy as np
import imutils
import cv2 as cv
import urllib.request
import ssl


video=cv.VideoCapture(0)
address='http://192.168.1.6:8080/shot.jpg'
video.open(address)

Known_distance = 30  
Known_width = 5.7
whT = 320 #width,high,Target 320 cause we re using 320 version yolo
confThreshold =0.5
nmsThreshold= 0.2
Distance_level = 0

# Define the codec and create VideoWriter object
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output21.mp4', fourcc, 30.0, (640, 480))

#extract the file "coco caméra" qui contient la liste des objets à détectés
classesFile = "/home/pi/Desktop/coco.names"
classNames = []
with open(classesFile, 'rt') as f:
    classNames = f.read().rstrip('\n').split('\n')
print(classNames)

#importer la configuration des fichier .cfg et .weights
modelConfiguration = "/home/pi/Desktop/yolov3-tiny.cfg"
modelWeights = "/home/pi/Desktop/yolov3-tiny.weights"
#creating our network, we re going to read from darknet model config nd model weights
net = cv.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)


def FocalLength(measured_distance, real_width, width_in_rf_image):
    focal_length = (width_in_rf_image * measured_distance) / real_width
    return focal_length


def Distance_finder(Focal_Length, real_object_width, object_width_in_frame):
    distance = (real_object_width * Focal_Length)/object_width_in_frame
    return distance


def findObjects(outputs,img):
    
    hT, wT, cT = img.shape
    bbox = []
    classIds = []
    confs = []
    for output in outputs:
        for det in output:
            scores = det[5:]
            classId = np.argmax(scores)
            confidence = scores[classId]
            #filtring our project
            if confidence > confThreshold:
                w,h = int(det[2]*wT) , int(det[3]*hT)
                x,y = int((det[0]*wT)-w/2) , int((det[1]*hT)-h/2)
                bbox.append([x,y,w,h])
                classIds.append(classId)
                confs.append(float(confidence))
     #déterminer l'indice du box dont la pourcentage du conf est la plus grande
    indices = cv.dnn.NMSBoxes(bbox, confs, confThreshold, nmsThreshold)
    object_width = 0
    object_x, object_y = 0,0
    object_center_x = 0
    object_center_y = 0
    
    for i in indices:
        i = i[0]
        box = bbox[i]
        x, y, w, h = box[0], box[1], box[2], box[3]
            #draw the box
        cv.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
        cv.putText(img, f'{classNames[classIds[i]].upper()}',(x,y-10),cv.FONT_HERSHEY_SIMPLEX,0.6,(255,0,255),2)
        print(classNames[classIds[i]])
        object_width = w
        object_center =[]
        object_center_x = int(w/2)+x
        object_center_y = int(h/2)+y
        
        object_x = x
        object_y = y
        
    return object_width, bbox, object_center_x, object_center_y
    

# reading reference image from directory
ref_image = cv.imread("Image_test.PNG")
blob = cv.dnn.blobFromImage(ref_image, 1 / 255, (whT, whT), [0, 0, 0], 1, crop=False)
net.setInput(blob)
layersNames = net.getLayerNames()
outputNames = [(layersNames[i[0] - 1]) for i in net.getUnconnectedOutLayers()]

outputs = net.forward(outputNames)
ref_image_object_width, _, _, _ = findObjects(outputs,ref_image)

Focal_length_found = FocalLength( Known_distance, Known_width, ref_image_object_width)
print(Focal_length_found)
cv.imshow("ref_image", ref_image)

   

while True:
    imgResp = urllib.request.urlopen(address)
    imgNp = np.array(bytearray(imgResp.read()), dtype=np.uint8)
    img = cv.imdecode(imgNp, -1)
    #convertir l'image de la caméra into our network, network accepts only a blob file(binary large object)
    blob = cv.dnn.blobFromImage(img, 1 / 255, (whT, whT), [0, 0, 0], 1, crop=False)
    net.setInput(blob)
    layersNames = net.getLayerNames()

    #print(layerNames)
    #extract only the output layers
    outputNames = [(layersNames[i[0] - 1]) for i in net.getUnconnectedOutLayers()]
    outputs = net.forward(outputNames)
    findObjects(outputs,img)
    object_width_in_frame, bbox, OB_X ,OB_Y = findObjects(outputs,img)

    for (object_x, object_y, object_w, object_h) in bbox:
        Distance=Distance_finder(Focal_length_found,Known_width,object_width_in_frame )
        Distance = round(Distance, 2)
        cv.putText(img, f"Distance {Distance} Inches",(object_x-6, object_y-6), cv.FONT_HERSHEY_COMPLEX, 0.5, (0,0,0), 2)
        print(Distance*0.0254)
    cv.imshow('temp',cv.resize(img,(600,400)))
    
    q = cv.waitKey(1)
    if q == ord("q"):
        break
         
video.release()
cv.destroyAllWindows 
##########################

This is my python script , i want to send the distance value to node red

Admin edit - put code in a code block as was requested!

Forget converting to javascript. You have dependencies to external libraries specifically written in Python. Much better to run the script outside of Node-RED and communicate the result to Node-RED. As example via MQTT

1 Like

image

i've tried to exec it but in vain

No, not that way. Do it with an exec node set to spawn mode and see what you get

sorry i am a bit new to Node-red programming

Is your script working as expected if you run it in a terminal? You run it in Linux on a Raspberry pi?

Anyway, I would run it in a terminal and send results (distance) to Node-RED via MQTT or http. You will have to add code in your python script for mqtt (or http) communication and if you go for mqtt, also install a mqtt broker. This sounds more complicated than it is, it is rather simple actually. One more time, try to format your script correctly or attach it as a file (you have to rename it to .txt). I can help you with mqtt in python, I have done it maybe hundred times

EDIT: you should use yolov4, is better and more accurate than yolov3

Yes it works when i run it in a terminal
I couldn't integrate the mqtt communication in the script
U should install the application "ip webcam" in your phone to run the script cause i've been using the phone camera

i would be grateful if you could help meee
Thank u so much
distance.txt (4.7 KB)

Sure, I will look at it, starting tomorrow

In the mean time, prepare your system a bit

Install mosquitto broker in your Raspberry Pi

Install Paho mqtt client (needed for the script)
pip3 install paho-mqtt

You can try this script. I have added the mqtt part and it works, you have to test with your camera

The flow below has very simple features:

  • just receiving the calculated distance from the script
  • command to abort the script (important since we have a thread running in the script, so you you not kill it with ctrl+c)

Start the script in a terminal: python3 distance.py

distance.txt (6.1 KB)

image

[{"id":"f097b105.f85e5","type":"mqtt in","z":"fcecd26b.a4283","name":"","topic":"distance/result","qos":"2","datatype":"auto","broker":"56c5f0f2.9f483","nl":false,"rap":true,"rh":0,"x":280,"y":940,"wires":[["c76a1e70.41db4"]]},{"id":"c76a1e70.41db4","type":"debug","z":"fcecd26b.a4283","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":520,"y":940,"wires":[]},{"id":"8c8a7d9d.505e2","type":"inject","z":"fcecd26b.a4283","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Stop-Distance-Analyzer","payloadType":"str","x":310,"y":1040,"wires":[["db5fe3a4.dbf9"]]},{"id":"db5fe3a4.dbf9","type":"mqtt out","z":"fcecd26b.a4283","name":"","topic":"distance","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"56c5f0f2.9f483","x":520,"y":1040,"wires":[]},{"id":"56c5f0f2.9f483","type":"mqtt-broker","name":"","broker":"127.0.0.1","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Yes it works , it sends the result to the debug node when i execute the script from the raspberry , how could i exec the script automatically from node red ?

Do you mean you want to start the script automatically from Node-RED? When the raspberry boots up?

What is your cpu load on the raspberry while the script is running? If it is high I think you need to insert a short "time.sleep(0.1)" in your while loop

There is a node called exec you should be able to enter the script command into it then send the node a signal (for example from an inject node) and it will run the script on the RPi.

For example, this will restart node-red by running the command node-red restart

image

[{"id":"39a5db5dd9ed8fcd","type":"inject","z":"e152a286a73e145c","g":"7e318a61314a68a2","name":"Restart Node-Red","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":150,"y":1320,"wires":[["8213394121366793"]]},{"id":"8213394121366793","type":"exec","z":"e152a286a73e145c","g":"7e318a61314a68a2","command":"node-red restart","addpay":"","append":"","useSpawn":"true","timer":"","winHide":false,"oldrc":false,"name":"","x":360,"y":1320,"wires":[[],[],[]]}]

Gunner, the exec node is already mentioned. But it will not work that simple, the script has some features inside that requires access to the display so the command needed in the exec node has to be a "bit more extensive" so to say

First I need to know if this is what is asked for

Ah, yes... I missed a bunch of posts. Sorry.

I have ran more complex scripts myself by formulating the command needed (whatever works in the terminal) via a function node then sending that to the exec node.

But again as you say, we need to know what is wanted, and perhaps the actual command that works.

No problem - but it is always good to read up on the topic first :wink: