Многопроцессорная очередь Python пуста, хотя она заполнена в другом потоке - PullRequest
0 голосов
/ 16 ноября 2018

Я пытался решить эту проблему в течение нескольких часов, но независимо от того, что я делаю, мне так и не удалось это сделать.

Мой проект отслеживает текущие данные и предоставляет конечную точку другим службам для получения самых последних измерений. Но что бы я ни делал, queue.get () всегда ничего не возвращает.

Вот мой код:

from collections import deque
import numpy as np
import argparse
import imutils
import cv2
from flask import Flask
from multiprocessing import Queue
import threading
import Queue as Q

app = Flask(__name__)


class ImageParser(object):
    def dosmth(self, q):
        ap = argparse.ArgumentParser()
        ap.add_argument("-v", "--video", help="path to the (optional) video file")
        ap.add_argument("-b", "--buffer", type=int, default=14, help="max buffer size")
        args = vars(ap.parse_args())

        greenLower = [(86, 61, 128)]
        greenUpper = [(148, 183, 196)]
        pts1 = deque(maxlen=args["buffer"])
        pts2 = deque(maxlen=args["buffer"])

        if not args.get("video", False):
            camera = cv2.VideoCapture(0)

        else:
            camera = cv2.VideoCapture(args["video"])

        while True:
            (grabbed, frame) = camera.read()

            if args.get("video") and not grabbed:
                break

            frame = imutils.resize(frame, width=1200)
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

            for j in range(len(greenLower)):
                upper = greenUpper[j]
                lower = greenLower[j]

                mask = cv2.inRange(hsv, lower, upper)
                mask = cv2.erode(mask, None, iterations=2)
                mask = cv2.dilate(mask, None, iterations=2)

                cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
                                        cv2.CHAIN_APPROX_SIMPLE)[-2]
                for i in range(len(cnts)):
                    center = None

                    if len(cnts) > 0:
                        c = max(cnts, key=cv2.contourArea)

                        ((x, y), radius) = cv2.minEnclosingCircle(c)
                        M = cv2.moments(c)
                        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

                        if radius > 10:
                            q.put(center)
                            cv2.circle(frame, (int(x), int(y)), int(radius),
                                       (0, 255, 255), 2)
                            cv2.circle(frame, center, 5, (0, 0, 255), -1)

                    if j == 0:
                        pts1.appendleft(center)
                        for i in xrange(1, len(pts1)):
                            if pts1[i - 1] is None or pts1[i] is None:
                                continue

                            thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
                            cv2.line(frame, pts1[i - 1], pts1[i], (255,0,0), thickness)

                    if j == 1:
                        pts2.appendleft(center)
                        for i in xrange(1, len(pts2)):
                            if pts2[i - 1] is None or pts2[i] is None:
                               continue

                            thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
                            cv2.line(frame, pts2[i - 1], pts2[i], (51, 153, 255), thickness)

            cv2.imshow("Frame", frame)
            key = cv2.waitKey(1) & 0xFF

            if key == ord("q"):
                break

        camera.release()
        cv2.destroyAllWindows()


imgPar = ImageParser()
q = Queue()
scp = threading.Thread(target=imgPar.dosmth, args=(q,))
scp.start()

def getVal():
    try:
        (x,y) = q.get_nowait()
    except Q.Empty:
        return -1 , -1
    return (x,y)

@app.route('/', methods=['GET'])
def doMain():
    x,y = getVal()
    print x,y
    return '{},{}'.format(x,y)

app.run(debug=True, host='10.21.8.52')

Поскольку у меня действительно нет никакой другой подсказки, что я должен сделать, любая помощь будет оценена.

Все работает на python 2.7.15 в среде анаконды, если это помогает.
Как у меня действительно нет

1 Ответ

0 голосов
/ 16 ноября 2018

Я позволил себе убрать код CV2, так как у меня нет камеры, и заменить заполнитель очереди парой случайных чисел каждые 0,5 секунды, а PEP8 - коднемного, и вот так это работает:

import random
import time

from flask import Flask
import threading
from multiprocessing import Queue
from Queue import Empty as QueueEmpty

app = Flask(__name__)

class ImageParser(object):
    def __init__(self, queue):
        self.queue = queue
        self.source = random.random
        self.pause = 0.5

    def run(self):
        while True:
            value = (self.source(), self.source())
            self.queue.put(value)
            time.sleep(self.pause)

queue = Queue()
image_parser = ImageParser(queue)
image_thread = threading.Thread(target=image_parser.run)

@app.route('/', methods=['GET'])
def do_main():
    try:
        value = queue.get_nowait()
    except QueueEmpty:
        value = None
    print(value)
    return str(value)

if __name__ == '__main__':
    image_thread.start()
    app.run(debug=True, host='127.0.0.1')

Под http://127.0.0.1:5000/ Теперь я получаю пары случайных чисел, и случайный None, когда я перезагружаюсь слишком быстро.

Поэтому я заключаю, чтопроблема, вероятно, заключается в части обработки изображений.В частности, я заметил, что в очередь помещаются только контуры с окружающим радиусом> 10.Возможно, этот путь кода просто никогда не будет выполнен.Вы уверены, что какие-либо значения вообще попадают в очередь?Может быть, print x, y, radius до того, как if radius > 10 прольет немного света.(А зачем ставить center вместо x и y?)

...