def test_one_photo_facedetect(self):
     # for photo in self.photos_list:
     for photo in self.photos_list[1:]:
         print(photo)
         photo, filename = self.__image_preprocess__(photo)
         _, ml_faces, tagged_faces, elapsed = face_extraction.extract_faces_from_image(
             photo, self.parameters)
         if len(ml_faces) > 0:
             break
     # Assert that we at least are getting one image
     # with a detected face.
     self.assertTrue(len(ml_faces) > 0)
    def test_extract_and_group_faces(self, redo=False):

        # for photo in self.photos_list:
        problems = [41, 65, 77, 79, 80, 83, 96, 100, 151]

        all_matches = []
        for p in range(len(self.photos_list)):
            # for p in problems:
            photo = self.photos_list[p]
            photo, filename = self.__image_preprocess__(photo)

            print(p, filename)
            out_file = re.sub('.(jpg|JPEG|JPG|jpeg)$', '.pkl', filename)
            if not os.path.isfile(out_file) or redo:
                _, ml_faces, tagged_faces, elapsed = face_extraction.extract_faces_from_image(
                    photo, self.parameters)
                assert ml_faces is not None
                assert tagged_faces is not None
                with open(out_file, 'wb') as fh:
                    pickle.dump([ml_faces, tagged_faces], fh)
            else:
                with open(out_file, 'rb') as fh:
                    ml_faces, tagged_faces = pickle.load(fh)

            test_bigface = False
            num_faces_file = re.sub('.(jpg|JPEG|JPG|jpeg)$', '_numface.pkl',
                                    filename)
            matched = face_extraction.associate_detections_and_tags(
                photo,
                ml_faces,
                tagged_faces,
                disp_photo=False,
                test=test_bigface)

            if test_bigface:
                pass
            else:

                if not os.path.isfile(num_faces_file):
                    with open(num_faces_file, 'wb') as fh:
                        pickle.dump([len(matched)], fh)
                else:
                    with open(num_faces_file, 'rb') as fh:
                        expected_num_faces = pickle.load(fh)[0]
                        # print(len(matched), expected_num_faces)
                        assert expected_num_faces == len(matched)
Beispiel #3
0
def face_extract_client(filename, server_ip_finder, logger=None):

    if logger is None:
        logger = logging.getLogger('__main__')
        logger.setLevel(logging.DEBUG)

        ch = logging.StreamHandler()
        ch.setLevel(logging.DEBUG)
        logger.addHandler(ch)
        coloredlogs.install()

    server_there = server_ip_finder.check_ip()
    if server_there:
        ext_ip = server_ip_finder.server_ip
    else:
        server_ip_finder.find_external_server()
        ext_ip = None

    with open(os.path.join(PARENT_DIR, 'parameters.xml')) as p:
        config = xmltodict.parse(p.read())
    port_image_handle = int(
        config['params']['ports']['server_port_image_handle'])
    port_ip_disc = int(config['params']['ports']['server_port_ip_disc'])
    connect_timeout = int(config['params']['timeout']['connect_timeout'])
    read_timeout = int(config['params']['timeout']['read_timeout'])

    # Get orientation data

    process_local = True
    if not ext_ip:
        logger.error(
            'GPU server not available to extract faces from {}'.format(
                filename))
        process_local = True
    else:
        payload, headers = image_for_network(filename)
        addr = f'http://{ext_ip}:{port_image_handle}'
        alive_url = addr + '/api/alive'
        logger.debug("Alive url is {}".format(alive_url))
        try:
            # Since 'alive' expects no payload, it will throw
            # an error if it receives one. So this is proper.
            response = requests.get(alive_url,
                                    timeout=(connect_timeout, read_timeout))
            # decode response
            retval = json.loads(response.text)
            if not retval['server_supports_cuda']:
                logger.error(
                    "Server does not support CUDA: processing locally.")
            if response.status_code == 200:
                process_local = not retval['server_supports_cuda']

        except requests.exceptions.ConnectionError as ce:
            print(ce)
            logger.error("Connection error for API -- will process locally")
            process_local = True

    if process_local:
        logger.warning("Processing locally!")
        if not dlib.DLIB_USE_CUDA:
            raise IOError("No GPU available")
        else:
            matched_faces, _, _, elapsed_time = face_extraction.extract_faces_from_image(
                filename, config)
    else:
        addr = f'http://{ext_ip}:{port_image_handle}'
        face_extract_url = addr + '/api/face_extract'
        logger.debug("Using GPU, address is {}".format(face_extract_url))

        # send http request with image and receive response
        try:
            response = requests.post(face_extract_url,
                                     data=payload,
                                     headers=headers,
                                     timeout=(connect_timeout, read_timeout))
            # decode response
            try:
                retval = json.loads(response.text)
            except json.decoder.JSONDecodeError as jde:
                if '500 Internal Server Error' in response.text:
                    logger.critical(
                        "Your server face extract code is broken! It broke on filename {}"
                        .format(filename))
                    raise IOError(
                        f'Your server face extract code is broken. Fix it! It broke on filename {filename}. \nError text: {response.text}'
                    )
                else:
                    print(
                        f"File is: {filename}. Text response is : {response.text[:300]}"
                    )
                    print(jde)
                    # raise(jde)
                    return
            # retval = json.loads(response.text)
            elapsed_time = retval['elapsed_time']

            if not retval['success']:
                print("No success: ", retval['message'])
            else:
                matched_faces = json.loads(retval['xmp_data'],
                                           object_hook=decode_object)

            logger.debug(
                'GPU server **was** used to extract faces from {}'.format(
                    filename))

        except requests.exceptions.ConnectionError as ce:
            print(ce)
            logger.error('GPU server could not connect in face extraction.')
            if not dlib.DLIB_USE_CUDA:
                raise ce
            else:
                matched_faces, _, _, elapsed_time = face_extraction.extract_faces_from_image(
                    filename, config)
        except requests.exceptions.ReadTimeout as ce:
            logger.error('GPU server timed out when face extracting {}'.format(
                filename))
            if not dlib.DLIB_USE_CUDA:
                raise ce
            else:
                matched_faces, _, _, elapsed_time = face_extraction.extract_faces_from_image(
                    filename, config)

    logger.debug('Elapsed time to extract faces from {} was {}'.format(
        filename, elapsed_time))

    for face_num in range(len(matched_faces)):
        # matched_faces[face_num].reconstruct_square_face(filename)
        matched_faces[face_num].reconstruct_nonrect_face(filename)

    return matched_faces
Beispiel #4
0
def face_extract():
    r = request

    # print(session)
    # if 'starttime' in session:
    #     old_start = session['starttime']
    #     print(f"Elapsed since last session is {time.time() - old_start}")
    # session['starttime'] = time.time()
    # print(session['starttime'])

    if not request.content_type == 'text':
        raise ValueError("Posted data must be text.")

    # Load the dict from the request. It should have a base64_file and
    # a checksum field.
    data = json.loads(r.data)
    file_data = data['base64_file']
    # Convert the string to bytes. We know that the string
    # is a base64 string encoded using utf-8.
    file_data = file_data.encode('utf-8')
    # Get the hex checksum from the payload
    checksum_data = data['checksum']

    # Compute the md5 checksum of the binary string. It should
    # match that of the checksum payload.
    loc_checksum = hashlib.md5(file_data)
    loc_checksum = loc_checksum.hexdigest()

    # If checksums don't match, send information back to client.
    if checksum_data != loc_checksum:
        response = {
            'success': False,
            'message': 'Bad image -- does not match the checksum.'
        }

        # # encode response using jsonpickle
        response_pickled = jsonpickle.encode(response)
        return Response(response=response_pickled,
                        status=200,
                        mimetype="application/json")

    # Shove that file data into a BytesIO object that can
    # be read using PIL. The key to getting string data back
    # from this IO object is to use getvalue, not read.

    dt = base64.b64decode(file_data)

    # Retrieve the XMP faces.
    file = io.BytesIO(dt)
    success, xmp_data = face_extraction.Get_XMP_Faces(file)
    assert success, 'XMP extraction failed'

    parameter_file = os.path.join(PARENT_DIR, 'parameters.xml')
    with open(parameter_file, 'r') as fh:
        parameters = xmltodict.parse(fh.read())

    print("extracting")
    matched_faces, _, _, elapsed_time = face_extraction.extract_faces_from_image(
        file, parameters, xmp_data)

    for idx in range(len(matched_faces)):
        encoding = matched_faces[idx].encoding
        if encoding is not None:
            matched_faces[idx].encoding = encoding.tolist()
        mm = matched_faces[idx]
        # image = matched_faces[idx].face_image_nonrect
        # if image is not None: # Shouldn't happen any other way...
        #     matched_faces[idx].image = image.tolist()
        #     logging.debug("Reg image OK")
        # else:
        #     logging.error("Your face extractor returned no image. This shouldn't happen.")
        #     return
        matched_faces[idx].face_image_nonrect = None

        # square_face = matched_faces[idx].square_face
        # if square_face is not None:
        #     logging.debug("Squre image OK")
        #     matched_faces[idx].square_face = square_face.tolist()
        # else:
        #     logging.error("Your face extractor returned no square image. This shouldn't happen.")
        #     return
        matched_faces[idx].square_face = None

    enc = (json.dumps(matched_faces, cls=CustomEncoder))

    # # build a response dict to send back to client
    response = {'success': True, 'message': 'image received and processed', \
                'xmp_data': enc, 'elapsed_time': elapsed_time }

    # # encode response using jsonpickle
    response_pickled = jsonpickle.encode(response)

    return Response(response=response_pickled,
                    status=200,
                    mimetype="application/json")