def downloader(fec_df):
    faces_df = load_faces_df()
    downloaded_imgs = {}
    for index, row in fec_df.iterrows():
        if index % SAVE_PROGRESS_INTERVAL == 0:
            save_downloaded_images(downloaded_imgs)
            downloaded_imgs = {}
            faces_df.to_csv("{}/{}.csv".format(SAVED_DF_PATH, SAVED_DF_NAME),
                            index=False)
            print("Progress is saved: ", index)
        for col in range(0, 15, 5):
            url = row[col]
            x1, x2, y1, y2 = float(row[col + 1]), float(row[col + 2]), float(
                row[col + 3]), float(row[col + 4])
            if url not in faces_df["url"].values:
                try:
                    img = Image.open(urllib.request.urlopen(url))
                    cv_img = np.array(img)
                    shape = cv_img.shape
                    x1, x2 = int(shape[1] * x1), int(shape[1] * x2)
                    y1, y2 = int(shape[0] * y1), int(shape[0] * y2)
                    annotated_face = cv_img[y1:y2, x1:x2]

                    face_id = uuid4()
                    [face_coords] = crop_faces([annotated_face])
                    if face_coords is not None:
                        # if a face is found by opencv, save the cropped face.
                        (x, y, w, h) = face_coords
                        face = crop_cv_img(annotated_face, x, y, w, h)
                        downloaded_imgs[face_id] = face
                        faces_df = add_img_to_faces_df(faces_df, face_id, url,
                                                       True)
                    else:
                        # if no face is found by opencv,
                        # save the face as specified by the boundaries in the dataset.
                        faces_df = add_img_to_faces_df(faces_df, face_id, url,
                                                       False)
                        downloaded_imgs[face_id] = annotated_face
                except urllib.error.HTTPError:
                    faces_df = add_img_to_faces_df(faces_df, uuid4(), url,
                                                   False)
                except Exception:
                    _, error, tb = sys.exc_info()
                    print("UNEXPECTED ERROR:", error)
                    traceback.print_tb(tb)
                    faces_df = add_img_to_faces_df(faces_df, uuid4(), url,
                                                   False)

    faces_df.to_csv("{}/{}.csv".format(SAVED_DF_PATH, SAVED_DF_NAME),
                    index=False)
def test_on_folder():
    images = []
    # r=root, d=directories, f = files
    for r, d, f in os.walk(config["path_images"]):
        for file in f:
            if any(extension in file
                   for extension in ['.jpeg', '.jpg', '.png']):
                images.append(os.path.join(r, file))

    results_df = pd.DataFrame()

    IMG_TO_TEST = 30
    i = 0

    for path in images:
        if i >= IMG_TO_TEST:
            break
        i += 1
        print("Processing {}".format(path))
        image = pl.Image.open(path)
        image = resize_input_image(image)
        cv_img = np.array(image)
        [face_coords] = crop_faces([cv_img])
        if face_coords is not None:
            print("Face found on image.")
            (x, y, w, h) = face_coords
            face_image = crop_cv_img(cv_img, x, y, w, h)
            pil_face_image = pl.Image.fromarray(face_image).resize(
                config["resolution"])
            pil_face_image = pre_process(pil_face_image).unsqueeze(0)

            model = load_model()
            results = model.predict_single(pil_face_image)
            results_dict = {
                cat: results[i]
                for i, cat in enumerate(config["catslist"])
            }
            results_dict["path"] = path
            results_df = results_df.append(results_dict, ignore_index=True)

    results_df.to_csv("predictions.csv", index=False)
def test_on_annotated_csv(annotations_csv_path, model_type="CustomVGG"):
    start_time = time()
    # add column "pixels" to annotated csv (same format as FER csv)
    print("Loading annotations...")
    df = pd.read_csv(annotations_csv_path)
    pixels = []
    imgs_with_detected_face = 0

    for i, path in enumerate(df["path"].values):
        if i % 20 == 0:
            print(i)

        image = np.array(pl.Image.open(path))

        cv_img = np.array(image)
        [face_coords] = crop_faces([cv_img])
        if face_coords is not None:
            imgs_with_detected_face += 1
            (x, y, w, h) = face_coords
            face_image = crop_cv_img(cv_img, x, y, w, h)
            pil_face_image = pl.Image.fromarray(face_image).resize(
                config["resolution"])
            pil_face_image = transforms.Grayscale(
                num_output_channels=1)(pil_face_image)

            pixels_list = np.array(pil_face_image).flatten().tolist()

            pixels.append(" ".join(map(str, pixels_list)))
        else:
            df.drop(index=i, inplace=True)
    df[config["data_column"]] = pixels
    df.reset_index(inplace=True)

    print("Loaded annotations in {}s".format(round(time() - start_time, 2)))
    start_time = time()
    # load model and evaluate it
    print("Loading model...")
    model = load_model(model_type=model_type)

    print("Evaluating model...")

    def preprocess_batch(pixelstring_batch, emotions_batch, DEVICE):
        if model_type == "CustomVGG":
            return preprocess_batch_custom_vgg(pixelstring_batch,
                                               emotions_batch, DEVICE, False,
                                               config["loss_mode"])
        elif model_type == "DenseSIFTHybrid":
            return preprocess_batch_dense_sift_hybrid(pixelstring_batch,
                                                      emotions_batch, DEVICE,
                                                      False,
                                                      config["loss_mode"])
        elif model_type == "SIFTHybrid":
            return preprocess_batch_sift_hybrid(pixelstring_batch,
                                                emotions_batch, DEVICE, False,
                                                config["loss_mode"])

    use_descriptors = (model_type == "DenseSIFTHybrid"
                       or model_type == "SIFTHybrid")
    # we don't care about the test loss value here
    dummy_weights = torch.FloatTensor([1] * len(config["catslist"])).to(DEVICE)
    proba, _, acc, cm1, cm2, acc_fact = evaluate(
        model,
        df,
        preprocess_batch,
        dummy_weights,
        DEVICE,
        compute_cm=True,
        use_descriptors=use_descriptors)

    print("FINAL ACCURACY: {}".format(acc))
    print("Average predicted proba for right class: {}".format(proba))
    print("Duration on {} test faces: {}s".format(
        imgs_with_detected_face, round(time() - start_time, 2)))
    print("Close the confusion matrix to end the script.")
    print("Accuracy with grouped classes : {}".format(acc_fact))
    plot_confusion_matrix(cm1, config["catslist"])
    plot_confusion_matrix(cm2, ["bad", "good", "surprise", "neutral"])