Exemple #1
0
def read_and_find(in_paths, out_path):
    """
    Reads an image from a path, and locates and encodes any face on it.

    :param path: path to an image
    :return: tuple of (cv2/np.ndarray, list of encodings, list of locations)
        or empty tuple if no face was found
    """
    for path in in_paths:
        img = cv2.imread(path)
        if img is None:
            continue
        locations = detect(img)
        h, w = img.shape[:2]
        basepath, sep, name = path.rpartition("\\")
        name, dot, ext = name.rpartition(".")
        count = 0
        print(f"Found {len(locations)} faces in {path}...")
        for loc in locations:
            l, t, r, b = loc
            fw, fh = r - l, b - t
            dw, dh = int(fw * 0.5), int(fh * 0.5)
            l, t, r, b = l - dw, t - dh, r + dw, b + dh
            x0, y0 = max(0, l), max(0, t)
            x1, y1 = min(w, r), min(h, b)
            sub_img = img[y0:y1, x0:x1]
            cv2.imwrite(f"{out_path}/{name}_{count}_{(x0, y0, x1, y1)}.{ext}",
                        sub_img)
    return None
Exemple #2
0
def read_and_find(path):
    """
    Reads an image from a path, and locates and encodes any face on it.

    :param path: path to an image
    :return: tuple of (cv2/np.ndarray, list of encodings, list of locations)
        or empty tuple if no face was found
    """
    print(f"Reading {path}...")
    img = cv2.imread(path)
    if img is None:
        return tuple()
    locations = detect(img)
    if not (locations):
        return tuple()
    if C_LOAD_ATLAS:  # we don't have to do the encodings in this case
        return img, [], locations, path
    return img, encode(img, locations=locations), locations, path
Exemple #3
0

def compose(img1, img2, mask):
    cv2.erode(mask, kern_erode, mask)
    mask = cv2.GaussianBlur(mask, (17, 17), 0)
    imask = -1. * (mask - 1.)
    ret = ((img1 * imask) + (img2 * mask)).astype(np.uint8)
    return ret


ploc_count = 1000

while True:
    check, frame = video.read()
    if ploc_count > 4:
        ploc = detect(frame, upsample=0)
        ploc_count = 0
    faces = landmark(frame, locations=ploc)
    ploc_count += 1
    # frame = draw_faces(frame, faces)
    if faces:
        morphed = morph(frame, newface, faces[0], newface_marks[0])
        faces_points = faces[0].points
        points = cv2.convexHull(np.int32(faces_points), returnPoints=False)
        mask = cv2.fillConvexPoly(
            np.zeros(frame.shape, dtype=np.float32),
            np.int32([faces_points[int(i)] for i in points]), (1.0, 1.0, 1.0))
        #m2 = (mask * morphed).astype(np.uint8)
        #morphed = color_correct(frame, morphed, faces[0])
    else:
        morphed = frame.copy()
    "Santi": "c:/test/phantom/tests/santi.jpg",
}

for name, impath in known_faces.items():
    img = cv2.imread(impath)
    if img is None:
        known_faces[name] = None
        continue
    known_faces[name] = encode(img)
    

video = cv2.VideoCapture(0)

while True:
    check, frame = video.read()
    faces = detect(frame, upsample=0)
    if faces:
        encodings = encode(frame, locations=faces)
        for i, e in enumerate(encodings):
            for k, v in known_faces.items():
                if compare(e, v) <= 0.6:
                    left, top, right, bottom = faces[i]
                    x = int (left * 0.5 + right * 0.5)
                    y = top
                    cv2.putText(frame, k, (x,y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0))
    cv2.imshow("Caras", frame)
    key = cv2.waitKey(1)
    if key == ord("q"):
        break

video.release()
Exemple #5
0
def tag():
    """
    Show images from a path waiting for user input to tag them.

    We're keeping only the images were dlibs HOG face detector picks up only one
    face. Using dlibs 5 point face landmark dataset a balanced female/male ratio
    is found at about ~600 images. We also skip images were landmarking goes
    wrong, as they can negatively affect the result of facial encoding.

    :return: list of TaggedFace for each image
    """
    def age_table(age_counter, age, padding=2):
        lines = [["  "], ["m "], ["f "], ["  "], ["  "]]
        for idx, (low, high, name) in enumerate(age_tags[1:], start=1):
            lines[0].append(f"{low:{padding}}-{high:{padding}}")
            lines[1].append(f"{age_counter['m'][idx]:{padding * 2 + 1}}")
            lines[2].append(f"{age_counter['f'][idx]:{padding * 2 + 1}}")
            lines[3].append(f"{idx:^5}")
            lines[4].append(f"{'▲' if age == idx else ' ':^5}")
        lines[0].append("Total")
        lines[1].append(f"{sum(age_counter['m'][1:]): 5}")
        lines[2].append(f"{sum(age_counter['f'][1:]): 5}")
        lines[3].append(
            f"{sum(age_counter['m'][1:]) + sum(age_counter['f'][1:]): 5}")

        ret = [
            "|".join(l) if i < 3 else " ".join(l) for i, l in enumerate(lines)
        ]
        return "\n".join(ret)

    def redraw(img, face, locations, color, text):
        """
        Groups together all the frame drawing logic, since it was needed on
        many places.
        """
        point1 = (locations[0][0], locations[0][1])
        point2 = (locations[0][2], locations[0][3])
        img_ = img.copy()
        face_and_rect = cv2.rectangle(img_,
                                      point1,
                                      point2,
                                      color=color,
                                      thickness=2)
        face_and_rect = draw_faces(img_, faces, color=color)
        face = ((face_and_rect * 0.5) + (img * 0.5)).astype(np.uint8)
        noface = img.copy()
        height, width = img.shape[:2]
        while height > 768 or width > 768:  # hardcoded and hacky, but works
            face = cv2.resize(face, (int(width / 2), int(height / 2)))
            noface = cv2.resize(noface, (int(width / 2), int(height / 2)))
            height, width = face.shape[:2]
        if height < 768 or width < 768:
            new_face = np.zeros((768, 1024, 3), dtype=np.uint8)
            new_noface = np.zeros((768, 1024, 3), dtype=np.uint8)
            new_face[384 - (height // 2):384 - (height // 2) + height,
                     512 - (width // 2):512 - (width // 2) + width] = face
            new_noface[384 - (height // 2):384 - (height // 2) + height,
                       512 - (width // 2):512 - (width // 2) + width] = noface
            face = new_face
            noface = new_noface

        # a bit of an optimization to avoid multiple conversion between ndarray
        # and PIL.Image structures
        face = Image.fromarray(cv2.cvtColor(face, cv2.COLOR_BGR2RGB))
        noface = Image.fromarray(cv2.cvtColor(noface, cv2.COLOR_BGR2RGB))
        for y, line in enumerate(text.split("\n")):
            face = draw_text(face, line, (0, y * 20 + 20), CONST_FONT, 16,
                             color)
            noface = draw_text(noface, line, (0, y * 20 + 20), CONST_FONT, 16,
                               color)
        face = cv2.cvtColor(np.array(face), cv2.COLOR_RGB2BGR)
        noface = cv2.cvtColor(np.array(noface), cv2.COLOR_RGB2BGR)
        return face, noface

    tagged = []
    age_counter = {
        "m": [0 for i in range(9)],
        "f": [0 for i in range(9)],
    }

    count_f = 0
    count_m = 0
    color = next(color_cycle)
    for filename in glob.glob(f"{PATH_TRAIN}/*.jpg"):
        img = cv2.imread(filename)
        locations = detect(img)
        faces = landmark(img, locations=locations)
        if len(faces) != 1:
            continue
        toggle_face = True
        age_tag = 0
        text = (f"f: {count_f} "
                f"m: {count_m} "
                f"(total: {count_f + count_m})\n\n" +
                age_table(age_counter, age_tag))
        frame_face, frame_noface = redraw(img, faces, locations, color, text)
        cv2.imshow("Tagger", frame_face)
        key = chr(cv2.waitKey()).lower()
        while key not in "q mf":
            if key == "k":
                color = next(color_cycle)
                frame_face, frame_noface = redraw(img, faces, locations, color,
                                                  text)
                toggle_face = True
                cv2.imshow("Tagger", frame_face)
            if key == "l":
                if toggle_face:
                    cv2.imshow("Tagger", frame_noface)
                    toggle_face = False
                else:
                    cv2.imshow("Tagger", frame_face)
                    toggle_face = True
            if key in "12345678":
                age_tag = int(key)
                text = (f"f: {count_f} "
                        f"m: {count_m} "
                        f"(total: {count_f + count_m})\n\n" +
                        age_table(age_counter, age_tag))
                frame_face, frame_noface = redraw(img, faces, locations, color,
                                                  text)
                toggle_face = True
                cv2.imshow("Tagger", frame_face)
            key = chr(cv2.waitKey()).lower()
        if key == "q":
            break
        if key == " ":
            continue
        if key == "m":
            tag = tags_male
            count_m += 1
            age_counter["m"][age_tag] += 1
        if key == "f":
            tag = tags_female
            count_f += 1
            age_counter["f"][age_tag] += 1
        tagged.append(TaggedFace(tag, age_tag, filename, img))
    for t in tagged:
        print(t)
    cv2.destroyAllWindows()
    return tagged
Exemple #6
0
def tag():
    """
    Show images from a path waiting for user input to tag them.

    We're keeping only the images were dlibs HOG face detector picks up only one
    face. Using dlibs 5 point face landmark dataset a balanced female/male ratio
    is found at about ~600 images. We also skip images were landmarking goes
    wrong, as they can negatively affect the result of facial encoding.

    :return: list of TaggedFace for each image
    """
    def redraw(img, face, locations, color, text):
        """
        Groups together all the frame drawing logic, since it was needed on
        many places.
        """
        point1 = (locations[0][0], locations[0][1])
        point2 = (locations[0][2], locations[0][3])
        img_ = img.copy()
        face_and_rect = cv2.rectangle(img_,
                                      point1,
                                      point2,
                                      color=color,
                                      thickness=2)
        face_and_rect = draw_faces(img_, faces, color=color)
        face = ((face_and_rect * 0.5) + (img * 0.5)).astype(np.uint8)
        noface = img.copy()
        height, width = img.shape[:2]
        if height > 960 or width > 1800:  # hardcoded and hacky, but works
            face = cv2.resize(face, (int(width / 2), int(height / 2)))
            noface = cv2.resize(noface, (int(width / 2), int(height / 2)))

        for y, line in enumerate(text.split("\n")):
            cv2.putText(face, line, (0, y * 20 + 20), CONST_FONT, 0.75, color,
                        2)
            cv2.putText(noface, line, (0, y * 20 + 20), CONST_FONT, 0.75,
                        color, 2)
        return face, noface

    tagged = []
    count_f = 0
    count_m = 0
    color = next(color_cycle)
    for filename in glob.glob(f"{PATH_TRAIN}/*.jpg"):
        img = cv2.imread(filename)
        locations = detect(img)
        faces = landmark(img, locations=locations)
        if len(faces) != 1:
            continue
        toggle_face = True
        text = (f"total : {count_f + count_m}\n"
                f"female: {count_f}\n"
                f"male  : {count_m}")
        frame_face, frame_noface = redraw(img, faces, locations, color, text)
        cv2.imshow("Tagger", frame_face)
        key = chr(cv2.waitKey()).lower()
        while key not in "q mf":
            key = chr(cv2.waitKey()).lower()
            if key == "k":
                color = next(color_cycle)
                frame_face, frame_noface = redraw(img, faces, locations, color,
                                                  text)
                toggle_face = True
                cv2.imshow("Tagger", frame_face)
            if key == "l":
                if toggle_face:
                    cv2.imshow("Tagger", frame_noface)
                    toggle_face = False
                else:
                    cv2.imshow("Tagger", frame_face)
                    toggle_face = True
        if key == "q":
            break
        if key == " ":
            continue
        if key == "m":
            tag = tags_male
            count_m += 1
        if key == "f":
            tag = tags_female
            count_f += 1
        tagged.append(TaggedFace(tag, filename, img))
    for t in tagged:
        print(t)
    cv2.destroyAllWindows()
    return tagged