大家好,我们经常在搜索引擎上搜索图片的时候,直接上传一张图片,搜索引擎立即把相似的图片显示出来,比如我在百度图片中上传一张美女照片点击搜索,他展现出相似穿着的美女照片,那么这个技术是怎么实现的呢,今天我来揭晓一下。
环境要求
本文是在Ubuntu 18.04上进行,首先要安装了python3和pip3
sudo apt-get install python3 sudo apt-get install python3-pip第一步:下载SIS项目与依赖项
SIS是由日本东京大学工业科技学院的助理教授编写的一个开源图片搜索引擎,我直接从github克隆一下到本地
git clone https://github.com/matsui528/sis.git cd sis pip3 install -r requirements.txt他将下载5个依赖项
Pillow:是python的图像处理库。由于PIL不兼容setuptools,再加上更新缓慢等因素,Alex Clark等一些社区好心人还是希望能够继续支持PIL,所以fork了PIL,这就是Pillow的缘起。
h5py: 是python访问HDF5文件格式的交互接口. 它让你访问大型数值化的数据 ,并且处理来之 NumPy的数据.
tensorflow: 开源的人工智能开发框架.
Keras: 是运行在TensorFlow, CNTK, 或 Theano之上的高级别神经网络人工智能API.
Flask: python的web框架
第二步:存放图片
在sis目录下新建static/img 二级目录,并放一些jpg的图片,如下图
第三步:为目录下的每张图片生成pkl特征文件
这个脚本会将图片的特征值释放出来,使用了VGG16 网络 结合了ImageNet的预训练权重
python3 offline.py注意,vgg16网络文件大概533M,所有需要点时间
运行完后,我们打开feature目录,会看到每张图片的特征值文件
第四步:编写web访问
import os import numpy as np from PIL import Image from feature_extractor import FeatureExtractor import glob import pickle import json if __name__==”__main__”: fe = FeatureExtractor() features = [] img_paths = [] # Append every generated PKL file into an array and the image version as well for feature_path in glob.glob(“static/feature/*”): features.append(pickle.load(open(feature_path, rb))) img_paths.append(static/img/ + os.path.splitext(os.path.basename(feature_path))[0] + .jpg) # Define the query image, in our case it will be a hamburguer img = Image.open(“/home/ourcodeworld/Desktop/hamburguer_query.jpg”) # PIL image # Search for matches query = fe.extract(img) dists = np.linalg.norm(features – query, axis=1) # Do search ids = np.argsort(dists)[:30] # Top 30 results scores = [(dists[id], img_paths[id]) for id in ids] # Store results in a dictionary results = [] for item in scores: results.append({ “filename” : item[1], “uncertainty”: str(item[0]) }) # Create a JSON file with the results with open(data.json, w) as outputfile: json.dump(results, outputfile, ensure_ascii=False, indent=4)运行上面的命令后,我们打开浏览器输入网址http://0.0.0.0:5000
ok,一个简单的图片搜索引擎就出来了,当然我们也可以自己编写一个python文件来查询,输出自己需要的数据,下面新建一个文件custom.py,内容如下
import os import numpy as np from PIL import Image from feature_extractor import FeatureExtractor import glob import pickle import json if __name__==”__main__”: fe = FeatureExtractor() features = [] img_paths = [] # Append every generated PKL file into an array and the image version as well for feature_path in glob.glob(“static/feature/*”): features.append(pickle.load(open(feature_path, rb))) img_paths.append(static/img/ + os.path.splitext(os.path.basename(feature_path))[0] + .jpg) # Define the query image, in our case it will be a hamburguer img = Image.open(“/home/ourcodeworld/Desktop/hamburguer_query.jpg”) # PIL image # Search for matches query = fe.extract(img) dists = np.linalg.norm(features – query, axis=1) # Do search ids = np.argsort(dists)[:30] # Top 30 results scores = [(dists[id], img_paths[id]) for id in ids] # Store results in a dictionary results = [] for item in scores: results.append({ “filename” : item[1], “uncertainty”: str(item[0]) }) # Create a JSON file with the results with open(data.json, w) as outputfile: json.dump(results, outputfile, ensure_ascii=False, indent=4)运行一下
python3 custom.py运行完后我们可以看到结果
[ { “filename”: “static/img/hamburguer_4.jpg”, “uncertainty”: “0.95612574” }, { “filename”: “static/img/hamburguer_2.jpg”, “uncertainty”: “1.0821809” }, { “filename”: “static/img/hamburguer_3.jpg”, “uncertainty”: “1.099425” }, { “filename”: “static/img/hamburguer.jpg”, “uncertainty”: “1.1565413” }, { “filename”: “static/img/hot_dog2.jpg”, “uncertainty”: “1.1644002” }, { “filename”: “static/img/hot_dog_5.jpg”, “uncertainty”: “1.2176604” }, { “filename”: “static/img/portrait-if-a-spitz-pomeranian_t20_v3o29E-5ae9bbdca18d9e0037d95983.jpg”, “uncertainty”: “1.262754” }, { “filename”: “static/img/smiley_dog.jpg”, “uncertainty”: “1.3276863” }, { “filename”: “static/img/golden-retriever-puppy.jpg”, “uncertainty”: “1.3307321” }, { “filename”: “static/img/husky-winter-dogsled_h.jpg”, “uncertainty”: “1.3511014” } ]好了,一个简单的图片搜索引擎就好了,大家有什么问题欢迎在下方留言评论,关注我,每天更新一篇技术文章哦。