画像検索をノーコーディングでつくるよ！Azure Cognitive Search入門とコグニティブ(AI)スキル拡張

# 概要

「画像検索をつくりたい！」

というわけで、AzureにあるCognitive Searchというサービスを触ってみました。
そして私が全文検索初心者なので、ツッコミどころも多いかと思います。ご容赦。

# Azure Cognitive Searchとは

いわゆる「全文検索サーバ」にあたります。
ElasticsearchやApache Solrと同じ立ち位置（という理解）です。
*ドキュメントを読んでいると、Luceneがベースのようです。*


[参考]
下記記事では全文検索ライブラリ、サーバの種類や関係性が整理されています。
https://toranoana-lab.hatenablog.com/entry/2019/02/06/103709

Cognitive Searchにはこんなダッシュボードがついてきますよ。素敵。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124249/eee26ffd-1cca-d537-bb8b-7c64c36f85c1.png)



### 全文検索とは

文書の内容の中から、指定した文字列を検索すること（という理解）です。


# 「検索」×「AI」─ Cognitive Searchの特徴

注目すべき特徴は、Azure Cognitive Servicesとの連携ができることです。
Blob Storageに配置した、画像やテキスト（PDF等も含）データを、**AIによって解析し検索可能**にしてくれます。

Cognitive Searchのなかでは、この機能を「コグニティブスキル」と呼んでいます。

### Cognitive Servicesとは

Microsoftが用意した学習済みのつよつよAIを使って、画像認識やテキスト解析を行えるサービスです。
https://azure.microsoft.com/ja-jp/services/cognitive-services/


# いざCognitive Search入門

今回の記事では

- Cognitive Searchの作成
- コグニティブスキルの追加
- 検索

までをやってみます。

Cognitive Searchには無料プランがあります。
1サブスクリプションに、1個の無料プランが作成可能です。今回はお試しなので、無料プランでいきましょう。
無料プランでも、コグニティブスキルは試せます。:+1:

無料プランでは、「インデックス」「データソース」「インデクサー」がそれぞれ3つずつ作成できます。
なんか聞いたことない概念出てきました。
それぞれ（私の理解で）解説しますね。

### 「インデックス」
検索用に作れられる索引です。（まんまですが）
索引があることで検索が圧倒的に早くなります。
本も目次があるからこそ、たどりつきたい内容に素早くたどり着くことができますよね。

### 「データソース」
索引のもとになる元データ置き場のことです。
これにはBlob StorageやAzure SQL Databaseなどが指定できます。
本でいうと、本編・コンテンツが書かれたページたちですね。

### 「インデクサー」
索引を作る機能です。
本で例えると、作者がコンテンツを書き終えた後に、ページ番号を数えて「この章は12ページから、この章は46ページから...」とまとめていく作業のイメージです。
　

今回は「データソース」に、Blob Storageを。
「インデクサー」ではコグニティブスキルを使用し、画像認識した結果の「インデックス」を作成します。
この3つが揃って、AIによる画像検索が実現します。

（Blob Storageって何かって？ もう！AWSでいうS3ですわよ奥さん！）


# いざコグニティブスキル発動

リソース作成ができたら、コグニティブスキルを試してみましょう。
公式のチュートリアルを参考にポチポチとやっていきましょう。（雑）
https://docs.microsoft.com/ja-jp/azure/search/cognitive-search-quickstart-blob

私は画像認識だけ使いたかったので、下記のようにチェックを入れました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124249/56489a7f-ce83-19ef-6e7e-d303f3009903.png)

インデクサーには、インデックス頻度を指定できます。
スケジューリングしておけば、あとはBlobに画像を上げてくだけでよさそうです。すごい。 :clap: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124249/4cc57d93-db48-bf81-3b6c-4691c031efbd.png)


### Blob Storageについてチョト補足

*全体の流れは公式チュートリアルにおまかせするとして、チュートリアルに書いてないことを補足してゆきますね*

事前にストレージアカウントとコンテナーを作成しておく必要があります。
チョトわかりづらいので、はじめての方にもわかりやすいよう補足します。

手順ですが、ストレージアカウントをつくってから、コンテナーをつくります。
ややこしいのですが、「コンテナー」というのが、今回つかう「Blob Storage」のことです。

階層としては下記のようになっています

- ストレージアカウント
  - コンテナー（Blob Storage）

コンテナーをつくったらお目当てのファイルがアップロードできます。わーい。:clap:

*ストレージアカウントの下には、BlobのほかにTableストレージやQueueストレージなども作れます。*

#### 接続情報

アプリケーションから、Blob Storageに接続するには「接続文字列」を使用します。
これはストレージアカウントの単位で用意されています。

ナビゲーションから「アクセスキー」を開き、「接続文字列」を控えておきましょう。
Cognitive Searchでつくるインデクサーでも必要になります。


# 検索してみよう

~~私もまだ構文理解しきれてないんですけども、~~人が写っている画像を検索してみます。
「インデックス」から該当インデックスを選択すると「検索エクスプローラー」が開きます。

「クエリ文字列」に下記を入力し、検索します。

```
search=imageTags:("person")&$select=imageTags,metadata_storage_path
```

これは

- `imageTags`（画像認識結果）に、personを含むものを検索
- 結果には `imageTags` と `metadata_storage_path` のフィールドを表示して

という内容です。
`metadata_storage_path` がBlob Storage上のURLになります。

[参考]
クエリ構文のドキュメントは下記
https://docs.microsoft.com/ja-jp/azure/search/query-lucene-syntax


## いざ実行！

```
{
    "@odata.context": "https://XXXXXXX.search.windows.net/indexes('azureblob-index')/$metadata#docs(*)",
    "value": [
        {
            "@search.score": 0.0645925,
            "metadata_storage_path": "XXXXXXXXXXXXXXXXXX...c0LmNsaXBfaW1hZ2UwMDJfNkZFMjdFODUucG5n0",
            "imageTags": [
                "person",
                "man",
                "wall",
                "indoor",
                "standing",
                "human face",
                "clothing"
            ]
        },
        {
            "@search.score": 0.0645925,
            "metadata_storage_path": "XXXXXXXXXXXXXXXXXX...b3dzLm5ldC9teWNvbnRhaW5lci9ndXRocmllLmpwZw2",
            "imageTags": [
                "person",
                "man",
                "human face",
                "clothing",
                "shirt",
                "indoor",
                "glasses"
            ]
        },
        { ...
```

でたー！
確かにpersonを含むものがヒットしてますね！

**あれ、なんですか。このわけわからん文字列は！**
**画像を検索したいのに、画像に辿りつけてないじゃないか！**
`"metadata_storage_path": "XXXXXXXXXXXXXXXXXX...c0LmNsaXBfaW1hZ2UwMDJfNkZFMjdFODUucG5n0",`

と、私も焦ったのですが、
じつは、これはBlobにアップされたファイルのURLで、base64エンコードされているものなのです。
なので、適当な方法でデコードしてあげます。

すると下記のようにURLに戻ります。
`https://XXXXXXX.blob.core.windows.net/mycontainer/5074.clip_image002_6FE27E85.png`

*※エンコードしている理由は、キー名に記号を含めることができないからのようです。
インデクサーの作成画面で、じつはチェックマークがついていました。*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124249/05f4f181-92b1-0d71-3a8a-9b964a9dfd48.png)

## 画像だ！はやく画像を見せてくれ！

こちらがヒットして出てきた画像です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124249/f1269ae5-97d1-bb07-3672-5d4417c026a2.png)

ちゃんと人が写った画像ですね。やった！ :clap: 
*※今回つかったのは、チュートリアルにあったサンプル画像です*


# ノーコディーングで画像検索がつくれた！ ただし結果は英語...

知識が必要だったりしたものの、なんとここまでノーコーディングでした。すごい！ :clap: 

ただし、結果は英語で出力されているので、そこは日本人からすると不便ですね。
検索クエリにする前に、翻訳をかませるなどの工夫が必要そうです。
（Cognitive Services自体のアップデートにも期待したいです！）

[余談]
私は日本語で検索をしたいので、日本語WordNetやアレやコレやをつかってAI画像検索をつくろうと思っています。
その話はまたいつか。

それではまたー。