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.
item | Description |
---|---|
Verification date | 2016.04.08 |
OS | Mac OS X 10.10.5 |
Python | 2.7.11 |
Elasticsearch | 2.2.1 |
$ brew install py2cairo cairo elasticsearch
$ pip install numpy scipy image_match
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