Exemple #1
0
    def launch_aligner(self):
        """ Launch the face aligner """
        logger.debug("Launching Aligner")
        kwargs = {"in_queue": self.queues["extract_align_in"],
                  "out_queue": self.queues["extract_align_out"]}

        process = SpawnProcess(self.aligner.run, **kwargs)
        event = process.event
        error = process.error
        process.start()
        self.processes.append(process)

        # Wait for Aligner to take it's VRAM
        # The first ever load of the model for FAN has reportedly taken
        # up to 3-4 minutes, hence high timeout.
        # TODO investigate why this is and fix if possible
        for mins in reversed(range(5)):
            for seconds in range(60):
                event.wait(seconds)
                if event.is_set():
                    break
                if error.is_set():
                    break
            if event.is_set():
                break
            if mins == 0 or error.is_set():
                raise ValueError("Error initializing Aligner")
            logger.info("Waiting for Aligner... Time out in %s minutes", mins)

        logger.debug("Launched Aligner")
Exemple #2
0
    def init_extractor(self, loglevel):
        """ Initialize FAN """
        logger.debug("Initialize Extractor")
        out_queue = queue_manager.get_queue("out")

        d_kwargs = {"in_queue": queue_manager.get_queue("in"),
                    "out_queue": queue_manager.get_queue("align")}
        a_kwargs = {"in_queue": queue_manager.get_queue("align"),
                    "out_queue": out_queue}

        detector = PluginLoader.get_detector("manual")(loglevel=loglevel)
        detect_process = SpawnProcess(detector.run, **d_kwargs)
        d_event = detect_process.event
        detect_process.start()

        for plugin in ("fan", "cv2_dnn"):
            aligner = PluginLoader.get_aligner(plugin)(loglevel=loglevel)
            align_process = SpawnProcess(aligner.run, **a_kwargs)
            a_event = align_process.event
            align_process.start()

            # Wait for Aligner to initialize
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            a_event.wait(300)
            if not a_event.is_set():
                if plugin == "fan":
                    align_process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
                break

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            align_process.join()
            logger.error("Error initializing FAN. Trying CV2-DNN")

        d_event.wait(10)
        if not d_event.is_set():
            raise ValueError("Error inititalizing Detector")

        self.extractor["detect"] = detector
        self.extractor["align"] = aligner
        logger.debug("Initialized Extractor")
Exemple #3
0
    def launch_aligner():
        """ Load the aligner plugin to retrieve landmarks """
        out_queue = queue_manager.get_queue("out")
        kwargs = {"in_queue": queue_manager.get_queue("in"),
                  "out_queue": out_queue}

        for plugin in ("fan", "dlib"):
            aligner = PluginLoader.get_aligner(plugin)()
            process = SpawnProcess(aligner.run, **kwargs)
            event = process.event
            process.start()
            # Wait for Aligner to take init
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            event.wait(300)

            if not event.is_set():
                if plugin == "fan":
                    process.join()
                    logger.error("Error initializing FAN. Trying Dlib")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "dlib":
                return

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            process.join()
            logger.error("Error initializing FAN. Trying Dlib")
Exemple #4
0
    def launch_detector(self):
        """ Launch the face detector """
        out_queue = queue_manager.get_queue("detect")
        kwargs = {
            "in_queue": queue_manager.get_queue("load"),
            "out_queue": out_queue
        }
        if self.args.detector == "mtcnn":
            mtcnn_kwargs = self.detector.validate_kwargs(
                self.get_mtcnn_kwargs())
            kwargs["mtcnn_kwargs"] = mtcnn_kwargs

        if self.detector.parent_is_pool:
            detect_process = PoolProcess(self.detector.detect_faces)
        else:
            detect_process = SpawnProcess()

        event = None
        if hasattr(detect_process, "event"):
            event = detect_process.event

        detect_process.in_process(self.detector.detect_faces, **kwargs)

        if not event:
            return

        event.wait(60)
        if not event.is_set():
            raise ValueError("Error inititalizing Detector")
Exemple #5
0
    def launch_aligner(self):
        """ Load the aligner plugin to retrieve landmarks """
        out_queue = queue_manager.get_queue("out")
        kwargs = {"in_queue": queue_manager.get_queue("in"),
                  "out_queue": out_queue}

        for plugin in ("fan", "cv2_dnn"):
            aligner = PluginLoader.get_aligner(plugin)(loglevel=self.args.loglevel)
            process = SpawnProcess(aligner.run, **kwargs)
            event = process.event
            process.start()
            # Wait for Aligner to take init
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            event.wait(300)

            if not event.is_set():
                if plugin == "fan":
                    process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
                return

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            process.join()
            logger.error("Error initializing FAN. Trying CV2-DNN")
Exemple #6
0
    def launch_aligner(self):
        """ Launch the face aligner """
        logger.debug("Launching Aligner")
        out_queue = queue_manager.get_queue("align")
        kwargs = {
            "in_queue": queue_manager.get_queue("detect"),
            "out_queue": out_queue
        }

        self.process_align = SpawnProcess(self.aligner.run, **kwargs)
        event = self.process_align.event
        self.process_align.start()

        # Wait for Aligner to take it's VRAM
        # The first ever load of the model for FAN has reportedly taken
        # up to 3-4 minutes, hence high timeout.
        # TODO investigate why this is and fix if possible
        event.wait(300)
        if not event.is_set():
            raise ValueError("Error initializing Aligner")

        logger.debug("Launched Aligner")
Exemple #7
0
    def load_extractor(self):
        """ Set on the fly extraction """
        logger.warning("No Alignments file found. Extracting on the fly.")
        logger.warning(
            "NB: This will use the inferior dlib-hog for extraction "
            "and dlib pose predictor for landmarks. It is recommended "
            "to perfom Extract first for superior results")
        for task in ("load", "detect", "align"):
            queue_manager.add_queue(task, maxsize=0)

        detector = PluginLoader.get_detector("dlib_hog")(
            loglevel=self.args.loglevel)
        aligner = PluginLoader.get_aligner("dlib")(loglevel=self.args.loglevel)

        d_kwargs = {
            "in_queue": queue_manager.get_queue("load"),
            "out_queue": queue_manager.get_queue("detect")
        }
        a_kwargs = {
            "in_queue": queue_manager.get_queue("detect"),
            "out_queue": queue_manager.get_queue("align")
        }

        d_process = SpawnProcess(detector.run, **d_kwargs)
        d_event = d_process.event
        d_process.start()

        a_process = SpawnProcess(aligner.run, **a_kwargs)
        a_event = a_process.event
        a_process.start()

        d_event.wait(10)
        if not d_event.is_set():
            raise ValueError("Error inititalizing Detector")
        a_event.wait(10)
        if not a_event.is_set():
            raise ValueError("Error inititalizing Aligner")

        self.extract_faces = True
Exemple #8
0
        self.sort_process()

    def launch_aligner(self):
        """ Load the aligner plugin to retrieve landmarks """
        out_queue = queue_manager.get_queue("out")
        kwargs = {"in_queue": queue_manager.get_queue("in"),
                  "out_queue": out_queue}

<<<<<<< HEAD
        for plugin in ("fan", "dlib"):
=======
        for plugin in ("fan", "cv2_dnn"):
>>>>>>> upstream/master
            aligner = PluginLoader.get_aligner(plugin)(loglevel=self.args.loglevel)
            process = SpawnProcess(aligner.run, **kwargs)
            event = process.event
            process.start()
            # Wait for Aligner to take init
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            event.wait(300)

            if not event.is_set():
                if plugin == "fan":
                    process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
Exemple #9
0
class Plugins():
    """ Detector and Aligner Plugins and queues """
    def __init__(self, arguments):
        self.args = arguments
        self.detector = self.load_detector()
        self.aligner = self.load_aligner()
        self.is_parallel = self.set_parallel_processing()

        self.process_detect = None
        self.process_align = None
        self.add_queues()

    def set_parallel_processing(self):
        """ Set whether to run detect and align together or seperately """
        detector_vram = self.detector.vram
        aligner_vram = self.aligner.vram
        gpu_stats = GPUStats()
        if (detector_vram == 0
                or aligner_vram == 0
                or gpu_stats.device_count == 0):
            return True

        if hasattr(self.args, "multiprocess") and not self.args.multiprocess:
            print("\nNB: Parallel processing disabled.\nYou may get faster "
                  "extraction speeds by enabling it with the -mp switch\n")
            return False

        required_vram = detector_vram + aligner_vram + 320  # 320MB buffer
        stats = gpu_stats.get_card_most_free()
        free_vram = int(stats["free"])
        if self.args.verbose:
            print("{} - {}MB free of {}MB".format(stats["device"],
                                                  free_vram,
                                                  int(stats["total"])))
        if free_vram <= required_vram:
            if self.args.verbose:
                print("Not enough free VRAM for parallel processing. "
                      "Switching to serial")
            return False
        return True

    def add_queues(self):
        """ Add the required processing queues to Queue Manager """
        for task in ("load", "detect", "align", "save"):
            size = 0
            if task == "load" or (not self.is_parallel and task == "detect"):
                size = 100
            queue_manager.add_queue(task, maxsize=size)

    def load_detector(self):
        """ Set global arguments and load detector plugin """
        detector_name = self.args.detector.replace("-", "_").lower()

        # Rotation
        rotation = None
        if hasattr(self.args, "rotate_images"):
            rotation = self.args.rotate_images

        detector = PluginLoader.get_detector(detector_name)(
            verbose=self.args.verbose,
            rotation=rotation)

        return detector

    def load_aligner(self):
        """ Set global arguments and load aligner plugin """
        aligner_name = self.args.aligner.replace("-", "_").lower()

        aligner = PluginLoader.get_aligner(aligner_name)(
            verbose=self.args.verbose)

        return aligner

    def launch_aligner(self):
        """ Launch the face aligner """
        out_queue = queue_manager.get_queue("align")
        kwargs = {"in_queue": queue_manager.get_queue("detect"),
                  "out_queue": out_queue}

        self.process_align = SpawnProcess()
        event = self.process_align.event

        self.process_align.in_process(self.aligner.align, **kwargs)

        # Wait for Aligner to take it's VRAM
        # The first ever load of the model for FAN has reportedly taken
        # up to 3-4 minutes, hence high timeout.
        # TODO investigate why this is and fix if possible
        event.wait(300)
        if not event.is_set():
            raise ValueError("Error inititalizing Aligner")

        try:
            err = None
            err = out_queue.get(True, 1)
        except QueueEmpty:
            pass

        if err:
            if isinstance(err, str):
                queue_manager.terminate_queues()
                print(err)
                exit(1)
            else:
                queue_manager.get_queue("detect").put(err)

    def launch_detector(self):
        """ Launch the face detector """
        out_queue = queue_manager.get_queue("detect")
        kwargs = {"in_queue": queue_manager.get_queue("load"),
                  "out_queue": out_queue}

        if self.args.detector == "mtcnn":
            mtcnn_kwargs = self.detector.validate_kwargs(
                self.get_mtcnn_kwargs())
            kwargs["mtcnn_kwargs"] = mtcnn_kwargs

        if self.detector.parent_is_pool:
            self.process_detect = PoolProcess(self.detector.detect_faces)
        else:
            self.process_detect = SpawnProcess()

        event = None
        if hasattr(self.process_detect, "event"):
            event = self.process_detect.event

        self.process_detect.in_process(self.detector.detect_faces, **kwargs)

        if not event:
            return

        event.wait(60)
        if not event.is_set():
            raise ValueError("Error inititalizing Detector")

    def get_mtcnn_kwargs(self):
        """ Add the mtcnn arguments into a kwargs dictionary """
        mtcnn_threshold = [float(thr.strip())
                           for thr in self.args.mtcnn_threshold]
        return {"minsize": self.args.mtcnn_minsize,
                "threshold": mtcnn_threshold,
                "factor": self.args.mtcnn_scalefactor}

    def detect_faces(self, extract_pass="******"):
        """ Detect faces from in an image """
        if self.is_parallel or extract_pass == "align":
            out_queue = queue_manager.get_queue("align")
        if not self.is_parallel and extract_pass == "detect":
            out_queue = queue_manager.get_queue("detect")

        while True:
            try:
                faces = out_queue.get(True, 1)
                if faces == "EOF":
                    break
                exception = faces.get("exception", None)
                if exception is not None:
                    queue_manager.terminate_queues()
                    yield faces
                    break
            except QueueEmpty:
                continue

            yield faces
Exemple #10
0
class Plugins():
    """ Detector and Aligner Plugins and queues """
    def __init__(self, arguments):
        logger.debug("Initializing %s", self.__class__.__name__)
        self.args = arguments
        self.detector = self.load_detector()
        self.aligner = self.load_aligner()
        self.is_parallel = self.set_parallel_processing()

        self.process_detect = None
        self.process_align = None
        self.add_queues()
        logger.debug("Initialized %s", self.__class__.__name__)

    def set_parallel_processing(self):
        """ Set whether to run detect and align together or separately """
        detector_vram = self.detector.vram
        aligner_vram = self.aligner.vram
        gpu_stats = GPUStats()
        if (detector_vram == 0 or aligner_vram == 0
                or gpu_stats.device_count == 0):
            logger.debug(
                "At least one of aligner or detector have no VRAM requirement. "
                "Enabling parallel processing.")
            return True

        if hasattr(self.args, "multiprocess") and not self.args.multiprocess:
            logger.info("NB: Parallel processing disabled.You may get faster "
                        "extraction speeds by enabling it with the -mp switch")
            return False

        required_vram = detector_vram + aligner_vram + 320  # 320MB buffer
        stats = gpu_stats.get_card_most_free()
        free_vram = int(stats["free"])
        logger.verbose("%s - %sMB free of %sMB", stats["device"], free_vram,
                       int(stats["total"]))
        if free_vram <= required_vram:
            logger.warning("Not enough free VRAM for parallel processing. "
                           "Switching to serial")
            return False
        return True

    def add_queues(self):
        """ Add the required processing queues to Queue Manager """
        for task in ("load", "detect", "align", "save"):
            size = 0
            if task == "load" or (not self.is_parallel and task == "detect"):
                size = 100
            queue_manager.add_queue(task, maxsize=size)

    def load_detector(self):
        """ Set global arguments and load detector plugin """
        detector_name = self.args.detector.replace("-", "_").lower()
        logger.debug("Loading Detector: '%s'", detector_name)
        # Rotation
        rotation = None
        if hasattr(self.args, "rotate_images"):
            rotation = self.args.rotate_images

        detector = PluginLoader.get_detector(detector_name)(
            loglevel=self.args.loglevel, rotation=rotation)

        return detector

    def load_aligner(self):
        """ Set global arguments and load aligner plugin """
        aligner_name = self.args.aligner.replace("-", "_").lower()
        logger.debug("Loading Aligner: '%s'", aligner_name)

        aligner = PluginLoader.get_aligner(aligner_name)(
            loglevel=self.args.loglevel)

        return aligner

    def launch_aligner(self):
        """ Launch the face aligner """
        logger.debug("Launching Aligner")
        out_queue = queue_manager.get_queue("align")
        kwargs = {
            "in_queue": queue_manager.get_queue("detect"),
            "out_queue": out_queue
        }

        self.process_align = SpawnProcess(self.aligner.run, **kwargs)
        event = self.process_align.event
        self.process_align.start()

        # Wait for Aligner to take it's VRAM
        # The first ever load of the model for FAN has reportedly taken
        # up to 3-4 minutes, hence high timeout.
        # TODO investigate why this is and fix if possible
        for mins in reversed(range(5)):
            event.wait(60)
            if event.is_set():
                break
            if mins == 0:
                raise ValueError("Error initializing Aligner")
            logger.info("Waiting for Aligner... Time out in %s minutes", mins)

        logger.debug("Launched Aligner")

    def launch_detector(self):
        """ Launch the face detector """
        logger.debug("Launching Detector")
        out_queue = queue_manager.get_queue("detect")
        kwargs = {
            "in_queue": queue_manager.get_queue("load"),
            "out_queue": out_queue
        }

        mp_func = PoolProcess if self.detector.parent_is_pool else SpawnProcess
        self.process_detect = mp_func(self.detector.run, **kwargs)

        event = None
        if hasattr(self.process_detect, "event"):
            event = self.process_detect.event

        self.process_detect.start()

        if event is None:
            logger.debug("Launched Detector")
            return

        for mins in reversed(range(5)):
            event.wait(60)
            if event.is_set():
                break
            if mins == 0:
                raise ValueError("Error initializing Detector")
            logger.info("Waiting for Detector... Time out in %s minutes", mins)

        logger.debug("Launched Detector")

    def detect_faces(self, extract_pass="******"):
        """ Detect faces from in an image """
        logger.debug("Running Detection. Pass: '******'", extract_pass)
        if self.is_parallel or extract_pass == "align":
            out_queue = queue_manager.get_queue("align")
        if not self.is_parallel and extract_pass == "detect":
            out_queue = queue_manager.get_queue("detect")

        while True:
            try:
                faces = out_queue.get(True, 1)
                if faces == "EOF":
                    break
                if isinstance(faces, dict) and faces.get("exception"):
                    pid = faces["exception"][0]
                    t_back = faces["exception"][1].getvalue()
                    err = "Error in child process {}. {}".format(pid, t_back)
                    raise Exception(err)
            except QueueEmpty:
                continue

            yield faces
        logger.debug("Detection Complete")
Exemple #11
0
    def init_extractor(self, loglevel):
        """ Initialize FAN """
        logger.debug("Initialize Extractor")
        out_queue = queue_manager.get_queue("out")

        d_kwargs = {
            "in_queue": queue_manager.get_queue("in"),
            "out_queue": queue_manager.get_queue("align")
        }
        a_kwargs = {
            "in_queue": queue_manager.get_queue("align"),
            "out_queue": out_queue
        }

        detector = PluginLoader.get_detector("manual")(loglevel=loglevel)
        detect_process = SpawnProcess(detector.run, **d_kwargs)
        d_event = detect_process.event
        detect_process.start()

        for plugin in ("fan", "cv2_dnn"):
            aligner = PluginLoader.get_aligner(plugin)(loglevel=loglevel)
            align_process = SpawnProcess(aligner.run, **a_kwargs)
            a_event = align_process.event
            align_process.start()

            # Wait for Aligner to initialize
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            a_event.wait(300)
            if not a_event.is_set():
                if plugin == "fan":
                    align_process.join()
                    logger.error("Error initializing FAN. Trying CV2-DNN")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "cv2_dnn":
                break

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            align_process.join()
            logger.error("Error initializing FAN. Trying CV2-DNN")

        d_event.wait(10)
        if not d_event.is_set():
            raise ValueError("Error inititalizing Detector")

        self.extractor["detect"] = detector
        self.extractor["align"] = aligner
        logger.debug("Initialized Extractor")
Exemple #12
0
    def init_extractor(self, verbose):
        """ Initialize FAN """
        in_queue = queue_manager.get_queue("in")
        align_queue = queue_manager.get_queue("align")
        out_queue = queue_manager.get_queue("out")

        d_kwargs = {"in_queue": in_queue, "out_queue": align_queue}
        a_kwargs = {"in_queue": align_queue, "out_queue": out_queue}
        detect_process = SpawnProcess()
        align_process = SpawnProcess()
        d_event = detect_process.event
        a_event = align_process.event

        detector = PluginLoader.get_detector("manual")(verbose=verbose)
        detect_process.in_process(detector.detect_faces, **d_kwargs)

        for plugin in ("fan", "dlib"):
            aligner = PluginLoader.get_aligner(plugin)(verbose=verbose)
            align_process.in_process(aligner.align, **a_kwargs)

            # Wait for Aligner to take init
            # The first ever load of the model for FAN has reportedly taken
            # up to 3-4 minutes, hence high timeout.
            a_event.wait(300)
            if not a_event.is_set():
                if plugin == "fan":
                    align_process.join()
                    print("Error initializing FAN. Trying Dlib")
                    continue
                else:
                    raise ValueError("Error inititalizing Aligner")
            if plugin == "dlib":
                break

            try:
                err = None
                err = out_queue.get(True, 1)
            except QueueEmpty:
                pass
            if not err:
                break
            align_process.join()
            print("Error initializing FAN. Trying Dlib")

        d_event.wait(10)
        if not d_event.is_set():
            raise ValueError("Error inititalizing Detector")

        self.extractor["detect"] = detector
        self.extractor["align"] = aligner