[PYTHON] How to use image-match

Introduction

image-match is, in a nutshell, an image search engine. You can register any image and find the image using the image as a key. It is also possible to perform image search at extremely high speed by combining with Elasticsearch.

Prerequisites

item Description
Verification date 2016.04.08
OS Mac OS X 10.10.5
Python 2.7.11
Elasticsearch 2.2.1

Advance preparation

$ brew install py2cairo cairo elasticsearch
$ pip install numpy scipy image_match

How to use

Try to compare images

Let's try an image-match README example.

first.py


from image_match.goldberg import ImageSignature

gis = ImageSignature()
# a = gis.generate_signature('https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg')
a = gis.generate_signature('687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg')
#b = gis.generate_signature('https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg')
b = gis.generate_signature('mona-lisa-67506_960_720.jpg')

print(gis.normalized_distance(a, b))

c = gis.generate_signature('https://upload.wikimedia.org/wikipedia/commons/e/e0/Caravaggio_-_Cena_in_Emmaus.jpg')
print(gis.normalized_distance(a, c))

d = gis.generate_signature('https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg')
print(gis.normalized_distance(a, d))

I will try it.

$ python first.py
0.220951701409
0.684462753815
0.422527138625

If you specify the URL for the target image, you can get the image and search it. It will take some time, so it is a good idea to drop it with curl etc. in advance and specify the file path directly.

with Elasticsearch Let's use it with Elasticsearch.

$ elasticsearch
[2016-04-08 15:18:47,952][INFO ][node                     ] [Alexander Lexington] version[2.2.1], pid[59417], build[d045fc2/2016-03-09T09:38:54Z]
[2016-04-08 15:18:47,952][INFO ][node                     ] [Alexander Lexington] initializing ...
[2016-04-08 15:18:48,945][INFO ][plugins                  ] [Alexander Lexington] modules [lang-expression, lang-groovy], plugins [], sites []
[2016-04-08 15:18:48,998][INFO ][env                      ] [Alexander Lexington] using [1] data paths, mounts [[/ (/dev/disk1)]], net usable_space [69.9gb], net total_space [232.6gb], spins? [unknown], types [hfs]
[2016-04-08 15:18:48,998][INFO ][env                      ] [Alexander Lexington] heap size [990.7mb], compressed ordinary object pointers [true]
[2016-04-08 15:18:48,999][WARN ][env                      ] [Alexander Lexington] max file descriptors [10240] for elasticsearch process likely too low, consider increasing to at least [65536]
[2016-04-08 15:18:52,884][INFO ][node                     ] [Alexander Lexington] initialized
[2016-04-08 15:18:52,884][INFO ][node                     ] [Alexander Lexington] starting ...
[2016-04-08 15:18:53,095][INFO ][transport                ] [Alexander Lexington] publish_address {127.0.0.1:9300}, bound_addresses {[fe80::1]:9300}, {[::1]:9300}, {127.0.0.1:9300}
[2016-04-08 15:18:53,109][INFO ][discovery                ] [Alexander Lexington] elasticsearch_hattori-h/FnX_ySN8RP2my8GcBTZsvw
[2016-04-08 15:18:56,148][INFO ][cluster.service          ] [Alexander Lexington] new_master {Alexander Lexington}{FnX_ySN8RP2my8GcBTZsvw}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
[2016-04-08 15:18:56,182][INFO ][http                     ] [Alexander Lexington] publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}
[2016-04-08 15:18:56,182][INFO ][node                     ] [Alexander Lexington] started
[2016-04-08 15:18:56,230][INFO ][gateway                  ] [Alexander Lexington] recovered [0] indices into cluster_state
[2016-04-08 15:34:22,441][INFO ][cluster.metadata         ] [Alexander Lexington] [images] creating index, cause [auto(index api)], templates [], shards [5]/[1], mappings [image]
[2016-04-08 15:34:22,889][INFO ][cluster.routing.allocation] [Alexander Lexington] Cluster health status changed from [RED] to [YELLOW](reason: [shards started [[images][4]] ...]).
[2016-04-08 15:34:22,998][INFO ][cluster.metadata         ] [Alexander Lexington] [images] update_mapping [image]

After starting Elasticsearch, execute the following script.

first_with_es.py


import json
from elasticsearch import Elasticsearch
from image_match.elasticsearch_driver import SignatureES

es = Elasticsearch()
ses = SignatureES(es)

image_set = (
    'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg',
    'https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg',
    'https://upload.wikimedia.org/wikipedia/commons/e/e0/Caravaggio_-_Cena_in_Emmaus.jpg',
    'https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg',
)
for img in image_set:
    print("add image to Elasticsearch. img=%s" % img)
    ses.add_image(img)


search_image_set = (
    'https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg',
    'http://i.imgur.com/CVYBCCy.jpg',
    'http://i.imgur.com/T5AusYd.jpg',
)
for img in search_image_set:
    print("=== search %s ===" % img)
    print(json.dumps(ses.search_image(img, all_orientations=True), indent=2))
$ first_with_es.py
add image to Elasticsearch. img=https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg
add image to Elasticsearch. img=https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg
add image to Elasticsearch. img=https://upload.wikimedia.org/wikipedia/commons/e/e0/Caravaggio_-_Cena_in_Emmaus.jpg
add image to Elasticsearch. img=https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg
=== search https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg ===
[
  {
    "path": "https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg ",
    "score": 2.435569,
    "dist": 0.0,
    "id": "AVP0lC4XSbcGjA3_XZUG"
  },
  {
    "path": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg ",
    "score": 0.029808408,
    "dist": 0.22095170140933634,
    "id": "AVP0lCRBSbcGjA3_XZUF"
  },
  {
    "path": "https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg ",
    "score": 0.004886414,
    "dist": 0.42325822368808808,
    "id": "AVP0lDflSbcGjA3_XZUI"
  }
]
=== search http://i.imgur.com/CVYBCCy.jpg ===
[
  {
    "path": "https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg ",
    "score": 0.20739666,
    "dist": 0.15454905655638429,
    "id": "AVP0lC4XSbcGjA3_XZUG"
  },
  {
    "path": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg ",
    "score": 0.016346568,
    "dist": 0.24980626832071956,
    "id": "AVP0lCRBSbcGjA3_XZUF"
  },
  {
    "path": "https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg ",
    "score": 0.0031033582,
    "dist": 0.43156216266051023,
    "id": "AVP0lDflSbcGjA3_XZUI"
  }
]
=== search http://i.imgur.com/T5AusYd.jpg ===
[
  {
    "path": "https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg ",
    "score": 1.5544797,
    "dist": 0.069116439263706961,
    "id": "AVP0lC4XSbcGjA3_XZUG"
  },
  {
    "path": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg/687px-Mona_Lisa,_by_Leonardo_da_Vinci,_from_C2RMF_retouched.jpg ",
    "score": 0.029808408,
    "dist": 0.22484320805049718,
    "id": "AVP0lCRBSbcGjA3_XZUF"
  },
  {
    "path": "https://c2.staticflickr.com/8/7158/6814444991_08d82de57e_z.jpg ",
    "score": 0.004886414,
    "dist": 0.42394015619010844,
    "id": "AVP0lDflSbcGjA3_XZUI"
  }
]

The larger the number of score (smaller, closer to dist), the more similar the images.

Recommended Posts

How to use image-match
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use shogun
How to use Pandas 2
How to use Virtualenv
How to use numpy.vectorize
How to use pytest_report_header
How to use partial
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
How to use list []
How to use python-kabusapi
How to use OptParse
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import
How to use Qt Designer
How to use search sorted
[gensim] How to use Doc2Vec
python3: How to use bottle (2)
Understand how to use django-filter
How to use the generator
[Python] How to use list 1
How to use FastAPI ③ OpenAPI
How to use Python argparse
How to use IPython Notebook
How to use Pandas Rolling
[Note] How to use virtualenv
How to use redis-py Dictionaries
Python: How to use pydub
[Python] How to use checkio
[Go] How to use "... (3 periods)"
How to use Django's GeoIp2
[Python] How to use input ()
How to use the decorator
[Introduction] How to use open3d
How to use Python lambda
How to use Jupyter Notebook
[Python] How to use virtualenv
python3: How to use bottle (3)
python3: How to use bottle
How to use Google Colaboratory
How to use Python bytes
How to use cron (personal memo)