Imagenetから選択したクラスの画像を取得するにはどうすればいいですか? 質問する

Imagenetから選択したクラスの画像を取得するにはどうすればいいですか? 質問する

背景

Deep Dream私はとを試しInceptionism、フレームワークを使用しCaffeて のレイヤーを視覚化してきました。 は、プロジェクトGoogLeNet用に構築されたアーキテクチャでありImagenet、視覚的な物体認識で使用するために設計された大規模な視覚データベースです。

こちらからご覧いただけますImagenet:Imagenet 1000 クラス。


アーキテクチャを調査して「夢」を生み出すために、私は 3 つのノートブックを使用しています。

  1. https://github.com/google/deepdream/blob/master/dream.ipynb

  2. https://github.com/kylemcdonald/deepdream/blob/master/dream.ipynb

  3. https://github.com/auduno/deepdraw/blob/master/deepdraw.ipynb


ここでの基本的な考え方は、モデルまたは「ガイド」画像から指定されたレイヤーの各チャネルからいくつかの特徴を抽出することです。

次に、変更したい画像をモデルに入力し、指定された同じレイヤー内の特徴(オクターブごと)を抽出して、最も一致する特徴、つまり 2 つの特徴ベクトルの最大ドット積を強化します。


これまで、私は以下のアプローチを使用して入力画像を変更し、夢を制御することができました。

  • (a)'end'入力画像の最適化の目的としてレイヤーを適用する。(参照:機能の視覚化
  • (b) 2番目の画像を使用して入力画像の最適化目標を導く。
  • (c)Googlenetノイズから生成されたモデルクラスを視覚化する。

しかし、私が達成したい効果はこれらのテクニックの中間に位置しますが、それに関するドキュメント、論文、コードは見つかりませんでした。

望ましい結果(回答すべき質問の一部ではありません)

特定のレイヤーに属する単一のクラスまたはユニット(a) が最適化目標 (b) を導き、このクラスが入力画像上で視覚化 (c) されるようにするには'end'、次の手順を実行します。

class = 'face'およびの例input_image = 'clouds.jpg':

ここに画像の説明を入力してください 注意: 上記の画像は、Imagenetデータセットでトレーニングされていない顔認識モデルを使用して生成されました。デモンストレーションのみを目的としています。


動作コード

アプローチ(a)

from cStringIO import StringIO
import numpy as np
import scipy.ndimage as nd
import PIL.Image
from IPython.display import clear_output, Image, display
from google.protobuf import text_format
import matplotlib as plt    
import caffe
         
model_name = 'GoogLeNet' 
model_path = 'models/dream/bvlc_googlenet/' # substitute your path here
net_fn   = model_path + 'deploy.prototxt'
param_fn = model_path + 'bvlc_googlenet.caffemodel'
   
model = caffe.io.caffe_pb2.NetParameter()
text_format.Merge(open(net_fn).read(), model)
model.force_backward = True
open('models/dream/bvlc_googlenet/tmp.prototxt', 'w').write(str(model))
    
net = caffe.Classifier('models/dream/bvlc_googlenet/tmp.prototxt', param_fn,
                       mean = np.float32([104.0, 116.0, 122.0]), # ImageNet mean, training set dependent
                       channel_swap = (2,1,0)) # the reference model has channels in BGR order instead of RGB

def showarray(a, fmt='jpeg'):
    a = np.uint8(np.clip(a, 0, 255))
    f = StringIO()
    PIL.Image.fromarray(a).save(f, fmt)
    display(Image(data=f.getvalue()))
  
# a couple of utility functions for converting to and from Caffe's input image layout
def preprocess(net, img):
    return np.float32(np.rollaxis(img, 2)[::-1]) - net.transformer.mean['data']
def deprocess(net, img):
    return np.dstack((img + net.transformer.mean['data'])[::-1])
      
def objective_L2(dst):
    dst.diff[:] = dst.data 

def make_step(net, step_size=1.5, end='inception_4c/output', 
              jitter=32, clip=True, objective=objective_L2):
    '''Basic gradient ascent step.'''

    src = net.blobs['data'] # input image is stored in Net's 'data' blob
    dst = net.blobs[end]

    ox, oy = np.random.randint(-jitter, jitter+1, 2)
    src.data[0] = np.roll(np.roll(src.data[0], ox, -1), oy, -2) # apply jitter shift
            
    net.forward(end=end)
    objective(dst)  # specify the optimization objective
    net.backward(start=end)
    g = src.diff[0]
    # apply normalized ascent step to the input image
    src.data[:] += step_size/np.abs(g).mean() * g

    src.data[0] = np.roll(np.roll(src.data[0], -ox, -1), -oy, -2) # unshift image
            
    if clip:
        bias = net.transformer.mean['data']
        src.data[:] = np.clip(src.data, -bias, 255-bias)

 
def deepdream(net, base_img, iter_n=20, octave_n=4, octave_scale=1.4, 
              end='inception_4c/output', clip=True, **step_params):
    # prepare base images for all octaves
    octaves = [preprocess(net, base_img)]
    
    for i in xrange(octave_n-1):
        octaves.append(nd.zoom(octaves[-1], (1, 1.0/octave_scale,1.0/octave_scale), order=1))
    
    src = net.blobs['data']
    
    detail = np.zeros_like(octaves[-1]) # allocate image for network-produced details
    
    for octave, octave_base in enumerate(octaves[::-1]):
        h, w = octave_base.shape[-2:]
        
        if octave > 0:
            # upscale details from the previous octave
            h1, w1 = detail.shape[-2:]
            detail = nd.zoom(detail, (1, 1.0*h/h1,1.0*w/w1), order=1)

        src.reshape(1,3,h,w) # resize the network's input image size
        src.data[0] = octave_base+detail
        
        for i in xrange(iter_n):
            make_step(net, end=end, clip=clip, **step_params)
            
            # visualization
            vis = deprocess(net, src.data[0])
            
            if not clip: # adjust image contrast if clipping is disabled
                vis = vis*(255.0/np.percentile(vis, 99.98))
            showarray(vis)

            print octave, i, end, vis.shape
            clear_output(wait=True)
            
        # extract details produced on the current octave
        detail = src.data[0]-octave_base
    # returning the resulting image
    return deprocess(net, src.data[0])

上記のコードを次のように実行します:

end = 'inception_4c/output'
img = np.float32(PIL.Image.open('clouds.jpg'))
_=deepdream(net, img)

アプローチ(b)

"""
Use one single image to guide 
the optimization process.

This affects the style of generated images 
without using a different training set.
"""

def dream_control_by_image(optimization_objective, end):
    # this image will shape input img
    guide = np.float32(PIL.Image.open(optimization_objective))  
    showarray(guide)
  
    h, w = guide.shape[:2]
    src, dst = net.blobs['data'], net.blobs[end]
    src.reshape(1,3,h,w)
    src.data[0] = preprocess(net, guide)
    net.forward(end=end)

    guide_features = dst.data[0].copy()
    
    def objective_guide(dst):
        x = dst.data[0].copy()
        y = guide_features
        ch = x.shape[0]
        x = x.reshape(ch,-1)
        y = y.reshape(ch,-1)
        A = x.T.dot(y) # compute the matrix of dot-products with guide features
        dst.diff[0].reshape(ch,-1)[:] = y[:,A.argmax(1)] # select ones that match best

    _=deepdream(net, img, end=end, objective=objective_guide)

上記のコードを次のように実行します:

end = 'inception_4c/output'
# image to be modified
img = np.float32(PIL.Image.open('img/clouds.jpg'))
guide_image = 'img/guide.jpg'
dream_control_by_image(guide_image, end)

質問

ここで、個々のクラスにアクセスしようとして、クラスのマトリックスをホット エンコードし、1 つに焦点を合わせようとした失敗したアプローチを示します (これまでのところ、効果はありません)。

def objective_class(dst, class=50):
   # according to imagenet classes 
   #50: 'American alligator, Alligator mississipiensis',
   one_hot = np.zeros_like(dst.data)
   one_hot.flat[class] = 1.
   dst.diff[:] = one_hot.flat[class]

明確にするために言うと、質問は、興味深い背景であり、すでに機能しているコードであるドリーム コードに関するものではなく、この最後の段落の質問についてのみです。ImageNetから選択したクラス (クラス を取る)の画像を取得する方法#50: 'American alligator, Alligator mississipiensis'(クラウド イメージと一緒に入力として使用してドリーム イメージを作成できるようにするため) を教えていただけませんか。

ベストアンサー1

問題は、#50: 'American alligator, Alligator mississipiensis'ImageNet から選択したクラスの画像を取得する方法です。

  1. へ移動https://www.image-net.org/

  2. へ移動ダウンロード

202303: このガイドは古くなっています。

ウェブサイトが変更されたため、次の手順のようにダウンロードできなくなりました。現在は次のようになっています:

ここに画像の説明を入力してください

ImageNetで最もよく使われるサブセットはImageNet 大規模視覚認識チャレンジ (ILSVRC)2012-2017年の画像分類と位置特定データセット。このデータセットは1000のオブジェクトクラスにまたがり、1,281,167枚のトレーニング画像、50,000枚の検証画像、100,000枚のテスト画像が含まれています。このサブセットは以下から入手できます。カグル

ImageNet データセット全体とその他のよく使用されるサブセットにアクセスするには、ログインするかアクセスをリクエストしてください。その際には、アクセス規約に同意する必要があります。

以下の手順は古くなっています。Web サイトが変更されました。

  1. 「画像 URL のダウンロード」の手順に従ってください。

ここに画像の説明を入力してください

ブラウザから synset の URL をダウンロードするにはどうすればいいですか?

1. Type a query in the Search box and click "Search" button

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ワニは表示されません。ImageNet is under maintenance. Only ILSVRC synsets are included in the search results.問題ありません。この検索は WordNet ツリーマップの正しいブランチに到達することを目的としているため、類似の動物「ワニトカゲ」で問題ありません。メンテナンスが行われなかったとしても、ここで直接 ImageNet 画像を取得できるかどうかはわかりません。

2. Open a synset papge

ここに画像の説明を入力してください

下にスクロールします:

ここに画像の説明を入力してください

下にスクロールします:

ここに画像の説明を入力してください

近隣の動物として、同じくトカゲ目双弓類爬虫類であるアメリカアリゲーターを探す:

ここに画像の説明を入力してください

3. You will find the "Download URLs" button under the left-bottom corner of the image browsing window.

ここに画像の説明を入力してください

選択したクラスのすべての URL が取得されます。ブラウザにテキスト ファイルがポップアップ表示されます。

http://image-net.org/api/text/imagenet.synset.geturls?wnid=n01698640

ここで、URL の末尾に配置する必要がある正しい WordNet ID を知ることが重要であることがわかります。

手動画像ダウンロード

テキスト ファイルは次のようになります。

ここに画像の説明を入力してください

たとえば、最初の URL は次の URL にリンクします。

ここに画像の説明を入力してください

2 番目はリンク切れです:

ここに画像の説明を入力してください

3 番目のリンクは無効ですが、4 番目のリンクは機能しています。

ここに画像の説明を入力してください

これらの URL の画像は公開されていますが、多くのリンクは無効であり、画像の解像度も低くなっています。

自動画像ダウンロード

再び ImageNet ガイドから引用します:

HTTP プロトコルでダウンロードするには? HTTP リクエストで synset をダウンロードするには、まず synset の「WordNet ID」(wnid) を取得する必要があります。エクスプローラーを使用して synset を参照する場合、画像ウィンドウの下に WordNet ID が表示されます。(ここをクリックして「Synset WordNet ID」を検索すると、「Dog, domestic dog, Canis familiaris」synset の wnid が表示されます)。「WordNet ID」の詳細については、次を参照してください。

Mapping between ImageNet and WordNet

synsetのwnidがわかれば、その画像のURLは次の場所で取得できる。

http://www.image-net.org/api/text/imagenet.synset.geturls?wnid=[wnid]

wnid を指定して下位語の synset を取得することもできます。詳細については、API ドキュメントを参照してください。

それで、そこには何があるのでしょうかAPIドキュメント?

すべての WordNet ID (いわゆる「synset ID」) とすべての synset の単語を取得するために必要なものがすべて揃っています。つまり、任意のクラス名とその WordNet ID が無料で手に入ります。

シノセットの単語を取得する

synsetのwnidが与えられると、synsetの単語は次の式で得られる。

http://www.image-net.org/api/text/wordnet.synset.getwords?wnid=[wnid]

あなたもすることができますここをクリックすべてのシノニムセットのWordNet IDと単語間のマッピングをダウンロードするには、ここをクリックすべてのシノニムセットの WordNet ID と用語間のマッピングをダウンロードします。

選択したWordNet IDとそのクラス名がわかっている場合は、「nltk」(自然言語ツールキット)のnltk.corpus.wordnetを使用できます。WordNetインターフェース

今回の場合、必要なのはクラスの画像だけです#50: 'American alligator, Alligator mississipiensis'。必要なものはすでにわかっているので、nltk.corpus.wordnet は無視できます (詳細についてはチュートリアルまたは Stack Exchange の質問を参照してください)。まだ有効な URL をループすることで、すべてのワニの画像のダウンロードを自動化できます。もちろん、すべての WordNet ID をループすることで、これを完全な WordNet に拡張することもできますが、これではツリーマップ全体に時間がかかりすぎます。また、毎日何千人もの人がダウンロードすると画像がなくなるため、お勧めできません。

残念ながら、ImageNet クラス番号「#50」を引数として受け入れるこの Python コードを書く時間はないと思いますが、WordNet から ImageNet へのマッピング テーブルを使用すれば、これも可能になるはずです。クラス名と WordNet ID があれば十分でしょう。

単一の WordNet ID の場合、コードは次のようになります。

import urllib.request 
import csv

wnid = "n01698640"
url = "http://image-net.org/api/text/imagenet.synset.geturls?wnid=" + str(wnid)

# From https://stackoverflow.com/a/45358832/6064933
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
with open(wnid + ".csv", "wb") as f:
    with urllib.request.urlopen(req) as r:
        f.write(r.read())

with open(wnid + ".csv", "r") as f:
    counter = 1
    for line in f.readlines():      
        print(line.strip("\n"))
        failed = []
        try:
            with urllib.request.urlopen(line) as r2:
                with open(f'''{wnid}_{counter:05}.jpg''', "wb") as f2:
                    f2.write(r2.read())
        except:
            failed.append(f'''{counter:05}, {line}'''.strip("\n"))
        counter += 1
        if counter == 10:
            break

with open(wnid + "_failed.csv", "w", newline="") as f3:
    writer = csv.writer(f3)
    writer.writerow(failed)

結果:

ここに画像の説明を入力してください

  1. リンク切れや元の品質の画像が必要で、プロジェクトが非営利である場合は、サインインして「画像のコピーを入手するにはどうすればいいですか?」を参照してください。ダウンロードに関するFAQ
  • 上記の URL では、wnid=n01698640URL の末尾に、ImageNet にマップされている WordNet ID が表示されます。
  • または、「Synset の画像」タブで、「Wordnet ID」をクリックします。

ここに画像の説明を入力してください

アクセス方法:

ここに画像の説明を入力してください

または右クリックして名前を付けて保存:

ここに画像の説明を入力してください

WordNet ID を使用して元の画像を取得できます。

ここに画像の説明を入力してください

商用の場合は、ImageNet チームに問い合わせることをお勧めします。


アドオン

コメントのアイデアを取り入れる: たくさんの画像ではなく、クラスをできるだけよく表す「単一のクラス画像」だけが必要な場合は、以下を参照してください。GoogLeNet クラスの視覚化代わりに、このメソッドを ImageNet の画像で使用してみます。これも deepdream コードを使用しています。

GoogLeNet クラスの視覚化

  1. 2015年7月

ディープ ニューラル ネットワークがダルメシアンの見た目をどう考えているか考えたことがありますか? もう疑問に思う必要はありません。

最近Google投稿を公開しましたディープ ニューラル ネットワークを使用してクラスの視覚化を生成し、いわゆる「インセプション主義」メソッドを使用して画像を変更する方法について説明しています。その後、インセプション主義メソッドを使用して画像を変更するためのコードを公開しましたが、同じ投稿で示すクラスの視覚化を生成するコードは公開しませんでした。

Googleがクラスの視覚化をどのように生成したのか正確にはわかりませんでしたが、ディープドリームコードこのiPythonノートブックカイル・マクドナルドから、私はGoogLeNetにこれらを描くように指導することができました:

ここに画像の説明を入力してください

... [他にもたくさんのサンプル画像が続きます]

おすすめ記事