/
feature.py
143 lines (117 loc) · 3.91 KB
/
feature.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
TODO: fill this area
"""
from sys import exit, argv
from skimage import io, feature, exposure
import numpy as np
import json
from models.db_mysql import Effectives
from models import db_mysql
from models.engine import get_engine
import itertools
import logging
from slit_utils import get_image
from sqlalchemy.orm import Session
logging.basicConfig(level=logging.DEBUG)
orb = feature.ORB()
def extract_orb(img):
print img
orb.detect_and_extract(img)
ret = orb.descriptors
print ret
return ret
def extract_kp(img):
kps = feature.corner_peaks(feature.corner_harris(img), min_distance = 2)
bb = feature.BRIEF(patch_size = 5) # iPad specific(or not)
bb.extract(img, kps)
return bb.descriptors
def extract_kp_CENSURE(img, plot = None):
d1 = feature.CENSURE(mode = 'STAR')
d1.detect(img)
if plot is not None:
plot.imshow(img)
plot.axis('off')
plot.scatter(d1.keypoints[:, 1], d1.keypoints[:, 0])
return d1.keypoints
def dumb_matcher(img1, img2):
kps = lambda img: feature.corner_peaks(feature.corner_harris(img), min_distance = 2)
kp1 = kps(img1)
kp2 = kps(img2)
to_set = lambda aoa: set(map(lambda x: (x[0], x[1]), aoa))
s1 = to_set(kp1)
s2 = to_set(kp2)
return float(len(s1 & s2) * 2) / (len(s1) + len(s2))
def matcher(img_extractor):
"""calculate similarity
img_extractor: takes image, returns feature point descriptors, as of writing this method, 'extractor_kp' is good example.
"""
def calculate_rate(it, jt):
mx = feature.match_descriptors(it, jt)
return float(len(mx) * 2) / (len(it) + len(jt))
def func(img1, img2):
return calculate_rate(img_extractor(img1), img_extractor(img2))
return func
"""Actual matcher being used"""
# default_matcher = matcher(extract_kp)
default_matcher = dumb_matcher
def reduce_groups(keys, image_src, compare):
"""Clustering similar images
TODO: Should use union find algorithm for better efficiency.
Parameters
----------
kv: [ key ] iterable
image_src: method which accepts key and returns image for that key
compare: method which accepts (image, image) and returns Boolean
Returns
-------
{ unique_id: [ keys ] } dict
"""
dic = { }
for it in keys:
img = image_src(it)
found = False
for jt in dic:
match = True
for kt in dic[jt]:
kmg = image_src(kt)
rate = compare(img, kmg)
if rate < 0.70:
match = False
break
print('match rate : %s %s %s' % (it, jt, rate))
if not match:
continue
found = True
dic[jt] += [ it ]
break
if not found:
dic[it] = [ it ]
return dic
def generate_groups(date):
raw_keys = itertools.product(db_mysql.cache_ids(date), range(2))
keys = itertools.ifilter(lambda x: int(db_mysql.cache_attack(x)) >= 0, raw_keys)
return reduce_groups(keys, get_image, default_matcher)
def process(date):
db_mysql.clear_tags(date)
s = Session(get_engine())
gs = generate_groups(date).values()
mosts = {}
for i, it in enumerate(gs):
fn = lambda (x, y): int(db_mysql.cache_tag(x, "atk_eff%s" % (y + 1)))
atk_fn = lambda (x, y): int(db_mysql.cache_tag(x, "attack%s" % (y+1)))
combined_fn = lambda v: -(atk_fn(v) * 10 + fn(v))
arr = sorted(it, key = combined_fn)
if atk_fn(arr[0]) > 0:
nk = arr[0][0]
if nk not in mosts: mosts[nk] = 0
mosts[nk] += 1
for j, jt in enumerate(arr):
s.add(Effectives(date=date, src_id=jt[0], atk_id=jt[1], group_id=i, group_idx=j))
s.commit()
for it in mosts:
db_mysql.add_tag(it, "most", mosts[it])
if __name__ == "__main__":
date = argv[-1]
process(date)