Машинное обучение Microsoft Azure — это мощный облачный сервис для предиктивной аналитики. Он позволяет вам определять модели и проводить эксперименты в облаке для анализа данных и поиска закономерностей.
Microsoft Azure Machine Learning Studio — это инструмент, предоставляющий интерфейс перетаскивания для создания моделей и быстрого их опробования. Вы можете поделиться своими моделями с сообществом, чтобы использовать или использовать то, чем поделились другие, через Cortana Intelligence Gallery.
Microsoft упаковала свои модели машинного обучения распознавания речи и лиц в Microsoft Cognitive Services (Project Oxford). Это не просто распознавание, API-интерфейсы могут извлекать гораздо больше контекста из данных, и поэтому приложения, которые мы создаем с их помощью, могут быть более продуктивными и персонализированными.
В этом эксперименте мы будем изучать Face API. Сначала мы поймем, что может предоставить служба, а затем рассмотрим вариант использования.
Майкрософт Фейс API,
Это часть Microsoft Cognitive Services, мощного облачного сервиса с функциями обнаружения и распознавания лиц.
- Обнаружение лица означает поиск области лица на изображении. Он представлен прямоугольником. API также имеет функциональные возможности для поиска различных характеристик/атрибутов лица — возраста, пола, позы, очков и растительности на лице. Есть много онлайн-приложений, которые используют Face API в фоновом режиме.
- Face Verification — это возможность найти сходство между двумя лицами. Этот API может сравнивать два лица, находить все похожие лица и тому подобное.
Чтобы понять, как использовать сервис, нам нужно сначала немного разобраться в организации данных. Иерархия объектов следующая:
Существуют группы пользователей, в которых может быть до 1000 человек. С каждым человеком может быть связано до 248 лиц. Изображение с лицом можно искать в группе людей, человеке или на фоне другого лица.
У вас может быть одна группа членов семьи, другая из друзей и тому подобное. Ваша группа членов семьи может иметь объект Person, и каждый из них представляет члена семьи. И тогда вы можете иметь несколько изображений лиц, связанных с каждым человеком. Он хорошо работает с изображениями лица и лица вблизи.
Поэтому, прежде чем мы начнем, активируйте бесплатную подписку на Face API в Microsoft Azure Cognitive Services. А здесь документация по API для ознакомления.
Давайте пойдем по принципу «сверху вниз»!
Группы лиц
Сначала мы создадим группу лиц. PersonGroup — это логическая группа лиц. Вы можете создать один универсальный набор или создать группы из нескольких человек в зависимости от варианта использования. Ограничение составляет 1000 объектов Person в одной PersonGroup.
public class PersonGroups { public string personGroupId { get; set; } public string name { get; set; } public string userData { get; set; } }
У PersonGroup есть идентификатор, который мы определяем, и мы предоставляем «имя». Мы также можем связать с ним некоторые «пользовательские данные». Например, описание или может быть что-то внутреннее для нашего использования.
public static async Task<string> AddPersonGroups(string personGroupId, string name, string userData) { string uri = HttpHandler.BaseUri + "/" + personGroupId; string jsonString = "{\"name\":\"" + name + "\", \"userData\":\"" + userData + "\"}"; HttpContent content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await HttpHandler.client.PutAsync(uri, content); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; } BaseUri: https://api.projectoxford.ai/face/v1.0/persongroups
лица
Объект person представляет человека в группе людей. Когда мы создаем новый объект человека, нам нужно связать его с personGroupId.
class Persons { public string personId { get; set; } public string name { get; set; } public string userData { get; set; } public List persistedFaceIds { get; set; } }
Нам нужно связать «имя» и можно связать «userData». PersonId возвращается при создании нового человека, но с ним не связано лицо.
public static async Task<string> CreatePerson(string personGroupId, string name, string userData) { string uri = HttpHandler.BaseUri + "/" + personGroupId + "/persons"; string jsonString = "{\"name\":\"" + name + "\", \"userData\":\"" + userData + "\"}"; HttpContent content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await HttpHandler.client.PostAsync(uri, content); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; }
Лица
Объект лица связан с Person и personGroup. С человеком может быть связано до 248 лиц.
public class FaceData { public string persistedFaceId { get; set; } public string userData { get; set; } }
На изображении может быть только одно детектируемое лицо (за исключением, для краткости, отброшенного).
public static async Task<string> AddPersonFace(string personGroupId, string personId, string userData) { string uri = HttpHandler.BaseUri + "/" + personGroupId + "/persons/" + personId + "/persistedFaces?userData=" + userData + "&userData=" + userData; string jsonString = "{\"url\":\"" + HttpHandler.storagePath + "originals/" + userData + "\"}"; HttpContent content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await HttpHandler.client.PostAsync(uri, content); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; }
Обучение
Прежде чем мы сможем запустить какое-либо сравнение, нам нужно обучить нашу систему. Обучение заключается в запуске модели машинного обучения для группы людей, которую мы определили.
public static async Task<string> TrainPersonGroups(string personGroupId) { string uri = HttpHandler.BaseUri + "/" + personGroupId + "/train"; HttpResponseMessage response = await HttpHandler.client.PostAsync(uri, null); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; }
Он собирается создать внутреннюю базу функций и связать ее с различными объектами. Для лиц, которые мы связали с каждым человеком, будут сохранены некоторые извлеченные данные. Это не означает полное изображение, а набор функций, которые ML будет использовать для сравнения.
Статус обучения можно запросить, после завершения мы можем запустить наш сравнительный запрос!
public static async Task<string> StatusPersonGroups(string personGroupId) { string uri = HttpHandler.BaseUri + "/" + personGroupId + "/training"; HttpResponseMessage response = await HttpHandler.client.GetAsync(uri); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); return responseBody; }
Searching
Теперь наша установка машинного обучения заполнена данными и обучена. Давайте запросим лицо, чтобы идентифицировать человека!
Шаги просты
- Загрузите изображение-кандидат в хранилище BLOB-объектов. Я объяснил процесс ранее.
- Найдите FaceId всех лиц на изображении-кандидате
- Для всех FaceId на изображении-кандидате выполните идентификационный запрос.
- Идентификационный запрос возвращает кандидатов с PersonId и уровнем достоверности
- Преобразовать PersonId в имя человека
Несколько классов для представления данных, которые мы будем отправлять и получать:
public class FaceRectangle { public int top { get; set; } public int left { get; set; } public int width { get; set; } public int height { get; set; } } public class Visitors { public string faceId { get; set; } public FaceRectangle faceRectangle { get; set; } } public class FaceQueryPayload { public string personGroupId { get; set; } public List faceIds { get; set; } public int maxNumOfCandidatesReturned { get; set; } public double confidenceThreshold { get; set; } } public class Candidate { public string personId { get; set; } public double confidence { get; set; } } public class CandidateObject { public string faceId { get; set; } public List candidates { get; set; } }
Отправка изображения-кандидата в хранилище BLOB-объектов
private async void btnTestPic_Click(object sender, RoutedEventArgs e) { btnTestPic.IsEnabled = false; FileOpenPicker filePicker = new FileOpenPicker(); filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; filePicker.ViewMode = PickerViewMode.Thumbnail; filePicker.FileTypeFilter.Clear(); filePicker.FileTypeFilter.Add(".jpeg"); filePicker.FileTypeFilter.Add(".jpg"); filePicker.FileTypeFilter.Add(".png"); filePicker.FileTypeFilter.Add(".gif"); StorageFile file = await filePicker.PickSingleFileAsync(); CloudBlockBlob blob = null; string blobFileName = null; if (null != file) { BitmapImage bitmapImage = new BitmapImage(); IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read); bitmapImage.SetSource(fileStream); CapturedPhoto.Source = bitmapImage; CapturedPhoto.Tag = file.Path; blobFileName = System.Guid.NewGuid() + "." + file.Name.Split('.').Last(); await HttpHandler.tempContainer.CreateIfNotExistsAsync(); BlobContainerPermissions permissions = new BlobContainerPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Blob; await HttpHandler.tempContainer.SetPermissionsAsync(permissions); blob = HttpHandler.tempContainer.GetBlockBlobReference(blobFileName); await blob.DeleteIfExistsAsync(); await blob.UploadFromFileAsync(file); string uri = "https://api.projectoxford.ai/face/v1.0/detect?returnFaceId=true"; string jsonString = "{\"url\":\"" + HttpHandler.storagePath + "visitors/" + blobFileName + "\"}"; HttpContent content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await HttpHandler.client.PostAsync(uri, content); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); List names = await VisitorCmds.CheckFace(responseBody, ((PersonGroups)cmbPersonGroup.SelectedItem).personGroupId); txtResponse.Text = string.Join(",", names.ToArray()); } btnTestPic.IsEnabled = true; } }
Сравнение лиц
public static async Task<List> CheckFace(string responseString, string personGroupId) { List visitors = JsonConvert.DeserializeObject<List>(responseString); List faceIds = new List(); ; foreach (Visitors visitor in visitors) { faceIds.Add(visitor.faceId); } FaceQueryPayload jsonPayLoad = new PhotoBooth.VisitorCmds.FaceQueryPayload(); jsonPayLoad.personGroupId = personGroupId; jsonPayLoad.faceIds = faceIds; jsonPayLoad.maxNumOfCandidatesReturned = 1; jsonPayLoad.confidenceThreshold = 0.5; string uri = "https://api.projectoxford.ai/face/v1.0/identify"; string jsonString = JsonConvert.SerializeObject(jsonPayLoad); HttpContent content = new StringContent(jsonString, Encoding.UTF8, "application/json"); HttpResponseMessage response = await HttpHandler.client.PostAsync(uri, content); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); List candidates = JsonConvert.DeserializeObject<List>(responseBody); List names = new List(); foreach (CandidateObject candidate in candidates) { //get person from personId if (candidate.candidates.Count != 0) { string name = await PersonCmds.GetPerson(personGroupId, candidate.candidates[0].personId); names.Add(name); } } return names; } }
Я опубликую полный код на github вскоре после очистки и некоторой обработки ошибок. А пока, взломай!