Unable to get print results from YOLOv4 Python object detection, PHP returns blank
P粉275883973
2023-08-28 12:41:17
<p>I am using this git package to run target detection using YOLOv4 in Python</p>
<pre class="brush:php;toolbar:false;">https://github.com/erentknn/yolov4-object-detection</pre>
<p>The script runs fine and I can print out the found targets in the terminal with confidence, but when I execute it from PHP the results returned are empty. I guess it might be because the PHP script is waiting for Python to finish and not returning the results in real time. I tried creating a dictionary to store the results and return it at the end, but it still returns empty. I used to be able to do this easily in YOLOv3, not sure what has changed in v4. </p>
<p>Edit: After more testing, I can't even write the results to a file, which is weird. If run from terminal I can. </p>
<p>EDIT: If I var_dump($output), it returns NULL. After turning on debugging, no additional information is returned.</p>
<p>我正在运行脚本 - yolo_video.py</p>
<pre class="brush:php;toolbar:false;"># example usage: python3 yolo_video.py -i video.mp4 -o video_out.avi
import argparse
import glob
import time
import logging
from pathlib import Path
import cv2
import numpy as np
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s-%(name)s-%(message)s")
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input", type=str, default="",
help="video.mp4")
parser.add_argument("-o", "--output", type=str, default="",
help="path to (optional) output video file")
parser.add_argument("-d", "--display", type=int, default=1,
help="display output or not (1/0)")
parser.add_argument("-ht", "--height", type=int, default=1200,
help="height of output")
parser.add_argument("-wt", "--width", type=int, default=700,
help="width of output")
parser.add_argument("-c", "--confidence", type=float, default=0.8,
help="confidence threshold")
parser.add_argument("-t", "--threshold", type=float, default=0.6,
help="non-maximum supression threshold")
args = parser.parse_args()
logger.info("Parsed Arguments")
CONFIDENCE_THRESHOLD = args.confidence
NMS_THRESHOLD = args.threshold
if not Path(args.input).exists():
raise FileNotFoundError("Path to video file is not exist.")
vc = cv2.VideoCapture(args.input)
weights = glob.glob("yolo/*.weights")[0]
labels = glob.glob("yolo/*.txt")[0]
cfg = glob.glob("yolo/*.cfg")[0]
logger.info("Using {} weights ,{} configs and {}labels.".format(weights, cfg, labels))
class_names = list()
with open(labels, "r") as f:
class_names = [cname.strip() for cname in f.readlines()]
COLORS = np.random.randint(0, 255, size=(len(class_names), 3), dtype="uint8")
net = cv2.dnn.readNetFromDarknet(cfg, weights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
layer = net.getLayerNames()
layer = [layer[i[0] - 1] for i in net.getUnconnectedOutLayers()]
writer = None
def detect(frm, net, ln):
(H, W) = frm.shape[:2]
blob = cv2.dnn.blobFromImage(frm, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
start_time = time.time()
layerOutputs = net.forward(ln)
end_time = time.time()
boxes = []
classIds = []
confidences = []
for output in layerOutputs:
for detection in output:
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID]
if confidence > CONFIDENCE_THRESHOLD:
box = detection[0:4] * np.array([W, H, W, H])
(centerX, centerY, width, height) = box.astype("int")
x = int(centerX - (width / 2))
y = int(centerY - (height / 2))
boxes.append([x, y, int(width), int(height)])
classIds.append(classID)
confidences.append(float(confidence))
idxs = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)
if len(idxs) > 0:
for i in idxs.flatten():
(x, y) = (boxes[i][0], boxes[i][1])
(w, h) = (boxes[i][2], boxes[i][3])
color = [int(c) for c in COLORS[classIds[i]]]
cv2.rectangle(frm, (x, y), (x w, y h), color, 2)
text = "{}: {:.4f}".format(class_names[classIds[i]], confidences[i])
# Here I print the results (working in terminal)
print("found")
print(confidences[i])
print(class_names[classIds[i]])
cv2.putText(
frm, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2
)
fps_label = "FPS: %.2f" % (1 / (end_time - start_time))
cv2.putText(
frm, fps_label, (0, 25), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2
)
while cv2.waitKey(1) < 1:
(grabbed, frame) = vc.read()
if not grabbed:
break
frame = cv2.resize(frame, (args.height, args.width))
detect(frame, net, layer)
if writer is not None:
writer.write(frame)</pre>
<p>Then in my PHP script</p>
<pre class="brush:php;toolbar:false;">$command = escapeshellcmd('python3 yolo_video.py -i video.mp4 -o video_out.avi');
$output = shell_exec($command);
echo $output;</pre>
<p>How to output the results of Python script in PHP? I don't get any errors and the script completes. </p>
cv2.waitKey
will not work in general, depending on whether your machine is PHP or jupyter notebook.I tried this on my machine and it solved the problem:
or
The script will stop when the video has finished playing.