.NET SDKを使ってImage Searchの類似検索を試す【検索編】

#はじめに
そろそろ .NET を触ってみようと思い急遽Image Searchの検索処理を.NET で書いてみました。

# 今回の目的（.NET SDKを使って検索してみる）
前回、Image Searchの設定と画像取り込みまで終わりました。今回は、前回作ったImage Searchにプログラムでアクセスしてみようと思います。

## 実装環境の構築

``` dotnetインストール
PS C:\Users\user> scoop install dotnet-sdk
Installing 'dotnet-sdk' (3.1.201) [64bit]
dotnet-sdk-3.1.201-win-x64.zip (153.4 MB) [===================================================================] 100%
Checking hash of dotnet-sdk-3.1.201-win-x64.zip ... ok.
Extracting dotnet-sdk-3.1.201-win-x64.zip ... done.
Linking ~\scoop\apps\dotnet-sdk\current => ~\scoop\apps\dotnet-sdk\3.1.201
Creating shim for 'dotnet'.
'dotnet-sdk' (3.1.201) was installed successfully!
'dotnet-sdk' suggests installing 'extras/vcredist2019'.
```

## .net プロジェクトの作成

```
PS C:\Users\user\Documents> dotnet new console -o dotnet-sample
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on dotnet-sample\dotnet-sample.csproj...
  C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj の復元が 195.88 ms で完了しました。

Restore succeeded.

```

プロジェクト階層

``` 
PS C:\Users\user\Documents\dotnet-sample> tree /F
フォルダー パスの一覧:  ボリューム Windows
ボリューム シリアル番号は 9411-0B65 です
C:.
│  dotnet-sample.csproj
│  Program.cs
│
└─obj
       dotnet-sample.csproj.nuget.dgspec.json
       dotnet-sample.csproj.nuget.g.props
       dotnet-sample.csproj.nuget.g.targets
       project.assets.json
       project.nuget.cache

PS C:\Users\user\Documents\dotnet-sample>
```

### 依存関係の追加
Alibaba CloudのSDKを追加します。

``` 
PS C:\Users\user\Documents\dotnet-sample> dotnet add package aliyun-net-sdk-core
  Writing C:\Users\user\AppData\Local\Temp\tmpF02D.tmp
info : パッケージ 'aliyun-net-sdk-core' の PackageReference をプロジェクト 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' に追加しています。
info : C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj のパッケージを復元しています...
info :   GET https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-core/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-core/index.json 653 ミリ秒
info :   GET https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-core/1.5.6/aliyun-net-sdk-core.1.5.6.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-core/1.5.6/aliyun-net-sdk-core.1.5.6.nupkg 655 ミリ秒
info : aliyun-net-sdk-core 1.5.6 をインストールしています。
info : パッケージ 'aliyun-net-sdk-core' は、プロジェクト 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' のすべての指定されたフレームワークとの互換性があります。
info : ファイル 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' に追加されたパッケージ 'aliyun-net-sdk-core' バージョン '1.5.6' の PackageReference。
info : 復元をコミットしています...
info : アセット ファイルをディスクに書き込んでいます。パス: C:\Users\user\Documents\dotnet-sample\obj\project.assets.json
log  : C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj の復元が 3.07 sec で完了しました。
```

```
PS C:\Users\user\Documents\dotnet-sample> dotnet add package aliyun-net-sdk-imagesearch
  Writing C:\Users\user\AppData\Local\Temp\tmp30DF.tmp
info : パッケージ 'aliyun-net-sdk-imagesearch' の PackageReference をプロジェクト 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' に追加しています。
info : C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj のパッケージを復元しています...
info :   GET https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-imagesearch/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-imagesearch/index.json 853 ミリ秒
info :   GET https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-imagesearch/2.0.0/aliyun-net-sdk-imagesearch.2.0.0.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/aliyun-net-sdk-imagesearch/2.0.0/aliyun-net-sdk-imagesearch.2.0.0.nupkg 753 ミリ秒
info : aliyun-net-sdk-imagesearch 2.0.0 をインストールしています。
info : パッケージ 'aliyun-net-sdk-imagesearch' は、プロジェクト 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' のすべての指定されたフレームワークとの互換性があります。
info : ファイル 'C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj' に追加されたパッケージ 'aliyun-net-sdk-imagesearch' バージョン '2.0.0' の PackageReference。
info : 復元をコミットしています...
info : アセット ファイルをディスクに書き込んでいます。パス: C:\Users\user\Documents\dotnet-sample\obj\project.assets.json
log  : C:\Users\user\Documents\dotnet-sample\dotnet-sample.csproj の復元が 2 sec で完了しました。
```


### 前回作成したImage Searchにアクセスする

アクセスキーとシークレットキーは前回作成したものを使用します。
また、リージョンとエンドポイントについては、以下の表から設定します。今回は日本（東京）を設定します。

| リージョン | エンドポイント |
|:-:|:-:|
| シンガポール  | imagesearch.ap-southeast-1.aliyuncs.com  |
| 中国 (香港)  | imagesearch.cn-hongkong.aliyuncs.com  |
| 日本 (東京)  | imagesearch.ap-northeast-1.aliyuncs.com  |
| オーストラリア (シドニー)  | imagesearch.ap-southeast-2.aliyuncs.com  |

``` Program.cs
using System;
using System.Collections.Generic;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.ImageSearch.Model.V20190325;

namespace dotnet_sample
{
    class Program
    {
        public const String ACCESS_KEY = "XXXXXXXXXXXXXXXX";
        public const String SEACRET_KEY= "YYYYYYYYYYYYYYY";
        static void Main(string[] args)
        {
            IClientProfile profile = DefaultProfile.GetProfile("ap-northeast-1", ACCESS_KEY, SEACRET_KEY);
            profile.AddEndpoint("ap-northeast-1", "ap-northeast-1", "ImageSearch", "imagesearch.ap-northeast-1.aliyuncs.com");
            IAcsClient client = new DefaultAcsClient(profile);

             // 画像の検索
            SearchImageRequest searchRequest = new SearchImageRequest();
            searchRequest.InstanceName = "itemsearch";
            searchRequest.Type = "SearchByPic";
            byte[] img = System.IO.File.ReadAllBytes("search01.jpg");
            string pic = Convert.ToBase64String(img);

            searchRequest.PicContent = pic;
            SearchImageResponse searchResponse = client.GetAcsResponse(searchRequest);

            SearchImageResponse.SearchImage_PicInfo picInfo = searchResponse.PicInfo;
            int? categoryId = picInfo.CategoryId;
            string region = picInfo.Region;
            List<SearchImageResponse.SearchImage_PicInfo.SearchImage_Category> allCategories = picInfo.AllCategories;
            Console.WriteLine("picInfo:");
            Console.WriteLine("\tcategoryId: {0}\n\tregion: {1}",categoryId,region);
            allCategories.ForEach(item => {
                Console.WriteLine("\tid:{0}, name:{1}",item.Id,item.Name);
            });

            SearchImageResponse.SearchImage_Head head = searchResponse.Head;
            int? docsFound = head.DocsFound;
            int? docsReturn = head.DocsReturn;
            int? searchTime = head.SearchTime;
            Console.WriteLine("Head:");
            Console.WriteLine("\tdocsFound: {0}\n\tdocsReturn: {1}\n\tsearchTime: {2}",docsFound,docsReturn,searchTime);

            string requestId = searchResponse.RequestId;
            int? code = searchResponse.Code;
            string msg = searchResponse.Msg;
            bool? success = searchResponse.Success;
            Console.WriteLine("requestId: {0}\ncode: {1}\nmsg: {2}\nsuccess:{3}",requestId,code,msg,success);

            List<SearchImageResponse.SearchImage_Auction> auctions = searchResponse.Auctions;
            Console.WriteLine("Auctions:");
            auctions.ForEach(item =>{
                int? categoryId1 = item.CategoryId;
                string customContent = item.CustomContent;
                int? intAttr = item.IntAttr;
                string picName = item.PicName;
                string productId = item.ProductId;
                string sortExprValues = item.SortExprValues;
                string strAttr = item.StrAttr;
                Console.WriteLine("\tcategoryId1: {0}\n\tcustomContent: {1}\n\tintAttr: {2}\n\tpicName: {3}\n\tproductId: {4}\n\tsortExprValues: {5}\n\tstrAttr: {6}",categoryId1,customContent,intAttr,picName,productId,sortExprValues,strAttr);
                Console.WriteLine("\t-------------");
            });
            
            
        }
    }
}

```

```
picInfo:
	categoryId: 9
	region: 140,474,36,578
	id:0, name:Tops
	id:1, name:Dress
	id:2, name:Bottoms
	id:3, name:Bag
	id:4, name:Shoes
	id:5, name:Accessories
	id:6, name:Snack
	id:7, name:Makeup
	id:8, name:Bottle
	id:9, name:Furniture
	id:20, name:Toy
	id:21, name:Underwear
	id:22, name:Digital device
	id:88888888, name:Other
Head:
	docsFound: 11
	docsReturn: 10
	searchTime: 108
requestId: 1452E527-8879-46FA-A7D6-158B5BDCCE18
code: 0
msg: success
success:True
Auctions:
	categoryId1: 9
	customContent: k1:v12,k2:v211,k3:v311
	intAttr:
	picName: 12.jpg
	productId: 1011
	sortExprValues: 3.07306838035583;217
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v11,k2:v210,k3:v310
	intAttr:
	picName: 11.jpg
	productId: 1010
	sortExprValues: 2.97270393371582;222
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v09,k2:v208,k3:v308
	intAttr:
	picName: 09.jpg
	productId: 1008
	sortExprValues: 2.87724995613098;238
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v10,k2:v209,k3:v309
	intAttr:
	picName: 10.jpg
	productId: 1009
	sortExprValues: 2.79507827758789;235
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v02,k2:v201,k3:v301
	intAttr:
	picName: 02.jpg
	productId: 1001
	sortExprValues: 2.67687916755676;251
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v05,k2:v204,k3:v304
	intAttr:
	picName: 05.jpg
	productId: 1004
	sortExprValues: 2.67470407485962;249
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v06,k2:v205,k3:v305
	intAttr:
	picName: 06.jpg
	productId: 1005
	sortExprValues: 2.66586232185364;254
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v04,k2:v203,k3:v303
	intAttr:
	picName: 04.jpg
	productId: 1003
	sortExprValues: 2.63756942749023;255
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v01,k2:v200,k3:v300
	intAttr:
	picName: 01.jpg
	productId: 1000
	sortExprValues: 2.57631182670593;270
	strAttr:
	-------------
	categoryId1: 9
	customContent: k1:v07,k2:v206,k3:v306
	intAttr:
	picName: 07.jpg
	productId: 1006
	sortExprValues: 2.52564144134521;253
	strAttr:
	-------------

```

C#で記述してみました。今回はここまで。dotnetコマンドでプロジェクト作成から実行までできるんですね。
プログラムの実行には以下のコマンドで実行できます。.NET も便利になったもんだ。

```
PS C:\Users\user\Documents\dotnet-sample> dotnet run
picInfo:
        categoryId: 9
        region: 140,474,36,578
        id:0, name:Tops
        id:1, name:Dress
        id:2, name:Bottoms
        id:3, name:Bag
        id:4, name:Shoes
        id:5, name:Accessories
        id:6, name:Snack
        id:7, name:Makeup
        id:8, name:Bottle
        id:9, name:Furniture
        id:20, name:Toy
        id:21, name:Underwear
        id:22, name:Digital device
        id:88888888, name:Other
Head:
        docsFound: 11
        docsReturn: 10
        searchTime: 105
requestId: 30D74625-56D8-432F-8D58-ED0066157CB6
code: 0
msg: success
success:True
Auctions:
        categoryId1: 9
        customContent: k1:v12,k2:v211,k3:v311
        intAttr:
        picName: 12.jpg
        productId: 1011
        sortExprValues: 3.07306838035583;217
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v11,k2:v210,k3:v310
        intAttr:
        picName: 11.jpg
        productId: 1010
        sortExprValues: 2.97270393371582;222
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v09,k2:v208,k3:v308
        intAttr:
        picName: 09.jpg
        productId: 1008
        sortExprValues: 2.87724995613098;238
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v10,k2:v209,k3:v309
        intAttr:
        picName: 10.jpg
        productId: 1009
        sortExprValues: 2.79507827758789;235
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v02,k2:v201,k3:v301
        intAttr:
        picName: 02.jpg
        productId: 1001
        sortExprValues: 2.67687916755676;251
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v05,k2:v204,k3:v304
        intAttr:
        picName: 05.jpg
        productId: 1004
        sortExprValues: 2.67470407485962;249
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v06,k2:v205,k3:v305
        intAttr:
        picName: 06.jpg
        productId: 1005
        sortExprValues: 2.66586232185364;254
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v04,k2:v203,k3:v303
        intAttr:
        picName: 04.jpg
        productId: 1003
        sortExprValues: 2.63756942749023;255
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v01,k2:v200,k3:v300
        intAttr:
        picName: 01.jpg
        productId: 1000
        sortExprValues: 2.57631182670593;270
        strAttr:
        -------------
        categoryId1: 9
        customContent: k1:v07,k2:v206,k3:v306
        intAttr:
        picName: 07.jpg
        productId: 1006
        sortExprValues: 2.52564144134521;253
        strAttr:
        -------------
PS C:\Users\user\Documents\dotnet-sample>
```