Небольшая предыстория:
Мой бот вполне успешно работал пару месяцев с использованием распознавания IBM Watson, однако затем на хабре вышла статья про google cloud vision и оказалось, что Google распознает изображения лучше, чем IBM. В тот же день я зарегистрировался в консоли разработчика Google cloud platform и начал переписывать блок модерации котиков в своем боте.
Немного поискав, я нашел подходящий пример на C# на гитхабе GoogleCloudPlatform. Я поменял аутентификацию из примера и сделал ее из json файла с private key, который взял в разделе «сервисные аккаунты» консоли.
private VisionService service; private string _JsonPath = @"C:BOTSfcatsbotjson.json"; private VisionService CreateAuthorizedClient(string JsonPath) { GoogleCredential credential = GoogleCredential.FromStream(new FileStream(JsonPath, FileMode.Open)); // Inject the Cloud Vision scopes if (credential.IsCreateScopedRequired) { credential = credential.CreateScoped(new[] { VisionService.Scope.CloudPlatform }); } var res = new VisionService(new BaseClientService.Initializer { HttpClientInitializer = credential, GZipEnabled = false }); return res; }
Далее я переделал модерацию изображений (label detection). В примере на гитхабе DetectLabels работает с файлом, а мне нужно было работать с ссылкой, которую я получал с серверов Telegram, чтобы не хранить у себя файлы изображений. Я сохраняю в базе только file_id, что дает неплохой прирост скорости работы.
private async Task> DetectLabels( VisionService vision, string imageUrl) { // Convert image to Base64 encoded for JSON ASCII text based request MemoryStream ms = new MemoryStream(); using (var client = new HttpClient()) { Stream imageBytes = await client.GetStreamAsync(imageUrl); imageBytes.CopyTo(ms); } byte[] imageArray = ms.ToArray(); string imageContent = Convert.ToBase64String(imageArray); // Post label detection request to the Vision API // [START construct_request] var responses = vision.Images.Annotate( new BatchAnnotateImagesRequest() { Requests = new[] { new AnnotateImageRequest() { Features = new [] { new Feature() { Type = "LABEL_DETECTION"} }, Image = new Image() { Content = imageContent } } } }).Execute(); ms.Dispose(); return responses.Responses; }
Затем я ищу в Responses есть ли label с описанием котика, с оценкой более 0.6, и таким образом, определяю есть ли котик в переданной боту картинке:
foreach (var response in responses.Responses) { foreach (var label in response.LabelAnnotations) { double _score = label.Score == null ? 0 : Convert.ToDouble(label.Score.Value); var class = label.Description.Trim(); if (class .Contains("kitten") || class .Contains("cat") ) && (_score > 0.60)) { HasCatOrKittenClass = true;//moderation OK } } }
Вот код работы с API Telegram для получения ссылки на изображение из file_id, я использовал библиотеку на C# telegram bot:
var file = await MainParams.TGBot.GetFileAsync(fileid); var file_path = file.FilePath; var urlImage = "https://api.telegram.org/file/bot" + MainParams.bot_token + "/" + file_path;
А когда я отправляю изображение пользователю с помощью sendPhoto, я просто передаю сохраненный file_id вторым параметром.
Таким образом, получается что когда пользователь присылает свое фото котика на модерацию (или использует для этого thecatapi.com), я сохраняю в базе только file_id и в дальнейшем использую его для получения ссылки на картинку на серверах Telegram и для отправки пользователям с помощью sendPhoto. А распознавание изображений с помощью Google cloud vision работает более точно, чем у IBM Watson
Источник