Поделиться через


Модерация с помощью настраиваемых списков изображений на C#

В этой статье содержатся сведения и примеры кода, которые помогут вам приступить к работе с пакетом SDK Content Moderator для .NET. Вы научитесь выполнять такие задачи:

  • создание настраиваемого списка изображений;
  • добавление и удаление изображений в списке;
  • получение идентификаторов всех изображений в списке;
  • извлечение и обновление метаданных списка;
  • обновление индекса поиска списка;
  • проверка изображений с помощью изображений в списке;
  • удаление всех изображений из списка;
  • удаление пользовательского списка.

Примечание.

Существует максимальное ограничение в 5 списков изображений, каждый из которых может содержать не более 10 000 изображений.

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

Если у вас нет подписки Azure, создайте бесплатную учетную запись, прежде чем приступить к работе.

Регистрация в службах Content Moderator

Прежде чем использовать службы Content Moderator с помощью REST API или пакета SDK, необходимо получить ключ подписки для API. Подпишитесь на службу Content Moderator на портале Azure, чтобы получить его.

Создание проекта Visual Studio

  1. Добавьте в свое решение новый проект Консольное приложение (.NET Framework).

    В примере кода назовите проект ImageLists.

  2. Выберите этот проект в качестве единственного запускаемого проекта для решения.

Установка необходимых пакетов

Установите следующие пакеты NuGet:

  • Microsoft.Azure.CognitiveServices.ContentModerator;
  • Microsoft.Rest.ClientRuntime
  • Newtonsoft.Json

Обновление инструкций using в программе

Добавьте следующие операторы using:

using Microsoft.Azure.CognitiveServices.ContentModerator;
using Microsoft.Azure.CognitiveServices.ContentModerator.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

Создание клиента Content Moderator

Добавьте следующий фрагмент кода, чтобы создать клиент Content Moderator для своей подписки. Обновите поля AzureEndpoint и CMSubscriptionKey с учетом значений URL-адреса конечной точки и ключа подписки. Их можно найти на вкладке Быстрый запуск своего ресурса на портале Azure.

/// <summary>
/// Wraps the creation and configuration of a Content Moderator client.
/// </summary>
/// <remarks>This class library contains insecure code. If you adapt this 
/// code for use in production, use a secure method of storing and using
/// your Content Moderator subscription key.</remarks>
public static class Clients
{
	/// <summary>
	/// The base URL for Content Moderator calls.
	/// </summary>
	private static readonly string AzureEndpoint = "YOUR ENDPOINT URL";

	/// <summary>
	/// Your Content Moderator subscription key.
	/// </summary>
	private static readonly string CMSubscriptionKey = "YOUR API KEY";

	/// <summary>
	/// Returns a new Content Moderator client for your subscription.
	/// </summary>
	/// <returns>The new client.</returns>
	/// <remarks>The <see cref="ContentModeratorClient"/> is disposable.
	/// When you have finished using the client,
	/// you should dispose of it either directly or indirectly. </remarks>
	public static ContentModeratorClient NewClient()
	{
		// Create and initialize an instance of the Content Moderator API wrapper.
		ContentModeratorClient client = new ContentModeratorClient(new ApiKeyServiceClientCredentials(CMSubscriptionKey));

		client.Endpoint = AzureEndpoint;
		return client;
	}
}

Внимание

Обязательно удалите ключ из кода, когда завершите работу, и ни в коем случае не публикуйте его в открытом доступе. Для рабочей среды используйте безопасный способ хранения и доступа к учетным данным, например Azure Key Vault. Дополнительные сведения см. в статье по безопасности служб ИИ Azure.

Инициализация параметров приложения

Добавьте следующие классы и статические поля в класс Program в файле Program.cs.

/// <summary>
/// The minimum amount of time, im milliseconds, to wait between calls
/// to the Image List API.
/// </summary>
private const int throttleRate = 3000;

/// <summary>
/// The number of minutes to delay after updating the search index before
/// performing image match operations against the list.
/// </summary>
private const double latencyDelay = 0.5;

/// <summary>
/// Define constants for the labels to apply to the image list.
/// </summary>
private class Labels
{
	public const string Sports = "Sports";
	public const string Swimsuit = "Swimsuit";
}

/// <summary>
/// Define input data for images for this sample.
/// </summary>
private class Images
{
	/// <summary>
	/// Represents a group of images that all share the same label.
	/// </summary>
	public class Data
	{
		/// <summary>
		/// The label for the images.
		/// </summary>
		public string Label;

		/// <summary>
		/// The URLs of the images.
		/// </summary>
		public string[] Urls;
	}

	/// <summary>
	/// The initial set of images to add to the list with the sports label.
	/// </summary>
	public static readonly Data Sports = new Data()
	{
		Label = Labels.Sports,
		Urls = new string[] {
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png",
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample6.png",
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample9.png"
		}
	};

	/// <summary>
	/// The initial set of images to add to the list with the swimsuit label.
	/// </summary>
	/// <remarks>We're adding sample16.png (image of a puppy), to simulate
	/// an improperly added image that we will later remove from the list.
	/// Note: each image can have only one entry in a list, so sample4.png
	/// will throw an exception when we try to add it with a new label.</remarks>
	public static readonly Data Swimsuit = new Data()
	{
		Label = Labels.Swimsuit,
		Urls = new string[] {
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample1.jpg",
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample3.png",
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png",
			"https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png"
		}
	};

	/// <summary>
	/// The set of images to subsequently remove from the list.
	/// </summary>
	public static readonly string[] Corrections = new string[] {
		"https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png"
	};
}

/// <summary>
/// The images to match against the image list.
/// </summary>
/// <remarks>Samples 1 and 4 should scan as matches; samples 5 and 16 should not.</remarks>
private static readonly string[] ImagesToScreen = new string[] {
	"https://moderatorsampleimages.blob.core.windows.net/samples/sample1.jpg",
	"https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png",
	"https://moderatorsampleimages.blob.core.windows.net/samples/sample5.png",
	"https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png"
};

/// <summary>
/// A dictionary that tracks the ID assigned to each image URL when 
/// the image is added to the list.
/// </summary>
/// <remarks>Indexed by URL.</remarks>
private static readonly Dictionary<string, int> ImageIdMap =
	new Dictionary<string, int>();

/// <summary>
/// The name of the file to contain the output from the list management operations.
/// </summary>
/// <remarks>Relative paths are relative to the execution directory.</remarks>
private static string OutputFile = "ListOutput.log";

/// <summary>
/// A static reference to the text writer to use for logging.
/// </summary>
private static TextWriter writer;

/// <summary>
/// A copy of the list details.
/// </summary>
/// <remarks>Used to initially create the list, and later to update the
/// list details.</remarks>
private static Body listDetails;

Примечание.

Для ключа службы Content Moderator установлен лимит количества запросов в секунду. При его превышении пакет SDK создаст исключение с кодом ошибки 429. Для ключа уровня "Бесплатный" предусмотрен лимит в один запрос в секунду.

Создание метода для записи сообщений в файл журнала

Добавьте следующий метод в класс Program.

/// <summary>
/// Writes a message to the log file, and optionally to the console.
/// </summary>
/// <param name="message">The message.</param>
/// <param name="echo">if set to <c>true</c>, write the message to the console.</param>
private static void WriteLine(string message = null, bool echo = false)
{
	writer.WriteLine(message ?? String.Empty);

	if (echo)
	{
		Console.WriteLine(message ?? String.Empty);
	}
}

Создание метода для создания настраиваемого списка

Добавьте следующий метод в класс Program.

/// <summary>
/// Creates the custom list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <returns>The response object from the operation.</returns>
private static ImageList CreateCustomList(ContentModeratorClient client)
{
	// Create the request body.
	listDetails = new Body("MyList", "A sample list",
		new BodyMetadata("Acceptable", "Potentially racy"));

	WriteLine($"Creating list {listDetails.Name}.", true);

	var result = client.ListManagementImageLists.Create(
		"application/json", listDetails);
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

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

Добавьте следующий метод в класс Program. В этом руководстве не демонстрируется применение тегов к изображениям в списке.

/// <summary>
/// Adds images to an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <param name="imagesToAdd">The images to add.</param>
/// <param name="label">The label to apply to each image.</param>
/// <remarks>Images are assigned content IDs when they are added to the list.
/// Track the content ID assigned to each image.</remarks>
private static void AddImages(
ContentModeratorClient client, int listId,
IEnumerable<string> imagesToAdd, string label)
{
	foreach (var imageUrl in imagesToAdd)
	{
		WriteLine();
		WriteLine($"Adding {imageUrl} to list {listId} with label {label}.", true);
		try
		{
			var result = client.ListManagementImage.AddImageUrlInput(
				listId.ToString(), "application/json", new BodyModel("URL", imageUrl), null, label);

			ImageIdMap.Add(imageUrl, Int32.Parse(result.ContentId));

			WriteLine("Response:");
			WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
		}
		catch (Exception ex)
		{
			WriteLine($"Unable to add image to list. Caught {ex.GetType().FullName}: {ex.Message}", true);
		}
		finally
		{
			Thread.Sleep(throttleRate);
		}
	}
}

Создание метода для удаления изображений из списка

Добавьте следующий метод в класс Program.

/// <summary>
/// Removes images from an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <param name="imagesToRemove">The images to remove.</param>
/// <remarks>Images are assigned content IDs when they are added to the list.
/// Use the content ID to remove the image.</remarks>
private static void RemoveImages(
	ContentModeratorClient client, int listId,
	IEnumerable<string> imagesToRemove)
{
	foreach (var imageUrl in imagesToRemove)
	{
		if (!ImageIdMap.ContainsKey(imageUrl)) continue;
		int imageId = ImageIdMap[imageUrl];

		WriteLine();
		WriteLine($"Removing entry for {imageUrl} (ID = {imageId}) from list {listId}.", true);

		var result = client.ListManagementImage.DeleteImage(
			listId.ToString(), imageId.ToString());
		Thread.Sleep(throttleRate);

		ImageIdMap.Remove(imageUrl);

		WriteLine("Response:");
		WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
	}
}

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

Добавьте следующий метод в класс Program.

/// <summary>
/// Gets all image IDs in an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <returns>The response object from the operation.</returns>
private static ImageIds GetAllImageIds(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Getting all image IDs for list {listId}.", true);

	var result = client.ListManagementImage.GetAllImageIds(listId.ToString());
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

Создание метода для обновлений сведений о списке

Добавьте следующий метод в класс Program.

/// <summary>
/// Updates the details of an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <returns>The response object from the operation.</returns>
private static ImageList UpdateListDetails(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Updating details for list {listId}.", true);

	listDetails.Name = "Swimsuits and sports";

	var result = client.ListManagementImageLists.Update(
		listId.ToString(), "application/json", listDetails);
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

Создание метода для извлечения сведений о списке

Добавьте следующий метод в класс Program.

/// <summary>
/// Gets the details for an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <returns>The response object from the operation.</returns>
private static ImageList GetListDetails(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Getting details for list {listId}.", true);

	var result = client.ListManagementImageLists.GetDetails(listId.ToString());
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

Создание метода для обновления индекса поиска списка

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

/// <summary>
/// Refreshes the search index for an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <returns>The response object from the operation.</returns>
private static RefreshIndex RefreshSearchIndex(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Refreshing the search index for list {listId}.", true);

	var result = client.ListManagementImageLists.RefreshIndexMethod(listId.ToString());
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

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

Добавьте следующий метод в класс Program.

/// <summary>
/// Matches images against an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
/// <param name="imagesToMatch">The images to screen.</param>
private static void MatchImages(
	ContentModeratorClient client, int listId,
	IEnumerable<string> imagesToMatch)
{
	foreach (var imageUrl in imagesToMatch)
	{
		WriteLine();
		WriteLine($"Matching image {imageUrl} against list {listId}.", true);

		var result = client.ImageModeration.MatchUrlInput(
				"application/json", new BodyModel("URL", imageUrl), listId.ToString());
		Thread.Sleep(throttleRate);

		WriteLine("Response:");
		WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
	}
}

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

Добавьте следующий метод в класс Program.

/// <summary>
/// Deletes all images from an image list.
/// </summary>
/// <param name="client">The Content Modertor client.</param>
/// <param name="listId">The list identifier.</param>
private static void DeleteAllImages(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Deleting all images from list {listId}.", true);

	var result = client.ListManagementImage.DeleteAllImages(listId.ToString());
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
}

Создание метода для удаления списка

Добавьте следующий метод в класс Program.

/// <summary>
/// Deletes an image list.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <param name="listId">The list identifier.</param>
private static void DeleteCustomList(
	ContentModeratorClient client, int listId)
{
	WriteLine();
	WriteLine($"Deleting list {listId}.", true);

	var result = client.ListManagementImageLists.Delete(listId.ToString());
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
}

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

Добавьте следующий метод в класс Program.

/// <summary>
/// Gets all list identifiers for the client.
/// </summary>
/// <param name="client">The Content Moderator client.</param>
/// <returns>The response object from the operation.</returns>
private static IList<ImageList> GetAllListIds(ContentModeratorClient client)
{
	WriteLine();
	WriteLine($"Getting all image list IDs.", true);

	var result = client.ListManagementImageLists.GetAllImageLists();
	Thread.Sleep(throttleRate);

	WriteLine("Response:");
	WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));

	return result;
}

Добавление кода для моделирования использования списка изображений

Добавьте следующий код в метод Main. Этот код моделирует многие операции, выполняемые для определения списка и управления им, а также для проверки изображений с его помощью. Возможности ведения журнала позволяют просматривать объекты ответа, создаваемые вызовами пакета SDK, отправленными к службе Content Moderator.

// Create the text writer to use for logging, and cache a static reference to it.
using (StreamWriter outputWriter = new StreamWriter(OutputFile))
{
	writer = outputWriter;

	// Create a Content Moderator client.
	using (var client = Clients.NewClient())
	{
		// Create a custom image list and record the ID assigned to it.
		var creationResult = CreateCustomList(client);
		if (creationResult.Id.HasValue)
		{
			// Cache the ID of the new image list.
			int listId = creationResult.Id.Value;

			// Perform various operations using the image list.
			AddImages(client, listId, Images.Sports.Urls, Images.Sports.Label);
			AddImages(client, listId, Images.Swimsuit.Urls, Images.Swimsuit.Label);
					
			GetAllImageIds(client, listId);
			UpdateListDetails(client, listId);
			GetListDetails(client, listId);

			// Be sure to refresh search index
			RefreshSearchIndex(client, listId);

			// WriteLine();
			WriteLine($"Waiting {latencyDelay} minutes to allow the server time to propagate the index changes.", true);
			Thread.Sleep((int)(latencyDelay * 60 * 1000));

			// Match images against the image list.
			MatchImages(client, listId, ImagesToMatch);

			// Remove images
			RemoveImages(client, listId, Images.Corrections);

			// Be sure to refresh search index
			RefreshSearchIndex(client, listId);

			WriteLine();
			WriteLine($"Waiting {latencyDelay} minutes to allow the server time to propagate the index changes.", true);
			Thread.Sleep((int)(latencyDelay * 60 * 1000));

			// Match images again against the image list. The removed image should not get matched.
			MatchImages(client, listId, ImagesToMatch);

			// Delete all images from the list.
			DeleteAllImages(client, listId);

			// Delete the image list.
			DeleteCustomList(client, listId);

			// Verify that the list was deleted.
			GetAllListIds(client);
			}
		}

		writer.Flush();
		writer.Close();
		writer = null;
}

Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

Запуск программы и просмотр выходных данных

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

Creating list MyList.
Response:
{
	"Id": 169642,
	"Name": "MyList",
	"Description": "A sample list",
	"Metadata": {
		"Key One": "Acceptable",
		"Key Two": "Potentially racy"
	}
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png to list 169642 with label Sports.
Response:
{
	"ContentId": "169490",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "233"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "2945548"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_b4d3e20a-0751-4760-8829-475e5da33ce8"
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample6.png to list 169642 with label Sports.
Response:
{
	"ContentId": "169491",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "215"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "2440050"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_cc1eb6af-2463-4e5e-9145-2a11dcecbc30"
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample9.png to list 169642 with label Sports.
Response:
{
	"ContentId": "169492",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "98"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "1631958"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_01edc1f2-b448-48cf-b7f6-23b64d5040e9"
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample1.jpg to list 169642 with label Swimsuit.
Response:
{
	"ContentId": "169493",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "27"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "17280"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_41f7bc6f-8778-4576-ba46-37b43a6c2434"
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample3.png to list 169642 with label Swimsuit.
Response:
{
	"ContentId": "169494",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "129"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "1242855"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_61a48f33-eb55-4fd9-ac97-20eb0f3622a5"
}

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png to list 169642 with label Swimsuit.
Unable to add image to list. Caught Microsoft.CognitiveServices.ContentModerator.Models.APIErrorException: Operation returned an invalid status code 'Conflict'

Adding https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png to list 169642 with label Swimsuit.
Response:
{
	"ContentId": "169495",
	"AdditionalInfo": [
	{
		"Key": "Source",
		"Value": "169642"
	},
	{
		"Key": "ImageDownloadTimeInMs",
		"Value": "65"
	},
	{
		"Key": "ImageSizeInBytes",
		"Value": "1088127"
	}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_1c1f3de4-58b9-4aa8-82fa-1b0f479f6d7c"
}

Getting all image IDs for list 169642.
Response:
{
	"ContentSource": "169642",
	"ContentIds": [
		169490,
		169491,
		169492,
		169493,
		169494,
		169495
],
"Status": {
	"Code": 3000,
	"Description": "OK",
	"Exception": null
	},
"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_0d017deb-38fa-4701-a7b1-5b6608c79da2"
}

Updating details for list 169642.
Response:
{
	"Id": 169642,
	"Name": "Swimsuits and sports",
	"Description": "A sample list",
	"Metadata": {
		"Key One": "Acceptable",
		"Key Two": "Potentially racy"
	}
}

Getting details for list 169642.
Response:
{
	"Id": 169642,
	"Name": "Swimsuits and sports",
	"Description": "A sample list",
	"Metadata": {
		"Key One": "Acceptable",
		"Key Two": "Potentially racy"
	}
}

Refreshing the search index for list 169642.
Response:
{
	"ContentSourceId": "169642",
	"IsUpdateSuccess": true,
	"AdvancedInfo": [],
	"Status": {
		"Code": 3000,
		"Description": "RefreshIndex successfully completed.",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_c72255cd-55a0-415e-9c18-0b9c08a9f25b"
}
Waiting 0.5 minutes to allow the server time to propagate the index changes.

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample1.jpg against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_ec384878-dbaa-4999-9042-6ac986355967",
	"CacheID": null,
	"IsMatch": true,
	"Matches": [
		{
			"Score": 1.0,
			"MatchId": 169493,
			"Source": "169642",
			"Tags": [],
			"Label": "Swimsuit"
		}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_e9db4b8f-3067-400f-9552-d3e6af2474c0",
	"CacheID": null,
	"IsMatch": true,
	"Matches": [
		{
			"Score": 1.0,
			"MatchId": 169490,
			"Source": "169642",
			"Tags": [],
			"Label": "Sports"
		}
	],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
		}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample5.png against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_25991575-05da-4904-89db-abe88270b403",
	"CacheID": null,
	"IsMatch": false,
	"Matches": [],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_c65d1c91-0d8a-4511-8ac6-814e04adc845",
	"CacheID": null,
	"IsMatch": true,
	"Matches": [
		{
			"Score": 1.0,
			"MatchId": 169495,
			"Source": "169642",
			"Tags": [],
			"Label": "Swimsuit"
		}
		],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Removing entry for https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png (ID = 169495) from list 169642.
Response:
""

Refreshing the search index for list 169642.
Response:
{
	"ContentSourceId": "169642",
	"IsUpdateSuccess": true,
	"AdvancedInfo": [],
	"Status": {
		"Code": 3000,
		"Description": "RefreshIndex successfully completed.",
		"Exception": null
		},
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_b55a375e-30a1-4612-aa7b-81edcee5bffb"
}

Waiting 0.5 minutes to allow the server time to propagate the index changes.

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample1.jpg against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_00544948-2936-489c-98c8-b507b654bff5",
	"CacheID": null,
	"IsMatch": true,
	"Matches": [
		{
			"Score": 1.0,
			"MatchId": 169493,
			"Source": "169642",
			"Tags": [],
			"Label": "Swimsuit"
		}
		],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample4.png against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_c36ec646-53c2-4705-86b2-d72b5c2273c7",
	"CacheID": null,
	"IsMatch": true,
	"Matches": [
		{
			"Score": 1.0,
			"MatchId": 169490,
			"Source": "169642",
			"Tags": [],
			"Label": "Sports"
		}
		],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample5.png against list 169642.
Response:
{
	TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_22edad74-690d-4fbc-b7d0-bf64867c4cb9",
	"CacheID": null,
	"IsMatch": false,
	"Matches": [],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Matching image https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png against list 169642.
Response:
{
	"TrackingId": "WE_f0527c49616243c5ac65e1cc3482d390_ContentModerator.Preview_abd4a178-3238-4601-8e4f-cf9ee66f605a",
	"CacheID": null,
	"IsMatch": false,
	"Matches": [],
	"Status": {
		"Code": 3000,
		"Description": "OK",
		"Exception": null
	}
}

Deleting all images from list 169642.
Response:
"Reset Successful."

Deleting list 169642.
Response:
""

Getting all image list IDs.
Response:
[]

Следующие шаги

Получите пакет SDK Content Moderator для .NET и решение Visual Studio для выполнения инструкций из этого и других кратких руководств по Content Moderator для .NET и приступите к интеграции.