如何从Imagenet获得选定的类图像?

背景

我一直在玩Deep DreamInceptionism,使用Caffe框架来可视化GoogLeNet的层,这是为Imagenet项目构建的体系结构,是一个用于视觉对象识别的大型可视化数据库。

你可以在这里找到Imagenet: Imagenet 1000类。


为了探索建筑并产生“梦想”,我使用了三本笔记本:

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

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

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


这里的基本思想是从模型或“指南”图像中指定层的每个通道中提取一些特征。

然后,我们输入一张我们想要修改的图像到模型中,并提取指定的同一层(每个八度)中的特征, 增强最佳匹配特征,即两个特征向量的最大点积。


到目前为止,我已经设法修改输入图像和控制梦境使用以下方法:

  • (a)将图层作为'end'目标用于输入图像优化。(参见特征可视化)
  • (b)使用第二图像对输入图像指导优化目标。
  • (c)可视化由噪声生成的Googlenet模型类

然而,我想要达到的效果介于这些技术之间,我还没有找到任何文档、论文或代码。

想要的结果(不是待回答问题的一部分)

要让属于给定'end'层的单个类或单元 (a)引导优化目标(b),并在输入图像上可视化(c)这个类:

class = 'face'input_image = 'clouds.jpg'的例子:

enter image description here 请注意:上图是使用人脸识别模型生成的,该模型没有在Imagenet数据集上进行训练。


工作代码

方法(一)

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)

问题

现在,失败的方法是如何I 尝试访问单个类,热编码类矩阵并专注于一个(到目前为止徒劳无益):

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')的图像吗(这样我就可以使用它们作为输入-与云图像一起-创建一个梦想的图像)?

12305 次浏览

问题是如何从ImageNet获取所选类#50: 'American alligator, Alligator mississipiensis'的图像。

  1. 访问image-net.org。

  2. 进入“下载”。

  3. 按照“;下载图像url "”的说明:

enter image description here

如何从您的浏览器下载一个同义词集的url ?

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

enter image description here

enter image description here

短吻鳄没有出现。ImageNet is under maintenance. Only ILSVRC synsets are included in the search results.没有问题,我们对类似的动物“短吻鳄蜥蜴”很好,因为这个搜索是关于获得WordNet树图的右边分支。我不知道您是否会在这里获得直接的ImageNet图像,即使没有维护。

2. Open a synset papge

enter image description here

向下滚动:

enter image description here

向下滚动:

enter image description here

寻找美洲短吻鳄,它碰巧也是一种蜥蜴类双壳爬行动物,是它的近邻:

enter image description here

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

enter image description here

您将获得所选类的所有url。浏览器中弹出一个文本文件:

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

我们在这里看到,这只是关于知道需要放在URL末尾的正确的WordNet id。

手动图像下载

文本文件如下所示:

enter image description here

例如,第一个URL链接到:

enter image description here

第二个是死链接:

enter image description here

第三个环节已经失效,但第四个环节还在发挥作用。

enter image description here

这些url的图像是公开的,但许多链接是死的,而且图片的分辨率较低。

自动图像下载

还是在ImageNet指南中:

如何通过HTTP协议下载?通过HTTP下载一个同义词集 请求,您需要获得&;WordNet id &;(wnid)。 当您使用资源管理器浏览同义词集时,您可以找到WordNet 图像窗口下方的ID。(点击这里搜索“Synset WordNet id”; 找出“Dog, domestic Dog, Canis familiarisy”这首歌的出处;同义词集)。 要了解更多关于“WordNet id”的信息,请参考

Mapping between ImageNet and WordNet

给定一个synset的wid,它的图像的url可以从

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

你也可以得到给定wid的下标同义词集,请参考API 文档 to learn more.

.

那么API文档中有什么呢?

这里有获取所有的WordNet ID(所谓的“synset ID”)和所有synset的单词所需的一切,也就是说,它有任何类名和它的WordNet ID,而且是免费的。

获取同义词集的单词

给定一个synset的wid,的单词 synset可以在

处获得
http://www.image-net.org/api/text/wordnet.synset.getwords?wnid=[wnid]
你也可以点击这里到 下载所有同义词集的WordNet ID和单词之间的映射, 点击这里下载 所有同义词集的WordNet ID和glosses之间的映射

如果你知道选择的WordNet id和它们的类名,你可以使用nltk.corpus.wordnet的"(自然语言工具包),请参见WordNet接口

在我们的例子中,我们只需要#50: 'American alligator, Alligator mississipiensis'类的映像,我们已经知道我们需要什么,因此我们可以把nltk.corpus.wordnet放在一边(更多信息请参阅教程或堆栈交换问题)。我们可以通过循环浏览仍然有效的url来自动下载所有鳄鱼图像。当然,我们可以也将此扩展到整个WordNet,并循环遍历所有WordNet id,尽管这将花费整个树图太多的时间-而且也不推荐,因为如果每天有1000人下载它们,图像将停止在那里。

我恐怕不会花时间写这段接受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)

结果:

enter image description here

  1. 如果你需要在死链接后面的图片和原始质量,如果你的项目是非商业性的,你可以登录,查看“我如何获得图片的副本?”在下载常见问题解答
  • 在上面的URL中,你可以看到URL末尾的wnid=n01698640,这是映射到ImageNet的WordNet id。
  • 或者在“synset的图像”中;标签,只需点击&;Wordnet IDs"。

enter image description here

到达:

enter image description here

或者右键单击—另存为:

enter image description here

您可以使用WordNet id来获取原始图像。

enter image description here

如果你是商业的,我会建议你联系ImageNet团队。


附加组件

采取一个评论的想法:如果你不想要很多图像,而只是“一个单一的类图像”;,看看可视化GoogLeNet类,并尝试将此方法用于ImageNet的图像。也在使用深梦代码。

可视化GoogLeNet类

  1. 2015年7月
有没有想过深度神经网络认为达尔马提亚狗应该做什么 看起来像什么?

最近谷歌发表一篇文章描述他们如何设法使用 深度神经网络生成类可视化和修改 图像通过所谓的“盗梦”方法。他们后来 发布了通过inception方法修改图像的代码 但是,他们并没有发布代码来生成类 它们在同一篇文章中显示的可视化 虽然我从来没有弄清楚谷歌是如何生成他们的类的 可视化后,屠宰deepdream代码和这个ipython 笔记本从凯尔麦克唐纳,我设法教练GoogLeNet到绘画 : < / p >

enter image description here

... [与许多其他示例图像跟随]