Скрипт для определения ориентиров и обрезки рта с изображений с использованием OpenCV не видит лиц

Итак, то, что я пытаюсь сделать с помощью OpenCV, dlib и Python, - это в основном идентифицировать лицевые ориентиры на наборе изображений с помощью dlib, а затем обрезать рты с тех же самых изображений и сохранять их как отдельные изображения с расширением ".jpg". расширения.

Вот код:

import numpy as np  
import cv2  
import dlib
import sys
import skimage 
from PIL import Image
import os
import glob

#Everything is imported here

folderpath = sys.argv[1]
cascPath = sys.argv[2]
PREDICTOR_PATH = "/home/victor/facial-landmarks/shape_predictor_68_face_landmarks.dat" 

#user supplies the folderpath and cascpath in a terminal/command prompt
#predictor_path is already set

imageformat = ".tif"
path = folderpath
imfilelist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith(imageformat)]

#only images with ".tif" extensions in the folder interest us, we create a
#list with paths to those images    

data = np.array([])
for IMG in imfilelist:
    image = cv2.imread(IMG) #this for-loop iterates through images we need
    np.append(data, image) # reads them, and appends them to the data 
                           # numpy array

gray = np.array([])
for j in range(0, len(data)):
    cvtimg = cv2.cvtColor(np.array(data[j]), cv2.COLOR_BGR2GRAY)
    np.append(gray, cvtimg) #empty numpy array called gray is declared
                            # for-loop goes through all RGB pictures
                            # stored in data, converts them to grayscale
                            # and stores them in gray



MOUTH_OUTLINE_POINTS = list(range(48, 61))  
MOUTH_INNER_POINTS = list(range(61, 68))

#defines the landmarks for the Mouth Outline and the inner mouth points  

faceCascade = cv2.CascadeClassifier(cascPath)

#faceCascade is defined here, cascPath which is user supplied is the param  

predictor = dlib.shape_predictor(PREDICTOR_PATH)  

faces = np.array([])   
for i in gray:
    face = faceCascade.detectMultiScale(gray[i], scaleFactor=1.05, minNeighbors=5, minSize=(100,100))
    np.append(faces, face) #this for-loop tries to detect faces and append       
                           #them to the empty numpy array called faces

print("Found {0} faces!".format(len(faces)))

# nothing is displayed beyond this print statement               

for (x, y, w, h) in faces:  

  dlib_rect = dlib.rectangle(int(x), int(y), int(x + w), int(y + h))  

  landmarks = np.matrix([[p.x, p.y]  
              for p in predictor(IMAGES, dlib_rect).parts()])  

  landmarks_display = landmarks[MOUTH_OUTLINE_POINTS + MOUTH_INNER_POINTS]

  highX = 0
  lowX = 1000
  highY = 0
  lowY = 1000

  for idx, point in enumerate(landmarks_display):  
    pos = (point[0, 0], point[0, 1])  
    cv2.circle(image, pos, 2, color=(0, 0, 255), thickness=-1)
  if (pos[0] > highX):
   highX = pos[0]
  if (pos[0] < lowX):
   lowX = pos[0]
  if (pos[1] > highY):
   highY = pos[1]
  if (pos[1] < lowY):
   lowY = pos[1]
  print (lowX, lowY, highX, highY)


  CONSTANT_FACTOR = 0.325
  delta_x = highX-lowX
  delta_y = highY - lowY
  low_x_adj = lowX - int(delta_x * CONSTANT_FACTOR)
  high_x_adj = highX + int(delta_x * CONSTANT_FACTOR)
  low_y_adj = lowY - int(delta_y * 0.2)
  high_y_adj = highY + int(delta_y * CONSTANT_FACTOR)

  crop_img = image[low_y_adj:high_y_adj,low_x_adj:high_x_adj]
  cv2.imwrite("Cropped_Mouth.jpg", crop_img)
  cv2.imshow("Cropped_Mouth.jpg", crop_img)

  cv2.waitKey(0)    

Теперь я проверил пути, и они верны. Я не получаю никаких синтаксических ошибок, ошибок времени выполнения, ничего. Сценарий выполняется, но не выводится ничего, кроме следующего оператора печати: print("Found {0} faces!".format(len(faces))).

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

Будем очень признательны за любые идеи и предложения. Спасибо.

P.S если проблема связана с кодом после строки, которая печатается, я все еще не начал работать над этой частью для этого сценария, потому что я считаю, что это код над оператором печати, который каким-то образом неисправен


person Victor Simon    schedule 29.06.2018    source источник


Ответы (1)


Почему бы не использовать детектор лиц dlib для обнаружения лиц ?. Ниже приведен код для обнаружения лиц с помощью детектора лиц dlib и сохранения рта от лиц с расширением .jpg. Я только что изменил dlib face landmarks.py, указанный в папке с примерами Python в dlib.

import sys
import os
import dlib
import glob
import cv2

predictor_path = "shape_predictor_68_face_landmarks.dat"
faces_folder_path = "path/to/faces/folder"

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_path)
win = dlib.image_window()
i = 0
for f in glob.glob(os.path.join(faces_folder_path, "*.tiff")):
    print("Processing file: {}".format(f))
    img = cv2.imread(f)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

    # to clear the previous overlay. Useful when multiple faces in the same photo
    win.clear_overlay()

    # to show the image
    win.set_image(img)

    # Ask the detector to find the bounding boxes of each face. The 1 in the
    # second argument indicates that we should upsample the image 1 time. This
    # will make everything bigger and allow us to detect more faces.
    dets = detector(img, 1)
    print("Number of faces detected: {}".format(len(dets)))
    for k, d in enumerate(dets):
        print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
            k, d.left(), d.top(), d.right(), d.bottom()))
        # Get the landmarks/parts for the face in box d.
        shape = predictor(img, d)
        i += 1
        # The next lines of code just get the coordinates for the mouth
        # and crop the mouth from the image.This part can probably be optimised
        # by taking only the outer most points.
        xmouthpoints = [shape.part(x).x for x in range(48,67)]
        ymouthpoints = [shape.part(x).y for x in range(48,67)]
        maxx = max(xmouthpoints)
        minx = min(xmouthpoints)
        maxy = max(ymouthpoints)
        miny = min(ymouthpoints) 

        # to show the mouth properly pad both sides
        pad = 10
        # basename gets the name of the file with it's extension
        # splitext splits the extension and the filename
        # This does not consider the condition when there are multiple faces in each image.
        # if there are then it just overwrites each image and show only the last image.
        filename = os.path.splitext(os.path.basename(f))[0]

        crop_image = img[miny-pad:maxy+pad,minx-pad:maxx+pad]
        cv2.imshow('mouth',crop_image)
        # The mouth images are saved in the format 'mouth1.jpg, mouth2.jpg,..
        # Change the folder if you want to. They are stored in the current directory
        cv2.imwrite(filename+'.jpg',crop_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        win.add_overlay(shape)

    win.add_overlay(dets)
person timedacorn    schedule 29.06.2018
comment
Работает безупречно. Вопрос только в том, как мне сохранить имена используемых файлов TIFF? Поэтому, если он называется abc123.tif, я хочу, чтобы результат был abc123.jpg. - person Victor Simon; 29.06.2018
comment
Я отредактировал код для этого. Имейте в виду, что если на одном изображении несколько лиц, сохраняется только один рот. Если вам нужны все изображения рта, вам нужно каждый раз менять имя файла. - person timedacorn; 29.06.2018
comment
Я заметил правку, спасибо. Это именно то, что нужно. Я имею дело с изображениями, на которых только одно лицо. - person Victor Simon; 29.06.2018