2

I'm currently using a Pepper Robot to take photos that I use to detect object from coco_classes with a yolov3 algorithm (https://github.com/qqwweee/keras-yolo3) located on my Windows 10 computer. I made an app that can be used on Pepper Tablet using responsive (html, bootstrap, php, ...), to select the object you want to recognize. I'm struggling to pass the class name value from php to a python file called yolo_video.py, it's unlucky because I really want the robot to point out the recognized object, so I need to interact with this Python file.

One important thing to know is that I use Anaconda to call the script and have GPU acceleration.

I tried every single command to pass a value from PHP to Python, sometimes it works, but the script do not complete is mission when it's the case (It's really strange because called from a command prompt it's working fine). With no input, the code works fine even when called from php.

I try to use exec() command because it returns an array-like value witch I can use to take back the last printed element of the python script (witch is angle information that need to take the robot to point the object).

here is yolo_detect.php :

<?php

$classe = $_GET ["choice"];

exec("C:/Anaconda/Scripts/activate yolo && cd C:/wamp64/www/app/projetba3/ && python yolo_video.py --image $who", $value); 


echo "valeur envoye ".$class;
var_dump ($value)

?>

You can see that i try to call the yolo_video.py after activating my yolo environment with the parameter --image (Because i do the recognition on one image taken by the robot). I wonder if that argument can cause problems ?

Yolo_video.py :

import sys
import argparse
from yolo import YOLO, detect_video
from PIL import Image

def detect_img(yolo):
    while True:
        img = "C:\wamp64\www\App\projetba3\camImage.png"
        try:
            image = Image.open(img)
        except:
            print('Open Error! Try again!')
            continue
        else:

            r_image, angle = yolo.detect_image(image,str(classe)) #img passe dans le réseau de neurone
            print(angle)
            #r_image.show() 
            r_image.save("C:\wamp64\www\App\projetba3\camerapepper.png")
        break;
    yolo.close_session()

FLAGS = None

if __name__ == '__main__':

    classe = sys.argv[1]
    print(sys.argv[1])

    # class YOLO defines the default value, so suppress any default here
    parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
    '''
    Command line options
    '''

    parser.add_argument(
        '--model', type=str,
        help='path to model weight file, default ' + YOLO.get_defaults("model_path")
    )

    parser.add_argument(
        '--anchors', type=str,
        help='path to anchor definitions, default ' + YOLO.get_defaults("anchors_path")
    )

    parser.add_argument(
        '--classes', type=str,
        help='path to class definitions, default ' + YOLO.get_defaults("classes_path")
    )

    parser.add_argument(
        '--gpu_num', type=int,
        help='Number of GPU to use, default ' + str(YOLO.get_defaults("gpu_num"))
    )

    parser.add_argument(
        '--image', default=True, action="store_true",
        help='Image detection mode, will ignore all positional arguments'
    )
    '''
    Command line positional arguments -- for video detection mode
    '''
    parser.add_argument(
        "--input", nargs='?', type=str,required=False,default='./path2your_video',
        help = "Video input path"
    )

    parser.add_argument(
        "--output", nargs='?', type=str, default="",
        help = "[Optional] Video output path"
    )


    FLAGS = parser.parse_args()

    if FLAGS.image:
        """
        Image detection mode, disregard any remaining command line arguments
        """
        print("Image detection mode")
        if "input" in FLAGS:
            print(" Ignoring remaining command line arguments: " + FLAGS.input + "," + FLAGS.output)
        detect_img(YOLO(**vars(FLAGS)))

    elif "input" in FLAGS:
        detect_video(YOLO(**vars(FLAGS)), FLAGS.input, FLAGS.output)
    else:
        print("Must specify at least video_input_path.  See usage with --help.")

You can see that i use the simple sys.argv[1] to put the value in classe variable. This value is transmitted to another python file yolo.py inside the function yolo.detect_image(image,str(classe)). I added in the function the calculation for the robot position that i need to have. Here is the function :

def detect_image(self, image, classe):
        start = timer()

        if self.model_image_size != (None, None):
            assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
            assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (image.width - (image.width % 32),
                              image.height - (image.height % 32))
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype='float32')

        print(image_data.shape)
        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0
            })

        print('Found {} boxes for {}'.format(len(out_boxes), 'img'))

        font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
                    size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
        thickness = (image.size[0] + image.size[1]) // 300
        angle = (0,0)
        for i, c in reversed(list(enumerate(out_classes))):
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            label = '{} {:.2f}'.format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)

            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype('int32'))
            left = max(0, np.floor(left + 0.5).astype('int32'))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
            right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
            print(label, (left, top), (right, bottom))

            if str(predicted_class)== classe :
                ite =+ 1
                if ite == 1 : 
                    centresofa = (left+(right-left)/2,top+(bottom-top)/2)
                    print (centresofa)
                    anglehor = 55.2*(centresofa[0]/640)
                    print (anglehor)
                    if anglehor > 27.2 :
                        anglehor = anglehor - 27.2
                    if anglehor < 27.2 :
                        anglehor = -(27.2 - anglehor)
                    else :
                        anglehor = 0 

                    anglever = 44.3*(centresofa[1]/480)
                    print(anglever)
                    if anglever < 22.15 :
                        anglever = 22.15-anglever
                    if anglever > 22.15 :
                        anglever = -(anglever-22.15)
                    else :
                        anglever = 0
                    print ("angle horizontal "+str(anglehor)+"angle vertical "+str(anglever))
                    angle = (anglehor,anglever)


            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, top + 1])

            # My kingdom for a good redistributable image drawing library.
            for i in range(thickness):
                draw.rectangle(
                    [left + i, top + i, right - i, bottom - i],
                    outline=self.colors[c])
            draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=self.colors[c])
            draw.text(text_origin, label, fill=(0, 0, 0), font=font)
            del draw

        end = timer()
        print(end - start)
        return image, angle

I should take the values back in the last element of var_dump($values), instead, it just shows me print(sys.argv[1]) value and nothing else (sign that the script stops just after it started). A more strange fact is that his value is "--image" (the argument of my function). How can i solve this big mess ? How is this exec() function really working with input arguments ???

TVK
  • 1,042
  • 7
  • 21

1 Answers1

0

Python

python yolo_video.py --image $who

sys.argv[0] = yolo_video.py
sys.argv[1] = --image
sys.argv[2] = $who (classname)

I believe you are passing argv[1] "--image" as the class name, when you should be passing argv[2]

https://www.pythonforbeginners.com/argv/more-fun-with-sys-argv

Also, you are trying to use classe as a global variable within detect_img(). This is not a good way to do this and you would have to add a global keyword to make it work.

Change detect_img(yolo) to detect_img(yolo, classe) and pass the actual classe variable to the function via sys.argv[2]

Line 83: detect_img(YOLO(**vars(FLAGS)), sys.argv[2])

PHP

echo "valeur envoye ".$class;

should be

echo "valeur envoye ".$classe;
Kenneth
  • 535
  • 2
  • 17