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 ???