Récemment, j'ai découvert une bibliothèque appelée trio.
[Modèle de codage asynchrone Python + Trio] (https://qiita.com/yura/items/689d065aba00fe14fbba)
Veuillez vous référer au.
Si vous écrivez un programme de traitement d'image / reconnaissance d'image, vous voudrez charger l'image suivante pendant le traitement d'image / temps de reconnaissance. J'ai donc décidé d'écrire un programme multi-thread en Python.
J'ai écrit une version de traitement séquentiel comme décrit plus tard. Je souhaite charger l'image suivante pendant ce processus de détection. Pour le fonctionnement, préparez une image d'entrée pour détecter les personnes, pat = r"*.png " Veuillez réécrire la partie de.
Version de traitement séquentiel
detectLoop.py
# -*- coding: utf-8 -*-
# pylint: disable-msg=C0103
import glob
import cv2
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
def detect(img):
found = hog.detectMultiScale(img, winStride=(8, 8), padding=(32, 32), scale=1.05)
return found
def draw_detections(img, rects, thickness=1):
for x, y, w, h in rects:
# the HOG detector returns slightly larger rectangles than the real objects.
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.05*h)
cv2.rectangle(img, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)
if __name__ == '__main__':
pat = r"*.png "
names = glob.glob(pat)[:100]
e1 = cv2.getTickCount()
imgname = names[0]
img = cv2.imread(imgname)
for i in range(1, len(names), 1):
found, scores = detect(img)
imgnameNext = names[i]
imgNext = cv2.imread(imgnameNext)
if 0:
print i, imgnameNext, imgNext.shape
print found
oldImg, imgname, img = img, imgnameNext, imgNext
draw_detections(oldImg, found)
cv2.imshow("detected", oldImg)
cv2.waitKey(1)
e2 = cv2.getTickCount()
timeDiff = (e2 - e1)/ cv2.getTickFrequency()
print timeDiff
"Il existe deux manières de gérer les threads dans le module de threading. Créez une sous-classe de threading.Thread. Créez une instance de threading.Thread. " Cependant, choisissons une méthode pour créer directement une instance.
Tout d'abord, examinons un exemple de traitement multi-thread qui ne renvoie pas de résultat à partir d'une fonction.
Ensuite, il est devenu clair que la partie suivante était le point principal.
\ # Créez une instance du thread. t = threading.Thread (cible = fonction, args = tapple d'arguments de fonction) t.start() Autre traitement t.join()
Dans cet exemple, le résultat de la fonction ne peut pas être retourné, donc pour renvoyer le résultat entre les threads, Queue est utilisé pour transmettre des données entre les threads.
nom de la fonction def(queue,argument):
Traitement des fonctions
queue.put(Valeur de retour)
t = threading.Thread(target=Nom de la fonction, args=(queue,argument))
t.start()
#Ecrire le processus
t.join()
Valeur de retour de la fonction= queue.get()
Il existe deux façons de décider d'appeler l'image ou de détecter la personne dans un fil distinct. Ici, j'ai essayé de faire du processus de détection de personne un fil distinct. En écrivant comme ceci, en chargeant l'image suivante et en traitant l'image chargée Il semble qu'il puisse fonctionner en parallèle.
Version multithread
detectLoop_thread.py
# -*- coding: utf-8 -*-
# pylint: disable-msg=C0103
import threading
import Queue
import glob
import cv2
global hog
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
def detect2(queue, img):
global hog
found = hog.detectMultiScale(img, winStride=(8, 8), padding=(32, 32), scale=1.05)
queue.put(found)
def draw_detections(img, rects, thickness=1):
for x, y, w, h in rects:
# the HOG detector returns slightly larger rectangles than the real objects.
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.05*h)
cv2.rectangle(img, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)
if __name__ == '__main__':
pat = r"*.png "
names = glob.glob(pat)[:100]
e1 = cv2.getTickCount()
queue = Queue.Queue()
imgname = names[0]
img = cv2.imread(imgname)
for i in range(1, len(names), 1):
t = threading.Thread(target=detect2, args=(queue, img, ))
t.start()
imgnameNext = names[i]
imgNext = cv2.imread(imgnameNext)
t.join()
found, scores = queue.get()
if 0:
print i, imgnameNext, imgNext.shape
print found
oldImg, imgname, img = img, imgNext, imgNext
draw_detections(oldImg, found)
cv2.imshow("detected", oldImg)
cv2.waitKey(1)
e2 = cv2.getTickCount()
timeDiff = (e2 - e1)/ cv2.getTickFrequency()
print timeDiff
Quant au résultat de l'opération, le temps de traitement est réduit d'environ 0,8 seconde lors de la lecture de 100 fichiers png. (Dans l'exemple, on peut voir qu'il est nécessaire de réduire le temps nécessaire au processus de détection de personne lui-même.)
Version de traitement séquentiel secondes 29.5429292224 Version multithread de secondes 28.7976980869
detectLoop_thread2.py
# -*- coding: utf-8 -*-
# pylint: disable-msg=C0103
import threading
import Queue
import glob
import cv2
global hog
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
def imread2(queue, imgnameNext):
imgNext = cv2.imread(imgnameNext)
queue.put(imgNext)
def draw_detections(img, rects, thickness=1):
for x, y, w, h in rects:
# the HOG detector returns slightly larger rectangles than the real objects.
# so we slightly shrink the rectangles to get a nicer output.
pad_w, pad_h = int(0.15*w), int(0.05*h)
cv2.rectangle(img, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)
if __name__ == '__main__':
pat = r"*.png "
names = glob.glob(pat)[:100]
e1 = cv2.getTickCount()
queue = Queue.Queue()
imgname = names[0]
img = cv2.imread(imgname)
for i in range(1, len(names), 1):
imgnameNext = names[i]
t = threading.Thread(target=imread2, args=(queue, imgnameNext, ))
t.start()
found, scores = hog.detectMultiScale(img, winStride=(8, 8), padding=(32, 32), scale=1.05)
t.join()
imgNext = queue.get()
if 0:
print i, imgnameNext, imgNext.shape
print found
oldImg, imgname, img = img, imgNext, imgNext
draw_detections(oldImg, found)
cv2.imshow("detected", oldImg)
cv2.waitKey(1)
e2 = cv2.getTickCount()
timeDiff = (e2 - e1)/ cv2.getTickFrequency()
print timeDiff
Post-scriptum: Ce que j'ai pensé récemment. Il est possible que l'image soit lue et détectée dans chaque thread. Si cette méthode peut être utilisée, il devrait être possible de paralléliser des images avec un travail uniformément réparti plutôt que de les paralléliser avec des temps de calcul complètement différents pour le chargement et la détection des images.
http://docs.python.jp/2/library/multiprocessing.html
16.2 Filetage - interface de filetage de haut niveau http://docs.python.jp/2/library/threading.html
Essayez un fil Python (2) http://bty.sakura.ne.jp/wp/archives/69
Traitement multithread avec Python http://qiita.com/konnyakmannan/items/2f0e3f00137db10f56a7
Article associé Essayez de charger l'image dans un thread séparé (version C ++) http://qiita.com/nonbiri15/items/016bb38eb42a219e98e2
Remarque: J'ai entendu dire qu'il existe une bibliothèque appelée TRIO et que vous devriez l'utiliser.
https://trio.readthedocs.io/en/latest/#
Recommended Posts