Рубрики
Без рубрики

Проект выходных: язык жестов и распознавание статического жеста с использованием Scikit-Learn

Автор оригинала: FreeCodeCapm Team.

Sreehari

Давайте построим машинный трубопровод, который может прочитать алфавит языка знака, просто глядя на сырье руку человека.

Эта проблема имеет две части к нему:

  1. Создание распознавателя статического жеста, которое является многократным классификатором, который предсказывает жесты языка статического знака.
  2. Расположение руки в необработанном изображении и кормление этого раздела изображения к распознаванию статического жеста (многоклассное классификатор).

Вы можете получить мой пример код и набор данных для этого проекта здесь Отказ

Во-первых, немного фона.

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

Разработан диапазон продвинутых методов для того же. Здесь мы посмотрим, как выполнить распознавание статического жест, используя библиотеки изображений Scikit и Scikit.

Часть 1: Создание распознавания статического жеста

Для этой части мы используем набор данных, содержащий необработанные изображения и соответствующий файл CSV с координатами, указывающими ограничивающую коробку для рук в каждом изображении. ( Используйте файл DataSet.zip, чтобы получить набор данных образца. Извлечь согласно инструкции в файле README )

Этот набор данных организован пользователем, и структура каталога набора данных выглядит следующим образом. Имена изображений указывают на алфавит, представленный образ.

dataset
   |----user_1
          |---A0.jpg
          |---A1.jpg
          |---A2.jpg
          |---...
          |---Y9.jpg
   |----user_2
          |---A0.jpg
          |---A1.jpg
          |---A2.jpg
          |---...
          |---Y9.jpg
   |---- ...
   |---- ...

Распознавание Static-Gesture по существу является многократным классификатором, который обучен на входных изображениях, представляющих 24 статическими жестами языка знака (A-Y, исключая j).

Создание распознавателя статического жеста с использованием плавных изображений и файл CSV довольно прост.

Чтобы использовать классификаторы многоклассных классификаторов из библиотеки Scikit Share, нам нужно сначала построить набор данных – то есть каждое изображение должно быть преобразовано в вектор функции (X), и каждое изображение будет иметь метку, соответствующую Язык знака алфавит, который он обозначает (Y).

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

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

Код:

Мы используем Pandas в функции get_data () для загрузки файла CSV. Две функции – урожай () и convertTograytohog () Используются для получения требуемого вектора свиньи и добавить его в список векторов, которые мы строят, чтобы обучить многоклассную классификатор.

# returns hog vector of a particular image vector
def convertToGrayToHOG(imgVector):
    rgbImage = rgb2gray(imgVector)
    return hog(rgbImage)
    
# returns cropped image 
def crop(img, x1, x2, y1, y2, scale):
    crp=img[y1:y2,x1:x2]
    crp=resize(crp,((scale, scale))) 
    return crp
    
#loads data for multiclass classification
def get_data(user_list, img_dict, data_directory):
  X = []
  Y = []
  
  for user in user_list:
    user_images = glob.glob(data_directory+user+'/*.jpg')
    
    boundingbox_df = pd.read_csv(data_directory + user + '/'
 + user + '_loc.csv')
        
    for rows in boundingbox_df.iterrows():
      cropped_img = crop( img_dict[rows[1]['image']], 
                         rows[1]['top_left_x'], 
                         rows[1]['bottom_right_x'], 
                         rows[1]['top_left_y'], 
                         rows[1]['bottom_right_y'], 
                         128
                        )
       hogvector = convertToGrayToHOG(cropped_img)
       
       X.append(hogvector.tolist())
       Y.append(rows[1]['image'].split('/')[1][0])
       
    return X, Y

Следующим шагом является кодировать этикетки вывода (значения Y) к числовым значениям. Мы делаем это, используя реактивный кодировщик Sklearn.

В нашем коде мы сделали это следующим образом:

Y_mul = self.label_encoder.fit_transform(Y_mul)

Где объект LABLE_ENCODER построен следующим образом в конструкторе класса распознавания жестов:

self.label_encoder = LabelEncoder().fit(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y'])

Как только это сделано, модель может быть обучена с использованием любого многоклассного алгоритма классификации вашего выбора из Scikit Surlection Toolbox. Мы обучили наши, используя Поддержка векторная классификация , с линейным ядром.

Обучение модели с использованием Sklearn не включает в себя более двух строк кода. Вот как вы это делаете:

svcmodel = SVC(kernel='linear', C=0.9, probability=True) 
self.signDetector = svcmodel.fit(X_mul, Y_mul) 

Гиперпараметры (то есть. 9 в этом случае) можно настроить с помощью поиска сетки. Подробнее об этом здесь Отказ

В этом случае мы не знаем много о данных как таковые (то есть векторы свиней). Итак, было бы хорошей идеей попробовать использовать алгоритмы, такие как Xgboost (Extreme Gradient Boosting) или случайные классификаторы лесов и посмотрите, как выполняются эти алгоритмы.

Часть 2: Создание локализатора

Эта часть требует немного больше усилий по сравнению с первым.

В целом, мы будем использовать следующие шаги в выполнении этой задачи.

  1. Создайте набор данных Состоит из изображений рук и частей, которые не являются рукой, используя заданный набор данных и значения ограничения для каждого изображения.
  2. Поезд бинарный классификатор Для обнаружения изображений рук/не ручной работы с использованием вышеуказанного набора данных.
  3. (Необязательно) Используйте Жесткая негативная добыча Улучшить классификатор.
  4. Используйте Скользящий оконный подход С различными весами , на изображении запроса, чтобы изолировать область интереса.

Здесь мы не собираемся использовать какие-либо методы обработки изображений, такие как фильтрация, цветовая сегментация и т. Д. Библиотека изображений Scikit используется для чтения, урожая, масштабирования, преобразования изображений в серые весы и экстрагировать векторы свивода.

Строительство руки/не наборный набор рук:

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

"""
This function randomly generates bounding boxes 
Returns hog vector of those cropped bounding boxes along with label 
Label : 1 if hand ,0 otherwise 
"""
def buildhandnothand_lis(frame,imgset):
    poslis =[]
    neglis =[]
    
    for nameimg in frame.image:
        tupl = frame[frame['image']==nameimg].values[0]
        x_tl = tupl[1]
        y_tl = tupl[2]
        side = tupl[5]
        conf = 0
        
        dic = [0, 0]
        
        arg1 = [x_tl,y_tl,conf,side,side]
        
        poslis.append( convertToGrayToHOG(crop(imgset[nameimg],  x_tl,x_tl+side,y_tl,y_tl+side)))
        
        while dic[0] <= 1 or dic[1] < 1:
            x = random.randint(0,320-side)
            y = random.randint(0,240-side) 
            crp = crop(imgset[nameimg],x,x+side,y,y+side)
            hogv = convertToGrayToHOG(crp)
            arg2 = [x,y, conf, side, side]
            
            z = overlapping_area(arg1,arg2)
            if dic[0] <= 1 and z <= 0.5:
                neglis.append(hogv)
                dic[0] += 1
            if dic[0]== 1:
                break
        label_1 = [1 for i in range(0,len(poslis)) ]
        label_0 = [0 for i in range(0,len(neglis))]
        label_1.extend(label_0)
        poslis.extend(neglis)
        
        return poslis,label_1

Обучение бинарного классификатора:

После того, как набор данных готов, обучение классификатора может быть сделано точно так же, как видно ранее частично 1.

Обычно в этом случае методика под названием Жесткая негативная добыча используется для уменьшения количества ложных положительных обнаружений и улучшения классификатора. Одним или двумя итерациями жесткой отрицательной добычи с использованием случайного классификатора леса, достаточно, чтобы ваш классификатор достигли приемлемых точков классификации, что в этом случае является чем-то выше 80%.

Посмотрите на код здесь для образца реализации того же Отказ

Обнаружение рук в тестовых изображениях:

Теперь, чтобы на самом деле использовать вышеуказанный классификатор, мы масштабируем тестовое изображение различными факторами, а затем используем Скользящий оконный подход На всех их выбрать окно, которое идеально отражает область интересов. Это сделано путем выбора региона, соответствующего максимум доверительных баллов, выделенных бинарным классификатором (рукой/нелетом) на всех весах.

Тестовые изображения должны быть масштабированы, потому что мы запустим окно размером с множеством (в нашем случае, это 128×128) по всем изображениям, чтобы выбрать интересующую область, и возможно, что область интересов не вписывается в этот размер окна Отказ

Образец реализации и Общее обнаружение по всем весам Отказ

Положить все это вместе

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

То есть, учитывая тестовое изображение, мы сначала получаем различные обнаруженные области на разных масштабах изображения и выберите лучший среди них. Затем этот регион вырезан, ReCaled (до 128×128) и его соответствующий вектору свиньи подается в многоклассное классификатор (I.E., распознавание жеста). Удерживание жеста затем предсказывает жест, обозначенный рукой на изображении.

Ключевые точки

Чтобы обобщить, этот проект включает в себя следующие шаги. Ссылки относятся к соответствующему коду в репозитории GitHub.

  1. Строительство руки/не набора данных Отказ
  2. Преобразование всех изображений I.E., обрезанные разделы с жестами и рукой, непосвященными изображениями, к его векторизованной форме.
  3. Создание бинарного классификатора для обнаружения раздела рукой и построение многоклассного классификатора для определения жеста с использованием этих наборов данных.
  4. Используя вышеуказанные классификаторы один за другим, чтобы выполнить необходимую задачу.

Соден И я работал над этим проектом как часть курса обучения машины, который мы взяли в колледж. Большой крик для нее за все ее вклады!

Кроме того, мы хотели упомянуть Pyimagesearch , который является замечательным блогом, который мы широко использовали, пока мы работали над проектом! Проверьте это для контента на обработке изображений и соответствующим контентом OpenCV.

Ваше здоровье!