Image Recognition code of Extension Project
This commit is contained in:
commit
e76128b095
|
@ -0,0 +1,33 @@
|
|||
from pathlib import Path
|
||||
import tqdm
|
||||
|
||||
import LFUtilities
|
||||
import BEBLIDExtractor as lf
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='BEBLID bulk extraction')
|
||||
parser.add_argument('src', type=str, help='text file containing a list of img paths')
|
||||
parser.add_argument('dest', type=str, help='BEBLID dest file')
|
||||
|
||||
args = parser.parse_args()
|
||||
src = args.src
|
||||
dest = args.dest
|
||||
|
||||
with open(src, 'r') as src_file:
|
||||
dataset = []
|
||||
|
||||
print('Extracting lf...')
|
||||
for line in src_file:
|
||||
try:
|
||||
kp, des = lf.extract(line.strip())
|
||||
dataset.append((kp, des))
|
||||
except:
|
||||
print("cannot process '%s'" % line)
|
||||
pass
|
||||
|
||||
LFUtilities.save(dataset, dest)
|
||||
|
||||
print('lf extracted.')
|
|
@ -0,0 +1,19 @@
|
|||
import cv2
|
||||
from pathlib import Path
|
||||
import tqdm
|
||||
import pickle
|
||||
import os
|
||||
import LFUtilities
|
||||
|
||||
import BEBLIDParameters as params
|
||||
|
||||
detector = cv2.ORB_create(params.KEYPOINTS)
|
||||
descriptor = cv2.xfeatures2d.BEBLID_create(0.75)
|
||||
|
||||
|
||||
def extract(img_path):
|
||||
img = LFUtilities.resize(params.IMG_SIZE, cv2.imread(img_path))
|
||||
kp = detector.detect(img, None)
|
||||
kp, des = descriptor.compute(img, kp)
|
||||
return (kp, des)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
NN_MATCH_RATIO = 0.8
|
||||
MIN_GOOD_MATCHES = 20
|
||||
MIN_INLIERS = 16
|
||||
KEYPOINTS = 1000
|
||||
IMG_SIZE = 1000
|
|
@ -0,0 +1,68 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import LFUtilities
|
||||
import BEBLIDParameters
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
class BEBLIDRescorer:
|
||||
|
||||
def __init__(self):
|
||||
self.lf = LFUtilities.load(settings.DATASET_BEBLID)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
#self.bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
|
||||
self.bf = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
|
||||
|
||||
def rescore_by_id(self, query_id, resultset):
|
||||
query_idx = self.ids.index(query_id)
|
||||
return self.rescore_by_img(self.lf[query_idx], resultset)
|
||||
|
||||
def rescore_by_img(self, query, resultset):
|
||||
max_inliers = -1
|
||||
res = []
|
||||
|
||||
for data_id, _ in resultset:
|
||||
data_idx = self.ids.index(data_id)
|
||||
try:
|
||||
data_el = self.lf[data_idx]
|
||||
|
||||
nn_matches = self.bf.knnMatch(query[1], data_el[1], 2)
|
||||
good = [m for m, n in nn_matches if m.distance < BEBLIDParameters.NN_MATCH_RATIO * n.distance]
|
||||
|
||||
if len(good) > BEBLIDParameters.MIN_GOOD_MATCHES:
|
||||
src_pts = np.float32([query[0][m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
dst_pts = np.float32([data_el[0][m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
|
||||
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 1.0)
|
||||
matches_mask = mask.ravel().tolist()
|
||||
# print(len(good))
|
||||
inliers = np.count_nonzero(matches_mask)
|
||||
# print(inliers)
|
||||
if (inliers >= BEBLIDParameters.MIN_INLIERS and inliers > max_inliers):
|
||||
max_inliers = inliers
|
||||
res.append((data_id, round(inliers/len(good), 3)))
|
||||
except:
|
||||
print('rescore error evaluating ' + data_id)
|
||||
pass
|
||||
|
||||
if res:
|
||||
res.sort(key=lambda result: result[1], reverse=True)
|
||||
return res
|
||||
|
||||
def add(self, lf):
|
||||
self.lf.append(lf)
|
||||
|
||||
def remove(self, idx):
|
||||
self.descs = np.delete(self.descs, idx, axis=0)
|
||||
|
||||
def save(self, is_backup=False):
|
||||
lf_save_file = settings.DATASET_LF
|
||||
ids_file = settings.DATASET_IDS_LF
|
||||
if lf_save_file != "None":
|
||||
if is_backup:
|
||||
lf_save_file += '.bak'
|
||||
ids_file += '.bak'
|
||||
|
||||
LFUtilities.save(lf_save_file, self.lf)
|
||||
np.savetxt(ids_file, self.ids, fmt='%s')
|
|
@ -0,0 +1,69 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import LFUtilities
|
||||
import BEBLIDParameters
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
class BEBLIDSearcher:
|
||||
|
||||
def __init__(self):
|
||||
self.lf = LFUtilities.load(settings.DATASET_BEBLID)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
#self.bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
|
||||
self.bf = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
|
||||
|
||||
def get_id(self, idx):
|
||||
return self.ids[idx]
|
||||
|
||||
def search_by_id(self, query_id):
|
||||
query_idx = self.ids.index(query_id)
|
||||
return self.search_by_img(self.lf[query_idx])
|
||||
|
||||
def search_by_img(self, query):
|
||||
max_inliers = -1
|
||||
res = []
|
||||
|
||||
for img_id, features in zip(self.ids, self.lf):
|
||||
try:
|
||||
nn_matches = self.bf.knnMatch(query[1], features[1], 2)
|
||||
good = [m for m, n in nn_matches if m.distance < BEBLIDParameters.NN_MATCH_RATIO * n.distance]
|
||||
|
||||
if len(good) > BEBLIDParameters.MIN_GOOD_MATCHES:
|
||||
src_pts = np.float32([query[0][m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
dst_pts = np.float32([features[0][m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
|
||||
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 1.0)
|
||||
matches_mask = mask.ravel().tolist()
|
||||
# print(len(good))
|
||||
inliers = np.count_nonzero(matches_mask)
|
||||
# print(inliers)
|
||||
if (inliers >= BEBLIDParameters.MIN_INLIERS and inliers > max_inliers):
|
||||
max_inliers = inliers
|
||||
class_name = img_id.split('/')[0]
|
||||
res.append((class_name, round(inliers/len(good), 3)))
|
||||
except:
|
||||
print('search error evaluating ' + img_id)
|
||||
pass
|
||||
|
||||
if res:
|
||||
res.sort(key=lambda result: result[1], reverse=True)
|
||||
return res
|
||||
|
||||
def add(self, lf):
|
||||
self.lf.append(lf)
|
||||
|
||||
def remove(self, idx):
|
||||
self.descs = np.delete(self.descs, idx, axis=0)
|
||||
|
||||
def save(self, is_backup=False):
|
||||
lf_save_file = settings.DATASET_LF
|
||||
ids_file = settings.DATASET_IDS_LF
|
||||
if lf_save_file != "None":
|
||||
if is_backup:
|
||||
lf_save_file += '.bak'
|
||||
ids_file += '.bak'
|
||||
|
||||
LFUtilities.save(lf_save_file, self.lf)
|
||||
np.savetxt(ids_file, self.ids, fmt='%s')
|
|
@ -0,0 +1,91 @@
|
|||
import h5py
|
||||
import numpy as np
|
||||
|
||||
rmac_out_file = '/media/Data/data/beni_culturali/out/rmac_out.txt'
|
||||
orb_out_file = '/media/Data/data/beni_culturali/out/orb_out.txt'
|
||||
|
||||
ground_truth_file = '/media/Data/data/beni_culturali/groundtruth.txt'
|
||||
|
||||
ground_truth = {}
|
||||
rmac_out = {}
|
||||
orb_out = {}
|
||||
|
||||
query_folder = '/media/Data/data/beni_culturali/ImmaginiComparazioni/'
|
||||
img_folder = '/media/Data/data/beni_culturali/thumbs/'
|
||||
|
||||
with open(ground_truth_file, 'r') as f:
|
||||
for line in f:
|
||||
values = line.strip().split(',')
|
||||
ground_truth[values[0]] = values[1:]
|
||||
|
||||
with open(orb_out_file, 'r') as f:
|
||||
for line in f:
|
||||
values = line.strip().split(',')
|
||||
orb_out[values[0]] = values[1]
|
||||
|
||||
with open(rmac_out_file, 'r') as f:
|
||||
for line in f:
|
||||
values = line.strip().split(',')
|
||||
rmac_out[values[0]] = values[1:]
|
||||
|
||||
counter = 0
|
||||
found = 0
|
||||
|
||||
html = '<html><body>'
|
||||
html += '<h1 align="center">Image Analysis Report</h1>'
|
||||
html += '<h2>Numero totale query: 64 (una query è ripetuta due volte)</h2>'
|
||||
html += '<h2>Immagini Recuperate (evidenziate dal bordo verde):</h2>'
|
||||
html += '<ul><li><h3>Al primo risultato: <span style="color:red;">78%</span> (50 su 64)</h3></li>'
|
||||
html += '<li><h3>Entro il terzo risultato: <span style="color:red;">83%</span> (53 su 64)</h3></li>'
|
||||
html += '<li><h3>Entro il 60esimo risultato: <span style="color:red;">84%</span> (54 su 64)</h3></li></ul>'
|
||||
|
||||
html += '<h2>Elenco delle query e delle immagini recuperate:</h2>'
|
||||
html += '<h3>[query, <span style="color:green;">immagine ritrovata</span>, posizione (ranking)]</h3><hr>'
|
||||
|
||||
counter = 1
|
||||
|
||||
for key, value in ground_truth.items():
|
||||
orb_res = orb_out[key]
|
||||
rmac_res = rmac_out[key]
|
||||
#print(key)
|
||||
#print(value)
|
||||
# print(orb_res + '\n')
|
||||
html += '<div><span style="color:red;">' + str(counter) + '. </span><b>' + key + '</b>'
|
||||
tmp = ''
|
||||
found_id = ''
|
||||
found = False
|
||||
k = 0
|
||||
if orb_res in value:
|
||||
found = True
|
||||
found_id = orb_res
|
||||
ground_truth[key] = 'already_found'
|
||||
tmp += '<img style="border-width: 5px; margin-left:10px; padding:2px; border-color: #00AA00; border-style: solid;" width="128" title="' + orb_res + '" src="' + img_folder + orb_res + '">'
|
||||
|
||||
else:
|
||||
for k in range(60):
|
||||
if rmac_res[k] in value:
|
||||
tmp += '<img style="border-width: 5px; margin-left:10px; padding:2px; border-color: #00AA00; border-style: solid;" width="128" title="' + rmac_res[k] + '" src="' + img_folder + rmac_res[k] + '">'
|
||||
found = True
|
||||
found_id = rmac_res[k]
|
||||
ground_truth[key] = 'already_found'
|
||||
break
|
||||
if k < 2:
|
||||
tmp += '<img width="128" title="' + rmac_res[k] + '" src="' + img_folder + rmac_res[k] + '">'
|
||||
else:
|
||||
tmp += '<span>.</span>'
|
||||
|
||||
if found:
|
||||
html += ', <span style="color:green;">' + found_id + '</span>' + ', (ranking: <b>' + str(k + 1) + '</b>)'
|
||||
else:
|
||||
html += ', <span style="color:red;"> NONE</span>'
|
||||
|
||||
html += '</br></br><img width="128" style="padding:5px;" src="' + query_folder + key + '">'
|
||||
if found:
|
||||
html += tmp
|
||||
else:
|
||||
html += '<img style="padding:32px; margin-left:10px;" height="48" src="/media/Data/data/beni_culturali/out/notfound.png">'
|
||||
|
||||
html += '</br></div><hr>'
|
||||
counter += 1
|
||||
html += '</body></html>'
|
||||
print(html)
|
|
@ -0,0 +1,77 @@
|
|||
from telegram import ReplyKeyboardMarkup, KeyboardButton
|
||||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ContextTypes
|
||||
import requests
|
||||
import json
|
||||
import telegram
|
||||
import re
|
||||
|
||||
endpoint = "http://bilioso.isti.cnr.it:8190/bcir/searchByURL"
|
||||
endpoint_rescorer = "http://bilioso.isti.cnr.it:8190/bcir/setRescorer"
|
||||
|
||||
|
||||
|
||||
def start(update, context):
|
||||
chat_id = update.effective_chat.id
|
||||
# custom_keyboard = [['top-left', 'top-right'], ['bottom-left', 'bottom-right']]
|
||||
# reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test", reply_markup = reply_markup)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test")
|
||||
photo_id = update.message.photo[-1].file_id
|
||||
if (photo_id is None):
|
||||
print(update.message)
|
||||
query = context.bot.getFile(photo_id)
|
||||
print(query.file_path)
|
||||
# r = requests.get(endpoint, params=params)
|
||||
# json_res = json.loads(r.text)
|
||||
response = "Sorry, I can't recognize it :-("
|
||||
# if json_res is not None:
|
||||
# title = re.sub("\\d", "", json_res['title'])
|
||||
# response = "*" + json_res['author'] + "*, _" + title + "_\n\n"
|
||||
# response += json_res['artworkPage']
|
||||
# update.message.reply_text(response)
|
||||
text = endpoint + '?tohtml=true&url=' + query.file_path
|
||||
|
||||
|
||||
print(text)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
params = {'url': query.file_path, 'securityID': 'FA6mMmeWZ8JjWKz5'}
|
||||
print(query.file_path)
|
||||
r = requests.get(endpoint, params=params)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
#context.bot.send_message(chat_id=chat_id, text='GEM', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
'''
|
||||
def commands(update, context):
|
||||
text = update.message.text
|
||||
if text.lower() == 'commands':
|
||||
chat_id = update.effective_chat.id
|
||||
markup = ReplyKeyboardMarkup(keyboard=[['GEM', KeyboardButton(text='BEBLID')],["GEM_TH", "BEB_TH"]])
|
||||
context.bot.sendMessage(chat_id=chat_id, text="available commands", reply_markup=markup, parse_mode=telegram.ParseMode.HTML)
|
||||
if text == "BEBLID":
|
||||
params = {'rescorer': 'true'}
|
||||
elif text == "GEM":
|
||||
params = {'rescorer': 'false'}
|
||||
r = requests.get(endpoint_rescorer, params=params)
|
||||
res = r.text
|
||||
print(res)
|
||||
update.message.reply_text(res)
|
||||
'''
|
||||
|
||||
def call_service(query):
|
||||
print(query)
|
||||
files = {'img': query}
|
||||
r = requests.post(endpoint, files=files)
|
||||
return r.text
|
||||
|
||||
|
||||
updater = Updater('2140606085:AAHEBR3a_O9b8E8tbJFaWopDUvT4ptAUkP4')
|
||||
|
||||
updater.dispatcher.add_handler(MessageHandler(Filters.photo, start))
|
||||
#updater.dispatcher.add_handler(MessageHandler(Filters.text, commands))
|
||||
updater.start_polling()
|
||||
|
||||
updater.idle()
|
|
@ -0,0 +1,105 @@
|
|||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
|
||||
import requests
|
||||
import json
|
||||
import telegram
|
||||
import re
|
||||
import uuid
|
||||
import urllib
|
||||
import cv2
|
||||
import io
|
||||
import numpy as np
|
||||
import json
|
||||
import LFUtilities
|
||||
import base64
|
||||
|
||||
endpoint = "http://bilioso.isti.cnr.it:8190/bcir/searchByImgB64"
|
||||
|
||||
log_folder = "/media/Data/data/extension/img_recognition/bot"
|
||||
|
||||
|
||||
def url_to_file(url):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
dest_path = log_folder + "/" + dest_file
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
|
||||
}
|
||||
)
|
||||
resp = urllib.request.urlopen(req)
|
||||
image = np.asarray(bytearray(resp.read()), dtype="uint8")
|
||||
decoded = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
#im = Image.fromarray(image)
|
||||
#im.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def start(update, context):
|
||||
chat_id = update.effective_chat.id
|
||||
# custom_keyboard = [['top-left', 'top-right'], ['bottom-left', 'bottom-right']]
|
||||
# reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test", reply_markup = reply_markup)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test")
|
||||
photo_id = update.message.photo[-1].file_id
|
||||
query = context.bot.getFile(photo_id)
|
||||
params = {'url': query.file_path}
|
||||
img_file = url_to_file(query.file_path)
|
||||
|
||||
with open(img_file, "rb") as image_file:
|
||||
encoded_string = base64.b64encode(image_file.read())
|
||||
|
||||
# r = requests.get(endpoint, params=params)
|
||||
# json_res = json.loads(r.text)
|
||||
response = "Sorry, I can't recognize it :-("
|
||||
# if json_res is not None:
|
||||
# title = re.sub("\\d", "", json_res['title'])
|
||||
# response = "*" + json_res['author'] + "*, _" + title + "_\n\n"
|
||||
# response += json_res['artworkPage']
|
||||
# update.message.reply_text(response)
|
||||
text = endpoint + '?tohtml=true&url=' + query.file_path
|
||||
|
||||
|
||||
|
||||
|
||||
print(text)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
data = {'image': encoded_string, 'securityID': 'FA6mMmeWZ8JjWKz5', 'rescorer': 'false', 'lf_impl': 'beblid'}
|
||||
r = requests.post(endpoint, data=data)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
#context.bot.send_message(chat_id=chat_id, text='GEM', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
data = {'image': encoded_string, 'securityID': 'FA6mMmeWZ8JjWKz5', 'rescorer': 'true', 'lf_impl': 'beblid'}
|
||||
r = requests.post(endpoint, data=data)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
# context.bot.send_message(chat_id=chat_id, text='GEM', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
|
||||
|
||||
|
||||
def hello(bot, update):
|
||||
update.message.reply_text(
|
||||
'Hello {}'.format(update.message.from_user.first_name))
|
||||
|
||||
|
||||
def call_service(query):
|
||||
files = {'img': query}
|
||||
r = requests.post(endpoint, files=files)
|
||||
return r.text
|
||||
|
||||
|
||||
updater = Updater('2140606085:AAHEBR3a_O9b8E8tbJFaWopDUvT4ptAUkP4')
|
||||
|
||||
updater.dispatcher.add_handler(MessageHandler(Filters.photo, start))
|
||||
updater.dispatcher.add_handler(CommandHandler('hello', hello))
|
||||
updater.start_polling()
|
||||
updater.idle()
|
|
@ -0,0 +1,87 @@
|
|||
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
|
||||
import requests
|
||||
import json
|
||||
import telegram
|
||||
import re
|
||||
|
||||
endpoint = "http://bilioso.isti.cnr.it:8290/bcirtest/searchByURL"
|
||||
|
||||
|
||||
def start(update, context):
|
||||
chat_id = update.effective_chat.id
|
||||
# custom_keyboard = [['top-left', 'top-right'], ['bottom-left', 'bottom-right']]
|
||||
# reply_markup = telegram.ReplyKeyboardMarkup(custom_keyboard)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test", reply_markup = reply_markup)
|
||||
# context.bot.send_message(chat_id=chat_id, text = "Custom Keyboard Test")
|
||||
photo_id = update.message.photo[-1].file_id
|
||||
query = context.bot.getFile(photo_id)
|
||||
params = {'url': query.file_path}
|
||||
print(query.file_path)
|
||||
# r = requests.get(endpoint, params=params)
|
||||
# json_res = json.loads(r.text)
|
||||
response = "Sorry, I can't recognize it :-("
|
||||
# if json_res is not None:
|
||||
# title = re.sub("\\d", "", json_res['title'])
|
||||
# response = "*" + json_res['author'] + "*, _" + title + "_\n\n"
|
||||
# response += json_res['artworkPage']
|
||||
# update.message.reply_text(response)
|
||||
text = endpoint + '?tohtml=true&url=' + query.file_path
|
||||
|
||||
|
||||
|
||||
|
||||
print(text)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
#-GEM-#
|
||||
params = {'url': query.file_path}
|
||||
r = requests.get(endpoint, params=params)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
context.bot.send_message(chat_id=chat_id, text='GEM', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
#-ORB-#
|
||||
params = {'url': query.file_path, 'rescorer': 'true', 'lf_impl': 'orb'}
|
||||
r = requests.get(endpoint, params=params)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
context.bot.send_message(chat_id=chat_id, text='ORB', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
#-BEBLID-#
|
||||
params = {'url': query.file_path, 'rescorer': 'true', 'lf_impl': 'beblid'}
|
||||
r = requests.get(endpoint, params=params)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
context.bot.send_message(chat_id=chat_id, text='BEBLID', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
# -LATCH-#
|
||||
params = {'url': query.file_path, 'rescorer': 'true', 'lf_impl': 'latch'}
|
||||
r = requests.get(endpoint, params=params)
|
||||
text = json.loads(r.text)
|
||||
print(text)
|
||||
|
||||
context.bot.send_message(chat_id=chat_id, text='LATCH', parse_mode=telegram.ParseMode.HTML)
|
||||
context.bot.send_message(chat_id=chat_id, text=text, parse_mode=telegram.ParseMode.HTML)
|
||||
|
||||
def hello(bot, update):
|
||||
update.message.reply_text(
|
||||
'Hello {}'.format(update.message.from_user.first_name))
|
||||
|
||||
|
||||
def call_service(query):
|
||||
files = {'img': query}
|
||||
r = requests.post(endpoint, files=files)
|
||||
return r.text
|
||||
|
||||
|
||||
updater = Updater('2140606085:AAHEBR3a_O9b8E8tbJFaWopDUvT4ptAUkP4')
|
||||
|
||||
updater.dispatcher.add_handler(MessageHandler(Filters.photo, start))
|
||||
updater.dispatcher.add_handler(CommandHandler('hello', hello))
|
||||
updater.start_polling()
|
||||
updater.idle()
|
|
@ -0,0 +1,10 @@
|
|||
import numpy as np
|
||||
import WebAppSettings as settings
|
||||
import requests
|
||||
|
||||
|
||||
def extract(img_path):
|
||||
files = {'image': ('img', open(img_path, 'rb'))}
|
||||
data = {'resize': 'true'}
|
||||
r = requests.post(settings.feature_extractor, data=data, files=files)
|
||||
return np.array(r.json())
|
|
@ -0,0 +1,61 @@
|
|||
import h5py
|
||||
import numpy as np
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
class GEMSearcher:
|
||||
|
||||
|
||||
def __init__(self):
|
||||
#self.dataset = h5py.File(settings.dataset_file, 'r')['rmac'][...]
|
||||
|
||||
#np.save('/media/Data/data/beni_culturali/deploy/dataset', self.dataset)
|
||||
self.descs = np.load(settings.DATASET_GEM)
|
||||
#self.desc1 = np.load(settings.DATASET1)
|
||||
#self.desc2 = np.load(settings.DATASET2)
|
||||
|
||||
#self.descs = (self.desc1 + self.desc2) / 2
|
||||
#self.descs /= np.linalg.norm(self.descs, axis=1, keepdims=True)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
|
||||
|
||||
def get_id(self, idx):
|
||||
return self.ids[idx]
|
||||
|
||||
|
||||
def add(self, desc, id):
|
||||
self.ids.append(id)
|
||||
self.descs = np.vstack((self.descs, desc))
|
||||
self.save()
|
||||
|
||||
|
||||
def remove(self, id):
|
||||
idx = self.ids.index(id)
|
||||
del self.ids[idx]
|
||||
self.descs = np.delete(self.descs, idx, axis=0)
|
||||
|
||||
|
||||
def search_by_id(self, query_id, k=10):
|
||||
query_idx = self.ids.index(query_id)
|
||||
return self.search_by_img(self.descs[query_idx], k)
|
||||
|
||||
def search_by_img(self, query, k=10):
|
||||
# print('----------query features-------')
|
||||
#print(query)
|
||||
dot_product = np.dot(self.descs, query[0])
|
||||
idx = dot_product.argsort()[::-1][:k]
|
||||
res = []
|
||||
for i in idx:
|
||||
res.append((self.ids[i], round(float(dot_product[i]), 3)))
|
||||
return res
|
||||
|
||||
def save(self, is_backup=False):
|
||||
descs_file = settings.DATASET
|
||||
ids_file = settings.DATASET_IDS
|
||||
|
||||
if is_backup:
|
||||
descs_file += '.bak'
|
||||
ids_file += '.bak'
|
||||
|
||||
np.save(descs_file, self.descs)
|
||||
np.savetxt(ids_file, self.ids, fmt='%s')
|
|
@ -0,0 +1,16 @@
|
|||
from PIL import Image
|
||||
import pyheif
|
||||
|
||||
def conv(image_path):
|
||||
new_name = image_path.replace('heic', 'png')
|
||||
heif_file = pyheif.read(image_path)
|
||||
data = Image.frombytes(
|
||||
heif_file.mode,
|
||||
heif_file.size,
|
||||
heif_file.data,
|
||||
"raw",
|
||||
heif_file.mode,
|
||||
heif_file.stride,
|
||||
)
|
||||
data.save(new_name, "PNG")
|
||||
return new_name
|
|
@ -0,0 +1,33 @@
|
|||
from pathlib import Path
|
||||
import tqdm
|
||||
|
||||
import LFUtilities
|
||||
import LATCHExtractor as lf
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='LATCH bulk extraction')
|
||||
parser.add_argument('src', type=str, help='text file containing a list of img paths')
|
||||
parser.add_argument('dest', type=str, help='LATCH dest file')
|
||||
|
||||
args = parser.parse_args()
|
||||
src = args.src
|
||||
dest = args.dest
|
||||
|
||||
with open(src, 'r') as src_file:
|
||||
dataset = []
|
||||
|
||||
print('Extracting lf...')
|
||||
for line in src_file:
|
||||
try:
|
||||
kp, des = lf.extract(line.strip())
|
||||
dataset.append((kp, des))
|
||||
except:
|
||||
print("cannot process '%s'" % line)
|
||||
pass
|
||||
|
||||
LFUtilities.save(dataset, dest)
|
||||
|
||||
print('lf extracted.')
|
|
@ -0,0 +1,16 @@
|
|||
import cv2
|
||||
import LFUtilities
|
||||
|
||||
import LATCHParameters as params
|
||||
|
||||
detector = cv2.ORB_create(params.KEYPOINTS)
|
||||
#descriptor = cv2.xfeatures2d.LATCH_create(1, True, 15)
|
||||
descriptor = cv2.xfeatures2d.LATCH_create()
|
||||
|
||||
|
||||
def extract(img_path):
|
||||
img = LFUtilities.resize(params.IMG_SIZE, cv2.imread(img_path))
|
||||
kp = detector.detect(img, None)
|
||||
kp, des = descriptor.compute(img, kp)
|
||||
return (kp, des)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
THRESHOLD = 70
|
||||
MIN_GOOD_MATCHES = 12
|
||||
MIN_INLIERS = 8
|
||||
KEYPOINTS = 5000
|
||||
IMG_SIZE = 500
|
|
@ -0,0 +1,67 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import LFUtilities
|
||||
import LATCHParameters
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
class LATCHRescorer:
|
||||
|
||||
def __init__(self):
|
||||
self.lf = LFUtilities.load(settings.DATASET_LATCH)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
|
||||
#self.orb = cv2.LATCH_create()
|
||||
self.bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
|
||||
|
||||
def rescore_by_id(self, query_id, resultset):
|
||||
query_idx = self.ids.index(query_id)
|
||||
return self.rescore_by_img(self.lf[query_idx], resultset)
|
||||
|
||||
def rescore_by_img(self, query, resultset):
|
||||
max_inliers = -1
|
||||
res = []
|
||||
|
||||
for data_id, _ in resultset:
|
||||
data_idx = self.ids.index(data_id)
|
||||
try:
|
||||
data_el = self.lf[data_idx]
|
||||
matches = self.bf.match(query[1], data_el[1])
|
||||
good = [m for m in matches if m.distance <= LATCHParameters.THRESHOLD]
|
||||
if len(good) > LATCHParameters.MIN_GOOD_MATCHES:
|
||||
src_pts = np.float32([query[0][m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
dst_pts = np.float32([data_el[0][m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
|
||||
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 1.0)
|
||||
matches_mask = mask.ravel().tolist()
|
||||
# print(len(good))
|
||||
inliers = np.count_nonzero(matches_mask)
|
||||
# print(inliers)
|
||||
if (inliers >= LATCHParameters.MIN_INLIERS and inliers > max_inliers):
|
||||
max_inliers = inliers
|
||||
res.append((data_id, inliers))
|
||||
except:
|
||||
print('rescore error evaluating ' + data_id)
|
||||
pass
|
||||
|
||||
if res:
|
||||
res.sort(key=lambda result: result[1], reverse=True)
|
||||
return res
|
||||
|
||||
def add(self, lf):
|
||||
self.lf.append(lf)
|
||||
|
||||
def remove(self, idx):
|
||||
self.descs = np.delete(self.descs, idx, axis=0)
|
||||
|
||||
def save(self, is_backup=False):
|
||||
lf_save_file = settings.DATASET_LF
|
||||
ids_file = settings.DATASET_IDS_LF
|
||||
if lf_save_file != "None":
|
||||
if is_backup:
|
||||
lf_save_file += '.bak'
|
||||
ids_file += '.bak'
|
||||
|
||||
LFUtilities.save(lf_save_file, self.lf)
|
||||
np.savetxt(ids_file, self.ids, fmt='%s')
|
|
@ -0,0 +1,38 @@
|
|||
from pathlib import Path
|
||||
import tqdm
|
||||
|
||||
import LFUtilities
|
||||
import ORBExtractor as lf
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='LF bulk extraction')
|
||||
parser.add_argument('src', type=str, help='img src folder path')
|
||||
parser.add_argument('dest', type=str, help='lf dest folder')
|
||||
|
||||
args = parser.parse_args()
|
||||
src = args.src
|
||||
dest = args.dest
|
||||
|
||||
paths = Path(src).rglob('*.*')
|
||||
paths_list = list(paths)
|
||||
|
||||
dataset = []
|
||||
|
||||
print('Extracting lf...')
|
||||
for path in tqdm.tqdm(paths_list):
|
||||
try:
|
||||
kp, des = lf.extract(os.path.join(path.parent, path.name))
|
||||
dataset.append((kp, des))
|
||||
except:
|
||||
print("cannot process '%s'" % path)
|
||||
pass
|
||||
|
||||
LFUtilities.save(dataset, os.path.join(dest, 'dataset_lf.dat'))
|
||||
with open(os.path.join(dest, 'dataset_lf.ids'), 'w') as f:
|
||||
for path in paths_list:
|
||||
id, _ = os.path.splitext(path.name)
|
||||
f.write("%s\n" % id)
|
||||
print('lf extracted.')
|
|
@ -0,0 +1,54 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
import pickle as pickle
|
||||
|
||||
import LFUtilities
|
||||
import WebAppSettings as settings
|
||||
from BEBLIDSearcher import BEBLIDSearcher
|
||||
import GEMExtractor as fe
|
||||
import ORBExtractor as lf
|
||||
import BEBLIDExtractor as beblid_lf
|
||||
import LATCHExtractor as latch_lf
|
||||
|
||||
|
||||
class Searcher:
|
||||
|
||||
def __init__(self):
|
||||
# self.dataset = h5py.File(settings.dataset_file, 'r')['rmac'][...]
|
||||
|
||||
# np.save('/media/Data/data/beni_culturali/deploy/dataset', self.dataset)
|
||||
self.search_engine = BEBLIDSearcher()
|
||||
|
||||
def get_id(self, idx):
|
||||
return self.search_engine.get_id(idx)
|
||||
|
||||
def add(self, img_file, id):
|
||||
self.save(True)
|
||||
|
||||
desc = fe.extract(img_file)
|
||||
orb = lf.extract(img_file)
|
||||
self.search_engine.add(desc, id)
|
||||
|
||||
self.save()
|
||||
print('added ' + id)
|
||||
|
||||
def remove(self, id):
|
||||
self.save(True)
|
||||
self.search_engine.remove(id)
|
||||
self.save()
|
||||
print('removed ' + id)
|
||||
|
||||
def search_by_id(self, query_id, k=10):
|
||||
kq = k
|
||||
res = self.search_engine.search_by_id(query_id)
|
||||
return res
|
||||
|
||||
def search_by_img(self, query_img, k=10):
|
||||
kq = k
|
||||
query_desc = beblid_lf.extract(query_img)
|
||||
res = self.search_engine.search_by_img(query_desc)
|
||||
return res
|
||||
|
||||
def save(self, is_backup=False):
|
||||
self.search_engine.save(is_backup)
|
||||
#self.rescorer.save(is_backup)
|
|
@ -0,0 +1,59 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
import pickle as pickle
|
||||
import os
|
||||
|
||||
def resize(max_side, img):
|
||||
if img.shape[1] > img.shape[0]:
|
||||
r = max_side / img.shape[1]
|
||||
dim = (max_side, int(img.shape[0] * r))
|
||||
else:
|
||||
r = max_side / img.shape[0]
|
||||
dim = (int(img.shape[1] * r), max_side)
|
||||
|
||||
# perform the actual resizing of the image and show it
|
||||
resized = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
|
||||
return resized
|
||||
|
||||
|
||||
def pickle_keypoints(keypoints, descriptors):
|
||||
i = 0
|
||||
temp_array = []
|
||||
for point in keypoints:
|
||||
temp = (point.pt, point.size, point.angle, point.response, point.octave,
|
||||
point.class_id, descriptors[i])
|
||||
i += 1
|
||||
temp_array.append(temp)
|
||||
return temp_array
|
||||
|
||||
|
||||
def unpickle_keypoints(array):
|
||||
keypoints = []
|
||||
descriptors = []
|
||||
for point in array:
|
||||
temp_feature = cv2.KeyPoint(x=point[0][0],y=point[0][1], size=point[1], angle=point[2], response=point[3], octave=point[4], class_id=point[5])
|
||||
temp_descriptor = point[6]
|
||||
keypoints.append(temp_feature)
|
||||
descriptors.append(temp_descriptor)
|
||||
return keypoints, np.array(descriptors)
|
||||
|
||||
|
||||
def load(lf_path):
|
||||
print('loading LF dataset ' + lf_path)
|
||||
ser_dataset = pickle.load(open(lf_path, "rb"))
|
||||
lf_dataset = []
|
||||
for item in ser_dataset:
|
||||
kp, desc = unpickle_keypoints(item)
|
||||
lf_dataset.append((kp, desc))
|
||||
return lf_dataset
|
||||
|
||||
|
||||
def save(lf_data, lf_path):
|
||||
data = []
|
||||
for lf in lf_data:
|
||||
data.append(pickle_keypoints(lf[0], lf[1]))
|
||||
pickle.dump(data, open(lf_path, 'wb'))
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
from pathlib import Path
|
||||
import tqdm
|
||||
|
||||
import LFUtilities
|
||||
import ORBExtractor as lf
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='ORB bulk extraction')
|
||||
parser.add_argument('src', type=str, help='text file containing a list of img paths')
|
||||
parser.add_argument('dest', type=str, help='ORB dest file')
|
||||
|
||||
args = parser.parse_args()
|
||||
src = args.src
|
||||
dest = args.dest
|
||||
|
||||
with open(src, 'r') as src_file:
|
||||
dataset = []
|
||||
|
||||
print('Extracting lf...')
|
||||
for line in src_file:
|
||||
try:
|
||||
kp, des = lf.extract(line.strip())
|
||||
dataset.append((kp, des))
|
||||
except:
|
||||
print("cannot process '%s'" % line)
|
||||
pass
|
||||
|
||||
LFUtilities.save(dataset, dest)
|
||||
|
||||
print('lf extracted.')
|
|
@ -0,0 +1,17 @@
|
|||
import cv2
|
||||
from pathlib import Path
|
||||
import tqdm
|
||||
import pickle
|
||||
import os
|
||||
|
||||
import LFUtilities
|
||||
import ORBParameters as params
|
||||
|
||||
orb = cv2.ORB.create(params.KEYPOINTS)
|
||||
|
||||
|
||||
def extract(img_path):
|
||||
img = LFUtilities.resize(params.IMG_SIZE, cv2.imread(img_path))
|
||||
kp, des = orb.detectAndCompute(img, mask=None)
|
||||
return (kp, des)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
THRESHOLD = 35
|
||||
MIN_GOOD_MATCHES = 12
|
||||
MIN_INLIERS = 8
|
||||
KEYPOINTS = 5000
|
||||
IMG_SIZE = 500
|
|
@ -0,0 +1,67 @@
|
|||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import LFUtilities
|
||||
import ORBParameters
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
class ORBRescorer:
|
||||
|
||||
def __init__(self):
|
||||
self.lf = LFUtilities.load(settings.DATASET_LF)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
|
||||
#self.orb = cv2.ORB_create()
|
||||
self.bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
|
||||
|
||||
def rescore_by_id(self, query_id, resultset):
|
||||
query_idx = self.ids.index(query_id)
|
||||
return self.rescore_by_img(self.lf[query_idx], resultset)
|
||||
|
||||
def rescore_by_img(self, query, resultset):
|
||||
max_inliers = -1
|
||||
res = []
|
||||
|
||||
for data_id, _ in resultset:
|
||||
data_idx = self.ids.index(data_id)
|
||||
try:
|
||||
data_el = self.lf[data_idx]
|
||||
matches = self.bf.match(query[1], data_el[1])
|
||||
good = [m for m in matches if m.distance <= ORBParameters.THRESHOLD]
|
||||
if len(good) > ORBParameters.MIN_GOOD_MATCHES:
|
||||
src_pts = np.float32([query[0][m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
dst_pts = np.float32([data_el[0][m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
|
||||
|
||||
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 1.0)
|
||||
matches_mask = mask.ravel().tolist()
|
||||
# print(len(good))
|
||||
inliers = np.count_nonzero(matches_mask)
|
||||
# print(inliers)
|
||||
if (inliers >= ORBParameters.MIN_INLIERS and inliers > max_inliers):
|
||||
max_inliers = inliers
|
||||
res.append((data_id, inliers))
|
||||
except:
|
||||
print('rescore error evaluating ' + data_id)
|
||||
pass
|
||||
|
||||
if res:
|
||||
res.sort(key=lambda result: result[1], reverse=True)
|
||||
return res
|
||||
|
||||
def add(self, lf):
|
||||
self.lf.append(lf)
|
||||
|
||||
def remove(self, idx):
|
||||
self.descs = np.delete(self.descs, idx, axis=0)
|
||||
|
||||
def save(self, is_backup=False):
|
||||
lf_save_file = settings.DATASET_LF
|
||||
ids_file = settings.DATASET_IDS_LF
|
||||
if lf_save_file != "None":
|
||||
if is_backup:
|
||||
lf_save_file += '.bak'
|
||||
ids_file += '.bak'
|
||||
|
||||
LFUtilities.save(lf_save_file, self.lf)
|
||||
np.savetxt(ids_file, self.ids, fmt='%s')
|
|
@ -0,0 +1,97 @@
|
|||
import json
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import pickle as pickle
|
||||
|
||||
import LFUtilities
|
||||
import WebAppSettings as settings
|
||||
#from ORBRescorer import ORBRescorer
|
||||
from BEBLIDRescorer import BEBLIDRescorer
|
||||
#from LATCHRescorer import LATCHRescorer
|
||||
from GEMSearcher import GEMSearcher
|
||||
import GEMExtractor as fe
|
||||
import ORBExtractor as orb_lf
|
||||
import BEBLIDExtractor as beblid_lf
|
||||
import LATCHExtractor as latch_lf
|
||||
|
||||
|
||||
class Searcher:
|
||||
|
||||
GEM_THRESHOLD = 0.3
|
||||
|
||||
def __init__(self):
|
||||
# self.dataset = h5py.File(settings.dataset_file, 'r')['rmac'][...]
|
||||
|
||||
# np.save('/media/Data/data/beni_culturali/deploy/dataset', self.dataset)
|
||||
self.ids = np.loadtxt(settings.DATASET_IDS, dtype=str).tolist()
|
||||
|
||||
self.search_engine = GEMSearcher()
|
||||
|
||||
# self.orb_rescorer = ORBRescorer()
|
||||
self.beblid_rescorer = BEBLIDRescorer()
|
||||
#self.latch_rescorer = LATCHRescorer()
|
||||
|
||||
def get_id(self, idx):
|
||||
return self.search_engine.get_id(idx)
|
||||
|
||||
def add(self, img_file, id):
|
||||
# self.save(True)
|
||||
|
||||
#desc = fe.extract(img_file)
|
||||
#orb = lf.extract(img_file)
|
||||
#self.search_engine.add(desc, id)
|
||||
#self.rescorer.add(orb)
|
||||
|
||||
#self.save()
|
||||
print('added ' + id)
|
||||
|
||||
def remove(self, id):
|
||||
#self.save(True)
|
||||
#self.search_engine.remove(id)
|
||||
#self.rescorer.remove(idx)
|
||||
#self.save()
|
||||
print('removed ' + id)
|
||||
|
||||
def search_by_id(self, query_id, k=10, rescorer=False, lf_impl='BEBLID'):
|
||||
kq = k
|
||||
if rescorer:
|
||||
kq = settings.k_reorder
|
||||
res = self.search_engine.search_by_id(query_id, kq)
|
||||
if rescorer:
|
||||
if lf_impl == 'BEBLID':
|
||||
res_lf = self.beblid_rescorer.rescore_by_id(query_id, res)
|
||||
#res = res_lf if res_lf else res[:k]
|
||||
res = res_lf
|
||||
return res
|
||||
|
||||
def search_by_img(self, query_img, k=10, rescorer=False, lf_impl='BEBLID'):
|
||||
if rescorer:
|
||||
print(lf_impl)
|
||||
kq = k
|
||||
if rescorer:
|
||||
kq = settings.k_reorder
|
||||
query_desc = fe.extract(query_img)
|
||||
res = self.search_engine.search_by_img(query_desc, kq)
|
||||
print(res[0])
|
||||
if rescorer:
|
||||
if lf_impl == 'BEBLID':
|
||||
query_lf = beblid_lf.extract(query_img)
|
||||
res_lf = self.beblid_rescorer.rescore_by_img(query_lf, res)
|
||||
if res_lf:
|
||||
label = res_lf[0][0].split('/')[0]
|
||||
res = [label, res_lf[0][1]]
|
||||
else:
|
||||
res = None
|
||||
else:
|
||||
if res[0][1] > self.GEM_THRESHOLD:
|
||||
label = res[0][0].split('/')[0]
|
||||
res = [label, res[0][1]]
|
||||
else:
|
||||
res = None
|
||||
|
||||
return res
|
||||
|
||||
def save(self, is_backup=False):
|
||||
self.search_engine.save(is_backup)
|
||||
#self.rescorer.save(is_backup)
|
|
@ -0,0 +1,21 @@
|
|||
import requests
|
||||
import base64
|
||||
|
||||
|
||||
BASE_URL = 'http://bilioso.isti.cnr.it:8190/bcir/'
|
||||
|
||||
image_path = '/home/paolo/Dropbox/extension_logs/352998a9ee4f490b9a56f84d05983168.png_90.jpg'
|
||||
|
||||
#searchByImg
|
||||
files = {'image': ('query', open(image_path, 'rb'))}
|
||||
post_data = {'securityID': 'A6mMmeWZ8JjWKz5', 'orientation': "1"}
|
||||
|
||||
r = requests.post(BASE_URL + 'searchByImg', files=files, data=post_data)
|
||||
print(r.json())
|
||||
|
||||
with open(image_path, "rb") as image_file:
|
||||
base64_img = base64.b64encode(image_file.read())
|
||||
base64_data = {'image': base64_img, 'securityID': 'FA6mMmeWZ8JjWKz5', 'orientation': "8"}
|
||||
|
||||
r = requests.post(BASE_URL + 'searchByImgB64', data=base64_data)
|
||||
print(r.json())
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
import json
|
||||
|
||||
from Searcher import Searcher
|
||||
import WebAppSettings as settings
|
||||
|
||||
|
||||
def search_by_img(img_file, lf_impl, rescorer=False):
|
||||
if lf_impl is not "GEM":
|
||||
rescorer = True
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
return results
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#testset= "/media/Data/data/extension/test_set/listfiles.txt"
|
||||
testset= "/media/Data/data/extension/merged_train_test/test/listfiles.txt"
|
||||
|
||||
settings.load_setting('conf_train_test.json')
|
||||
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
# Using readlines()
|
||||
file1 = open(testset, 'r')
|
||||
Lines = file1.readlines()
|
||||
|
||||
count = 0
|
||||
# Strips the newline character
|
||||
|
||||
#features = ["GEM", "ORB", "LATCH", "BEBLID"]
|
||||
features = ["GEM", "BEBLID"]
|
||||
|
||||
|
||||
counters = {"GEM":0, "ORB":0, "LATCH":0, "BEBLID":0}
|
||||
count_orb = 0
|
||||
count_latch = 0
|
||||
count_beblid = 0
|
||||
|
||||
for line in Lines:
|
||||
classname_q = line.replace("/media/Data/data/extension/merged_train_test/test/", "").split("/")[0]
|
||||
print("Query {}: {}".format(count, line.strip()))
|
||||
for f in features:
|
||||
results = search_by_img(line.strip(), f)
|
||||
if results is None or results[0][1] < 0.3:
|
||||
results = ["unknown", 1.0]
|
||||
classname = results[0][0].split("/")[0]
|
||||
if (classname_q == classname):
|
||||
counters[f] = counters[f] + 1
|
||||
print(results[0][0] + '", "conf":' + str(results[0][1]))
|
||||
|
||||
count += 1
|
||||
|
||||
for f in features:
|
||||
print(f'{f}: {counters}/{count}')
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
import json
|
||||
|
||||
from Searcher import Searcher
|
||||
import WebAppSettings as settings
|
||||
|
||||
def search_by_img(img_file, lf_impl, rescorer=False):
|
||||
if lf_impl is not "GEM":
|
||||
rescorer = True
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
return results
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
testset= "/media/Data/data/extension/test_set/listfiles.txt"
|
||||
|
||||
settings.load_setting('conf_test.json')
|
||||
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
# Using readlines()
|
||||
file1 = open(testset, 'r')
|
||||
Lines = file1.readlines()
|
||||
|
||||
count = 0
|
||||
# Strips the newline character
|
||||
|
||||
features = ["GEM", "ORB", "LATCH", "BEBLID"]
|
||||
counters = {"GEM":0, "ORB":0, "LATCH":0, "BEBLID":0}
|
||||
# features = ["GEM", "BEBLID"]
|
||||
# counters = {"GEM":0, "BEBLID":0}
|
||||
|
||||
out_csv = ''
|
||||
|
||||
for line in Lines:
|
||||
classname_q = line.replace("/media/Data/data/extension/test_set/", "").split("/")[0]
|
||||
filename_q = line.replace("/media/Data/data/extension/test_set/", "").split("/")[1]
|
||||
print("Query {}: {}".format(count, line.strip()))
|
||||
|
||||
out_line = ''
|
||||
out_line = out_line + f'{classname_q},{filename_q};'
|
||||
|
||||
for f in features:
|
||||
results = search_by_img(line.strip(), f)
|
||||
if results is None:
|
||||
results = ["unknown", 1.0]
|
||||
classname = results[0][0].split("/")[0]
|
||||
filename = results[0][0].split("/")[1]
|
||||
if (classname_q == classname):
|
||||
counters[f] = counters[f] + 1
|
||||
print(results[0][0] + '", "conf":' + str(results[0][1]))
|
||||
|
||||
out_line = out_line + f'{classname},{filename},{results[0][1]};'
|
||||
|
||||
print(out_line)
|
||||
out_csv = out_line + '\n'
|
||||
count += 1
|
||||
|
||||
print(f'{f}: {counters}/{count}')
|
||||
print(f'GEM accuracy: {counters["GEM"]}/{count}')
|
||||
print(f'BEBLID accuracy: {counters["BEBLID"]}/{count}')
|
||||
|
||||
#open text file
|
||||
out_file = open("out_csv.txt", "w")
|
||||
|
||||
#write string to file
|
||||
out_file.write(out_csv)
|
||||
|
||||
#close file
|
||||
out_file.close()
|
|
@ -0,0 +1,47 @@
|
|||
import glob, os
|
||||
from PIL import Image
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import tqdm
|
||||
|
||||
|
||||
w, h = 200,120
|
||||
|
||||
PATTERN = 'keyframes'
|
||||
REPLACE = 'thumbs'
|
||||
|
||||
|
||||
def resize_img(src, dest):
|
||||
paths = Path(src).rglob('*.*')
|
||||
paths_list = list(paths)
|
||||
|
||||
for path in tqdm.tqdm(paths_list):
|
||||
outfile = str(path).replace(PATTERN, REPLACE)
|
||||
folders = os.path.dirname(outfile)
|
||||
|
||||
#print(outfile)
|
||||
|
||||
if not os.path.isdir(folders):
|
||||
#print(folders)
|
||||
os.makedirs(folders)
|
||||
|
||||
try:
|
||||
im = Image.open(path)
|
||||
if im.mode in ("RGBA", "P"):
|
||||
im = im.convert("RGB")
|
||||
im.thumbnail((w, h), Image.ANTIALIAS)
|
||||
im.save(outfile, "JPEG")
|
||||
except IOError:
|
||||
print("cannot create thumbnail for '%s'" % path)
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# parser = argparse.ArgumentParser(description='Image resizing')
|
||||
# parser.add_argument('src', type=str, help='images source folder path')
|
||||
# parser.add_argument('dest', type=str, help='images dest folder path')
|
||||
|
||||
#args = parser.parse_args()
|
||||
#resize_img(args.src, args.dest)
|
||||
resize_img('/media/Data/data/rai/img/keyframes', '/media/Data/data/rai/img/keyframes')
|
||||
#resize_img('/media/Data/data/test/gem/img/originals/ImmaginiComparazioni', '/media/Data/data/test/gem/img/ImmaginiComparazioni_resized')
|
|
@ -0,0 +1,276 @@
|
|||
from re import split
|
||||
|
||||
from flask import Flask, request, redirect, url_for, flash, render_template, send_from_directory, abort, Response, session
|
||||
from random import randint
|
||||
import cv2
|
||||
import io
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
import urllib
|
||||
|
||||
import LFUtilities
|
||||
from Searcher import Searcher
|
||||
from GEMSearcher import GEMSearcher
|
||||
import WebAppSettings as settings
|
||||
import uuid
|
||||
import requests
|
||||
import os, os.path
|
||||
from PIL import Image
|
||||
import tornado.wsgi
|
||||
import tornado.httpserver
|
||||
import argparse
|
||||
import base64
|
||||
from Heic2Png import conv
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = "27eduCBA09"
|
||||
|
||||
|
||||
|
||||
security_id = 'FA6mMmeWZ8JjWKz5'
|
||||
rescorer = False
|
||||
lf_impl = 'BEBLID'
|
||||
|
||||
HEIC_MAGIC_NUMBER = "AAAAGGZ0eXA="
|
||||
|
||||
|
||||
@app.route('/bcir/')
|
||||
def api_root():
|
||||
print('index_with_randoms.html')
|
||||
random_ids = []
|
||||
for i in range(0, 15):
|
||||
random_ids.append(searcher.get_id(randint(0, 600)))
|
||||
return render_template('index_with_randoms.html', random_ids=random_ids)
|
||||
|
||||
|
||||
def url_to_file(url):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
|
||||
}
|
||||
)
|
||||
resp = urllib.request.urlopen(req)
|
||||
image = np.asarray(bytearray(resp.read()), dtype="uint8")
|
||||
decoded = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
#im = Image.fromarray(image)
|
||||
#im.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def post_to_file(image):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
|
||||
in_memory_file = io.BytesIO()
|
||||
image.save(in_memory_file)
|
||||
data = np.fromstring(in_memory_file.getvalue(), dtype=np.uint8)
|
||||
decoded = cv2.imdecode(data, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
return dest_path
|
||||
|
||||
def set_rescorer(rescore_param):
|
||||
global rescorer
|
||||
if rescore_param is not None:
|
||||
if rescore_param == 'true':
|
||||
rescorer = True
|
||||
elif rescore_param == 'false':
|
||||
rescorer = False
|
||||
|
||||
def base64_to_file(image_base64):
|
||||
ext = ".jpg"
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
ext = ".heic"
|
||||
dest_file = uuid.uuid4().hex + ext
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
with open(dest_path, "wb") as image_file:
|
||||
byte_content = base64.b64decode(image_base64)
|
||||
image_file.write(byte_content)
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
dest_path = conv(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def get_res(results, query_url=None, img_base64=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = '{"classname":"Unknown"}'
|
||||
else:
|
||||
results = '{"classname":"' + results[0] + '", "conf":' + str(results[1]) + '}'
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
if img_base64 != None:
|
||||
html_txt = str(datetime.now())
|
||||
html_txt += '</br>'
|
||||
html_txt += results
|
||||
html_txt += '</br>'
|
||||
html_txt += '<img height="256" src="data:image/png;base64,' + img_base64 + '">'
|
||||
html_txt += '</br></br></br>'
|
||||
html_txt += '\n'
|
||||
with open("/home/paolo/Dropbox/extension_logs/report.html", "a+") as myfile:
|
||||
myfile.write(html_txt)
|
||||
return json_res
|
||||
|
||||
def get_resDict(results, query_url=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = {"classname":"Unknown"}
|
||||
else:
|
||||
results = {"classname":"' + results[0][0] + '", "conf":' + str(results[0][1]) + '}
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
|
||||
return json_res
|
||||
|
||||
|
||||
@app.route('/bcir/searchById')
|
||||
def search_by_id():
|
||||
id = request.args.get('id')
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
results = searcher.search_by_id(id, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = id + ".jpg"
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
@app.route('/bcir/searchByImg', methods=['POST'])
|
||||
def search_by_img():
|
||||
if 'image' not in request.files:
|
||||
return Response(json.dumps("Error, unable to get the image"), status=401, mimetype='application/json')
|
||||
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
|
||||
file = request.files['image']
|
||||
img_file = post_to_file(file)
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcir/searchByImgB64', methods=['POST'])
|
||||
def search_by_img_base64():
|
||||
print("query by base64 received")
|
||||
#print(request)
|
||||
#print(request.form)
|
||||
sec_id = request.form.get("securityID")
|
||||
|
||||
#to fix a problem with photo orientation
|
||||
try:
|
||||
orientation = request.form.get("orientation")
|
||||
orientation = int(orientation)
|
||||
except:
|
||||
orientation = 1
|
||||
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
image = request.form.get('image')
|
||||
if image:
|
||||
img_file = base64_to_file(image)
|
||||
else:
|
||||
flash('No img sent')
|
||||
return redirect(request.url)
|
||||
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url, img_base64=image)
|
||||
|
||||
|
||||
@app.route('/bcir/searchByURL')
|
||||
def search_by_url():
|
||||
sec_id = request.args.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
url = request.args.get('url')
|
||||
img_file = url_to_file(url)
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = url
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcir/setRescorer')
|
||||
def set_bot_rescorer():
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
return "Rescorer set to " + str(rescorer)
|
||||
|
||||
|
||||
@app.route('/bcir/<path:filename>')
|
||||
def download_file(filename):
|
||||
print(filename)
|
||||
values = filename.split('/')
|
||||
folder = values[0]
|
||||
name = values[1]
|
||||
print(folder)
|
||||
print(name)
|
||||
|
||||
return send_from_directory(settings.working_folder + '/' + folder, name, as_attachment=False)
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = BeniCulturaliSearcher()
|
||||
|
||||
#app.run(host='0.0.0.0', port=8090, ssl_context='adhoc')
|
||||
app.run(host='0.0.0.0', port=settings.port)
|
||||
|
||||
# app.run(host='0.0.0.0', port=settings.port)
|
||||
"""
|
||||
|
||||
def start_tornado(app, port=8190):
|
||||
http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
|
||||
http_server.listen(port)
|
||||
app.logger.info("Tornado server starting on port {}".format(port))
|
||||
tornado.ioloop.IOLoop.instance().start()
|
||||
|
||||
|
||||
def start_from_terminal(app):
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
#if args.debug:
|
||||
# app.run(debug=True, host='0.0.0.0', port=settings.port)
|
||||
# else:
|
||||
#start_tornado(app, settings.port)
|
||||
|
||||
app.run(debug=True, host='0.0.0.0', port=settings.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_from_terminal(app)
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
from re import split
|
||||
|
||||
from flask import Flask, request, redirect, url_for, flash, render_template, send_from_directory, abort, Response, session
|
||||
from random import randint
|
||||
import cv2
|
||||
import io
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
import urllib
|
||||
|
||||
import LFUtilities
|
||||
from Searcher import Searcher
|
||||
from GEMSearcher import GEMSearcher
|
||||
import WebAppSettings as settings
|
||||
import uuid
|
||||
import requests
|
||||
import os, os.path
|
||||
from PIL import Image
|
||||
import tornado.wsgi
|
||||
import tornado.httpserver
|
||||
import argparse
|
||||
import base64
|
||||
from Heic2Png import conv
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = "27eduCBA09"
|
||||
|
||||
|
||||
|
||||
security_id = 'FA6mMmeWZ8JjWKz5'
|
||||
rescorer = False
|
||||
lf_impl = 'BEBLID'
|
||||
|
||||
HEIC_MAGIC_NUMBER = "AAAAGGZ0eXA="
|
||||
|
||||
|
||||
@app.route('/bcir/')
|
||||
def api_root():
|
||||
print('index_with_randoms.html')
|
||||
random_ids = []
|
||||
for i in range(0, 15):
|
||||
random_ids.append(searcher.get_id(randint(0, 600)))
|
||||
return render_template('index_with_randoms.html', random_ids=random_ids)
|
||||
|
||||
|
||||
def url_to_file(url):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
|
||||
}
|
||||
)
|
||||
resp = urllib.request.urlopen(req)
|
||||
image = np.asarray(bytearray(resp.read()), dtype="uint8")
|
||||
decoded = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
#im = Image.fromarray(image)
|
||||
#im.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def post_to_file(image):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
|
||||
in_memory_file = io.BytesIO()
|
||||
image.save(in_memory_file)
|
||||
data = np.fromstring(in_memory_file.getvalue(), dtype=np.uint8)
|
||||
decoded = cv2.imdecode(data, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
return dest_path
|
||||
|
||||
def set_rescorer(rescore_param):
|
||||
global rescorer
|
||||
if rescore_param is not None:
|
||||
if rescore_param == 'true':
|
||||
rescorer = True
|
||||
elif rescore_param == 'false':
|
||||
rescorer = False
|
||||
|
||||
def base64_to_file(image_base64):
|
||||
ext = ".jpg"
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
ext = ".heic"
|
||||
dest_file = uuid.uuid4().hex + ext
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
with open(dest_path, "wb") as image_file:
|
||||
byte_content = base64.b64decode(image_base64)
|
||||
image_file.write(byte_content)
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
dest_path = conv(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def get_res(results, query_url=None, img_base64=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = '{"classname":"Unknown"}'
|
||||
else:
|
||||
results = '{"classname":"' + results[0] + '", "conf":' + str(results[1]) + '}'
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
if img_base64 != None:
|
||||
html_txt = str(datetime.now())
|
||||
html_txt += '</br>'
|
||||
html_txt += results
|
||||
html_txt += '</br>'
|
||||
html_txt += '<img height="256" src="data:image/png;base64,' + img_base64 + '">'
|
||||
html_txt += '</br></br></br>'
|
||||
html_txt += '\n'
|
||||
with open("/home/paolo/Dropbox/extension_logs/report.html", "a+") as myfile:
|
||||
myfile.write(html_txt)
|
||||
return json_res
|
||||
|
||||
def get_resDict(results, query_url=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = {"classname":"Unknown"}
|
||||
else:
|
||||
results = {"classname":"' + results[0][0] + '", "conf":' + str(results[0][1]) + '}
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
|
||||
return json_res
|
||||
|
||||
def rotate_img(img_path, degree):
|
||||
im1 = Image.open(img_path)
|
||||
im2 = im1.rotate(degree)
|
||||
dest = img_path + str(degree) + ".jpg"
|
||||
im2.save(dest)
|
||||
return dest
|
||||
|
||||
|
||||
@app.route('/bcir/searchById')
|
||||
def search_by_id():
|
||||
id = request.args.get('id')
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
results = searcher.search_by_id(id, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = id + ".jpg"
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
@app.route('/bcir/searchByImg', methods=['POST'])
|
||||
def search_by_img():
|
||||
if 'image' not in request.files:
|
||||
return Response(json.dumps("Error, unable to get the image"), status=401, mimetype='application/json')
|
||||
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
|
||||
file = request.files['image']
|
||||
img_file = post_to_file(file)
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcir/searchByImgB64', methods=['POST'])
|
||||
def search_by_img_base64():
|
||||
print("query by base64 received")
|
||||
#print(request)
|
||||
#print(request.form)
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
image = request.form.get('image')
|
||||
if image:
|
||||
img_file = base64_to_file(image)
|
||||
else:
|
||||
flash('No img sent')
|
||||
return redirect(request.url)
|
||||
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
if results is None:
|
||||
print('No results. trying ' + str(90) + ' degrees')
|
||||
degree_90 = rotate_img(img_file, 90)
|
||||
results = searcher.search_by_img(degree_90, settings.k, rescorer, lf_impl)
|
||||
if results is None:
|
||||
print('No results. trying ' + str(270) + ' degrees')
|
||||
degree_270 = rotate_img(img_file, 270)
|
||||
results = searcher.search_by_img(degree_270, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url, img_base64=image)
|
||||
|
||||
|
||||
@app.route('/bcir/searchByURL')
|
||||
def search_by_url():
|
||||
sec_id = request.args.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
url = request.args.get('url')
|
||||
img_file = url_to_file(url)
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = url
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcir/setRescorer')
|
||||
def set_bot_rescorer():
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
return "Rescorer set to " + str(rescorer)
|
||||
|
||||
|
||||
@app.route('/bcir/<path:filename>')
|
||||
def download_file(filename):
|
||||
print(filename)
|
||||
values = filename.split('/')
|
||||
folder = values[0]
|
||||
name = values[1]
|
||||
print(folder)
|
||||
print(name)
|
||||
|
||||
return send_from_directory(settings.working_folder + '/' + folder, name, as_attachment=False)
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = BeniCulturaliSearcher()
|
||||
|
||||
#app.run(host='0.0.0.0', port=8090, ssl_context='adhoc')
|
||||
app.run(host='0.0.0.0', port=settings.port)
|
||||
|
||||
# app.run(host='0.0.0.0', port=settings.port)
|
||||
"""
|
||||
|
||||
def start_tornado(app, port=8190):
|
||||
http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
|
||||
http_server.listen(port)
|
||||
app.logger.info("Tornado server starting on port {}".format(port))
|
||||
tornado.ioloop.IOLoop.instance().start()
|
||||
|
||||
|
||||
def start_from_terminal(app):
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
#if args.debug:
|
||||
# app.run(debug=True, host='0.0.0.0', port=settings.port)
|
||||
# else:
|
||||
#start_tornado(app, settings.port)
|
||||
|
||||
app.run(debug=False, host='0.0.0.0', port=settings.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_from_terminal(app)
|
||||
|
|
@ -0,0 +1,378 @@
|
|||
from re import split
|
||||
|
||||
from flask import Flask, request, redirect, url_for, flash, render_template, send_from_directory, abort, Response, session
|
||||
from random import randint
|
||||
import cv2
|
||||
import io
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
import urllib
|
||||
|
||||
import LFUtilities
|
||||
from Searcher import Searcher
|
||||
from GEMSearcher import GEMSearcher
|
||||
import WebAppSettings as settings
|
||||
import uuid
|
||||
import requests
|
||||
import os, os.path
|
||||
from PIL import Image
|
||||
import tornado.wsgi
|
||||
import tornado.httpserver
|
||||
import argparse
|
||||
import base64
|
||||
from Heic2Png import conv
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = "27eduCBA09"
|
||||
|
||||
|
||||
|
||||
security_id = 'FA6mMmeWZ8JjWKz5'
|
||||
rescorer = False
|
||||
lf_impl = 'BEBLID'
|
||||
|
||||
HEIC_MAGIC_NUMBER = "AAAAGGZ0eXA="
|
||||
|
||||
|
||||
@app.route('/bcir/')
|
||||
def api_root():
|
||||
print('index_with_randoms.html')
|
||||
random_ids = []
|
||||
for i in range(0, 15):
|
||||
random_ids.append(searcher.get_id(randint(0, 600)))
|
||||
return render_template('index_with_randoms.html', random_ids=random_ids)
|
||||
|
||||
|
||||
def url_to_file(url):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
|
||||
}
|
||||
)
|
||||
resp = urllib.request.urlopen(req)
|
||||
image = np.asarray(bytearray(resp.read()), dtype="uint8")
|
||||
decoded = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
#im = Image.fromarray(image)
|
||||
#im.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def post_to_file(image):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
session["query"] = settings.log_folder + '/' + dest_file
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
|
||||
in_memory_file = io.BytesIO()
|
||||
image.save(in_memory_file)
|
||||
data = np.fromstring(in_memory_file.getvalue(), dtype=np.uint8)
|
||||
decoded = cv2.imdecode(data, cv2.IMREAD_COLOR)
|
||||
resized = LFUtilities.resize(500, decoded)
|
||||
cv2.imwrite(dest_path, resized)
|
||||
return dest_path
|
||||
|
||||
def set_rescorer(rescore_param):
|
||||
global rescorer
|
||||
if rescore_param is not None:
|
||||
if rescore_param == 'true':
|
||||
rescorer = True
|
||||
elif rescore_param == 'false':
|
||||
rescorer = False
|
||||
|
||||
def base64_to_file(image_base64):
|
||||
ext = ".jpg"
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
ext = ".heic"
|
||||
dest_file = uuid.uuid4().hex + ext
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
with open(dest_path, "wb") as image_file:
|
||||
byte_content = base64.b64decode(image_base64)
|
||||
image_file.write(byte_content)
|
||||
if (image_base64.startswith(HEIC_MAGIC_NUMBER)):
|
||||
dest_path = conv(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def get_res(results, query_url=None, img_base64=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = '{"classname":"Unknown"}'
|
||||
else:
|
||||
results = '{"classname":"' + results[0] + '", "conf":' + str(results[1]) + '}'
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
if img_base64 != None:
|
||||
html_txt = str(datetime.now())
|
||||
html_txt += '</br>'
|
||||
html_txt += results
|
||||
html_txt += '</br>'
|
||||
html_txt += '<img height="256" src="data:image/png;base64,' + img_base64 + '">'
|
||||
html_txt += '</br></br></br>'
|
||||
html_txt += '\n'
|
||||
with open("/home/paolo/Dropbox/extension_logs/report.html", "a+") as myfile:
|
||||
myfile.write(html_txt)
|
||||
return json_res
|
||||
|
||||
|
||||
def get_resDict(results, query_url=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = {"classname":"Unknown"}
|
||||
else:
|
||||
results = {"classname":"' + results[0][0] + '", "conf":' + str(results[0][1]) + '}
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
|
||||
return json_res
|
||||
|
||||
|
||||
def rotate_img(img_path, degree):
|
||||
im1 = Image.open(img_path)
|
||||
im2 = im1.rotate(degree, expand=True)
|
||||
dest = img_path + "_" + str(degree) + ".jpg"
|
||||
im2.save(dest)
|
||||
return dest
|
||||
|
||||
|
||||
@app.route('/bcir/searchById')
|
||||
def search_by_id():
|
||||
id = request.args.get('id')
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
results = searcher.search_by_id(id, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = id + ".jpg"
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
@app.route('/bcir/searchByImg', methods=['POST'])
|
||||
def search_by_img():
|
||||
if 'image' not in request.files:
|
||||
return Response(json.dumps("Error, unable to get the image"), status=401, mimetype='application/json')
|
||||
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
|
||||
file = request.files['image']
|
||||
img_file = post_to_file(file)
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
|
||||
results_0 = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
degree_90 = rotate_img(img_file, 90)
|
||||
results_90 = searcher.search_by_img(degree_90, settings.k, rescorer, lf_impl)
|
||||
degree_270 = rotate_img(img_file, 270)
|
||||
results_270 = searcher.search_by_img(degree_270, settings.k, rescorer, lf_impl)
|
||||
|
||||
max_res = results_0
|
||||
if results_90 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_90
|
||||
elif results_90[1] > max_res[1]:
|
||||
max_res = results_90
|
||||
if results_270 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_270
|
||||
elif results_270[1] > max_res[1]:
|
||||
max_res = results_270
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(max_res, query_url)
|
||||
|
||||
@app.route('/bcir/searchByImgB64', methods=['POST'])
|
||||
def search_by_img_base64():
|
||||
print("query by base64 received")
|
||||
#print(request)
|
||||
#print(request.form)
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
|
||||
#to fix a problem with photo orientation
|
||||
try:
|
||||
orientation = request.form.get("orientation")
|
||||
orientation = int(orientation)
|
||||
except:
|
||||
orientation = 1
|
||||
|
||||
image = request.form.get('image')
|
||||
if image:
|
||||
img_file = base64_to_file(image)
|
||||
else:
|
||||
flash('No img sent')
|
||||
return redirect(request.url)
|
||||
|
||||
oriented_img = img_file
|
||||
if orientation == 3:
|
||||
oriented_img = rotate_img(img_file, 180)
|
||||
elif orientation == 6:
|
||||
oriented_img = rotate_img(img_file, 270)
|
||||
elif orientation == 8:
|
||||
oriented_img = rotate_img(img_file, 90)
|
||||
|
||||
results = searcher.search_by_img(oriented_img, settings.k, rescorer, lf_impl)
|
||||
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url, img_base64=image)
|
||||
|
||||
'''
|
||||
results_0 = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
degree_90 = rotate_img(img_file, 90)
|
||||
results_90 = searcher.search_by_img(degree_90, settings.k, rescorer, lf_impl)
|
||||
degree_270 = rotate_img(img_file, 270)
|
||||
results_270 = searcher.search_by_img(degree_270, settings.k, rescorer, lf_impl)
|
||||
|
||||
max_res = results_0
|
||||
if results_90 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_90
|
||||
elif results_90[1] > max_res[1]:
|
||||
max_res = results_90
|
||||
if results_270 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_270
|
||||
elif results_270[1] > max_res[1]:
|
||||
max_res = results_270
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(max_res, query_url, img_base64=image)
|
||||
'''
|
||||
|
||||
@app.route('/bcir/searchByURL')
|
||||
def search_by_url():
|
||||
sec_id = request.args.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
url = request.args.get('url')
|
||||
img_file = url_to_file(url)
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
|
||||
|
||||
#to fix a problem with photo orientation
|
||||
try:
|
||||
orientation = request.args.get("orientation")
|
||||
orientation = int(orientation)
|
||||
except:
|
||||
orientation = 1
|
||||
|
||||
oriented_img = img_file
|
||||
if orientation == 3:
|
||||
oriented_img = rotate_img(img_file, 180)
|
||||
elif orientation == 6:
|
||||
oriented_img = rotate_img(img_file, 90)
|
||||
elif orientation == 8:
|
||||
oriented_img = rotate_img(img_file, 270)
|
||||
|
||||
results = searcher.search_by_img(oriented_img, settings.k, rescorer, lf_impl)
|
||||
|
||||
set_rescorer(request.form.get("rescorer"))
|
||||
|
||||
query_url = None
|
||||
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = url
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
results_0 = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
degree_90 = rotate_img(img_file, 90)
|
||||
results_90 = searcher.search_by_img(degree_90, settings.k, rescorer, lf_impl)
|
||||
degree_270 = rotate_img(img_file, 270)
|
||||
results_270 = searcher.search_by_img(degree_270, settings.k, rescorer, lf_impl)
|
||||
|
||||
max_res = results_0
|
||||
if results_90 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_90
|
||||
elif results_90[1] > max_res[1]:
|
||||
max_res = results_90
|
||||
if results_270 is not None:
|
||||
if max_res is None:
|
||||
max_res = results_270
|
||||
elif results_270[1] > max_res[1]:
|
||||
max_res = results_270
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = url
|
||||
return get_res(max_res, query_url)
|
||||
|
||||
@app.route('/bcir/setRescorer')
|
||||
def set_bot_rescorer():
|
||||
set_rescorer(request.args.get("rescorer"))
|
||||
return "Rescorer set to " + str(rescorer)
|
||||
|
||||
|
||||
@app.route('/bcir/<path:filename>')
|
||||
def download_file(filename):
|
||||
print(filename)
|
||||
values = filename.split('/')
|
||||
folder = values[0]
|
||||
name = values[1]
|
||||
print(folder)
|
||||
print(name)
|
||||
|
||||
return send_from_directory(settings.working_folder + '/' + folder, name, as_attachment=False)
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = BeniCulturaliSearcher()
|
||||
|
||||
#app.run(host='0.0.0.0', port=8090, ssl_context='adhoc')
|
||||
app.run(host='0.0.0.0', port=settings.port)
|
||||
|
||||
# app.run(host='0.0.0.0', port=settings.port)
|
||||
"""
|
||||
|
||||
def start_tornado(app, port=8190):
|
||||
http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
|
||||
http_server.listen(port)
|
||||
app.logger.info("Tornado server starting on port {}".format(port))
|
||||
tornado.ioloop.IOLoop.instance().start()
|
||||
|
||||
|
||||
def start_from_terminal(app):
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
#if args.debug:
|
||||
# app.run(debug=True, host='0.0.0.0', port=settings.port)
|
||||
# else:
|
||||
#start_tornado(app, settings.port)
|
||||
|
||||
app.run(debug=False, host='0.0.0.0', port=settings.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_from_terminal(app)
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
def load_setting(conf_file):
|
||||
global port, feature_extractor, k, k_reorder, img_folder, log_folder, logs, working_folder, data_folder, DATASET_GEM, DATASET1, DATASET2, DATASET_LF, DATASET_IDS, DATASET_BEBLID, DATASET_LATCH
|
||||
|
||||
with open(conf_file) as settings_file:
|
||||
|
||||
settings = json.load(settings_file)
|
||||
|
||||
port = settings['port']
|
||||
feature_extractor = settings['fe_service']
|
||||
|
||||
k = settings['k']
|
||||
k_reorder = settings['k_reorder']
|
||||
working_folder = settings['working_folder']
|
||||
|
||||
data_folder = os.path.join(working_folder, settings['data_folder'])
|
||||
|
||||
if not os.path.isdir(data_folder):
|
||||
os.mkdir(data_folder)
|
||||
|
||||
DATASET_GEM = os.path.join(data_folder, 'gem.npy')
|
||||
#DATASET1 = os.path.join(data_folder, 'dataset_resized.npy')
|
||||
#DATASET2 = os.path.join(data_folder, 'dataset_bw.npy')
|
||||
#DATASET_LF = os.path.join(data_folder, 'dataset_lf.dat')
|
||||
#DATASET_LF = os.path.join(data_folder, 'orb_5k.dat')
|
||||
DATASET_IDS = os.path.join(data_folder, 'dataset.ids')
|
||||
#DATASET_BEBLID = os.path.join(data_folder, 'dataset_beblid.dat')
|
||||
DATASET_BEBLID = os.path.join(data_folder, 'beblid.dat')
|
||||
#DATASET_LATCH = os.path.join(data_folder, 'dataset_latch.dat')
|
||||
#DATASET_LATCH = os.path.join(data_folder, 'latch_5k.dat')
|
||||
|
||||
img_folder = settings['img_folder']
|
||||
log_folder = settings['log_folder']
|
||||
#temporary for mobile app debugging
|
||||
log_folder = settings['log_folder']
|
||||
log_folder = '/home/paolo/Dropbox/extension_logs'
|
||||
logs = os.path.join(working_folder, log_folder)
|
||||
if not os.path.isdir(logs):
|
||||
os.mkdir(logs)
|
|
@ -0,0 +1,290 @@
|
|||
from re import split
|
||||
|
||||
from flask import Flask, request, redirect, url_for, flash, render_template, send_from_directory, abort, Response
|
||||
from random import randint
|
||||
import cv2
|
||||
import io
|
||||
import numpy as np
|
||||
import json
|
||||
|
||||
import urllib
|
||||
|
||||
from Searcher import Searcher
|
||||
from GEMSearcher import GEMSearcher
|
||||
import WebAppSettings as settings
|
||||
import uuid
|
||||
import requests
|
||||
import os, os.path
|
||||
from PIL import Image
|
||||
import tornado.wsgi
|
||||
import tornado.httpserver
|
||||
import argparse
|
||||
import base64
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
security_id = 'FA6mMmeWZ8JjWKz5'
|
||||
|
||||
|
||||
@app.route('/bcirtest/')
|
||||
def api_root():
|
||||
print('index_with_randoms.html')
|
||||
random_ids = []
|
||||
for i in range(0, 15):
|
||||
random_ids.append(searcher.get_id(randint(0, 600)))
|
||||
return render_template('index_with_randoms.html', random_ids=random_ids)
|
||||
|
||||
|
||||
def url_to_file(url):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
|
||||
}
|
||||
)
|
||||
resp = urllib.request.urlopen(req)
|
||||
image = np.asarray(bytearray(resp.read()), dtype="uint8")
|
||||
decoded = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
cv2.imwrite(dest_path, decoded)
|
||||
#im = Image.fromarray(image)
|
||||
#im.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
|
||||
def post_to_file(image):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
image.save(dest_path)
|
||||
return dest_path
|
||||
|
||||
def base64_to_file(image_base64):
|
||||
dest_file = uuid.uuid4().hex + ".png"
|
||||
dest_path = settings.logs + "/" + dest_file
|
||||
with open(dest_path, "wb") as image_file:
|
||||
byte_content = base64.b64decode(image_base64)
|
||||
image_file.write(byte_content)
|
||||
return dest_path
|
||||
|
||||
|
||||
def get_res(results, query_url=None):
|
||||
if query_url is not None:
|
||||
return render_template('search.html', results=results, query_url=query_url)
|
||||
elif results is None:
|
||||
results = '{"classname":"Unknown"}'
|
||||
else:
|
||||
results = '{"classname":"' + results[0][0] + '", "conf":' + str(results[0][1]) + '}'
|
||||
print(results)
|
||||
json_res = json.dumps(results)
|
||||
print(json_res)
|
||||
|
||||
return json_res
|
||||
|
||||
|
||||
@app.route('/bcirtest/searchById')
|
||||
def search_by_id():
|
||||
id = request.args.get('id')
|
||||
rescorer = False
|
||||
lf_impl = 'ORB'
|
||||
if request.args.get("rescorer") == 'true':
|
||||
rescorer = True
|
||||
|
||||
if request.args.get("lf_impl") == 'beblid':
|
||||
lf_impl = 'BEBLID'
|
||||
elif request.args.get("lf_impl") == 'latch':
|
||||
lf_impl = 'LATCH'
|
||||
#results = searcher.search_by_id(id, settings.k, rescorer, lf_impl)
|
||||
results = searcher.search_by_id(id, settings.k)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = id + ".jpg"
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
@app.route('/bcirtest/searchByImg', methods=['POST'])
|
||||
def search_by_img():
|
||||
if 'image' not in request.files:
|
||||
return Response(json.dumps("Error, unable to get the image"), status=401, mimetype='application/json')
|
||||
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
|
||||
|
||||
file = request.files['image']
|
||||
img_file = post_to_file(file)
|
||||
rescorer = False
|
||||
lf_impl = 'ORB500'
|
||||
if request.form.get("rescorer") == 'true':
|
||||
rescorer = True
|
||||
if request.form.get("lf_impl") == 'beblid':
|
||||
lf_impl = 'BEBLID'
|
||||
elif request.form.get("lf_impl") == 'latch':
|
||||
lf_impl = 'LATCH'
|
||||
elif request.form.get("lf_impl") == 'orb':
|
||||
lf_impl = 'ORB'
|
||||
#dest_file = uuid.uuid4().hex + ".jpg"
|
||||
#dest_path = settings.logs + "/" + dest_file
|
||||
#file.save(dest_path)
|
||||
#files = {'image': (dest_file, open(dest_path, 'rb'))}
|
||||
#r = requests.post(settings.rmac_service, files=files)
|
||||
#results = search_engine.search_by_img(np.array(r.json()), settings.k)
|
||||
#results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcirtest/searchByImgB64', methods=['POST'])
|
||||
def search_by_img_base64():
|
||||
sec_id = request.form.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
image = request.form.get('image')
|
||||
if image:
|
||||
img_file = base64_to_file(image)
|
||||
else:
|
||||
flash('No img sent')
|
||||
return redirect(request.url)
|
||||
|
||||
|
||||
rescorer = False
|
||||
lf_impl = 'ORB500'
|
||||
if request.form.get("rescorer") == 'true':
|
||||
rescorer = True
|
||||
if request.form.get("lf_impl") == 'beblid':
|
||||
lf_impl = 'BEBLID'
|
||||
elif request.form.get("lf_impl") == 'latch':
|
||||
lf_impl = 'LATCH'
|
||||
elif request.form.get("lf_impl") == 'orb':
|
||||
lf_impl = 'ORB'
|
||||
#dest_file = uuid.uuid4().hex + ".jpg"
|
||||
#dest_path = settings.logs + "/" + dest_file
|
||||
#file.save(dest_path)
|
||||
#files = {'image': (dest_file, open(dest_path, 'rb'))}
|
||||
#r = requests.post(settings.rmac_service, files=files)
|
||||
#results = search_engine.search_by_img(np.array(r.json()), settings.k)
|
||||
#results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
results = searcher.search_by_img(img_file, settings.k)
|
||||
query_url = None
|
||||
if request.form.get("tohtml") is not None:
|
||||
query_url = ""
|
||||
return get_res(results, query_url)
|
||||
|
||||
|
||||
@app.route('/bcirtest/searchByURL')
|
||||
def search_by_url():
|
||||
sec_id = request.args.get("securityID")
|
||||
#if sec_id != security_id:
|
||||
# return Response(json.dumps("Error 401, not authorized"), status=401, mimetype='application/json')
|
||||
url = request.args.get('url')
|
||||
rescorer = False
|
||||
if request.args.get("rescorer") == 'true':
|
||||
rescorer = True
|
||||
img_file = url_to_file(url)
|
||||
# query = cv2.imdecode(image, cv2.IMREAD_COLOR)
|
||||
# dest_file = uuid.uuid4().hex + ".jpg"
|
||||
# dest_path = settings.logs + "/" + dest_file
|
||||
# cv2.imwrite(dest_path, query)
|
||||
# files = {'image': open(dest_path, 'rb')}
|
||||
# r = requests.post(settings.rmac_service, files=files)
|
||||
# results = search_engine.search_by_img(np.array(r.json()), settings.k)
|
||||
rescorer = False
|
||||
lf_impl = 'ORB500'
|
||||
if request.args.get("rescorer") == 'true':
|
||||
rescorer = True
|
||||
if request.args.get("lf_impl") == 'beblid':
|
||||
lf_impl = 'BEBLID'
|
||||
elif request.args.get("lf_impl") == 'latch':
|
||||
lf_impl = 'LATCH'
|
||||
elif request.args.get("lf_impl") == 'orb':
|
||||
lf_impl = 'ORB'
|
||||
#results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
results = searcher.search_by_img(img_file, settings.k, rescorer, lf_impl)
|
||||
query_url = None
|
||||
if request.args.get("tohtml") is not None:
|
||||
query_url = url
|
||||
return get_res(results, query_url)
|
||||
|
||||
@app.route('/bcirtest/addImg', methods=['POST'])
|
||||
def add_img():
|
||||
if 'image' not in request.files:
|
||||
flash('No file part')
|
||||
return redirect(request.url)
|
||||
try:
|
||||
file = request.files['image']
|
||||
id = request.files['image'].filename
|
||||
id, _ = os.path.splitext(id)
|
||||
img_file = post_to_file(file)
|
||||
searcher.add(img_file, id)
|
||||
json_res = json.dumps("done")
|
||||
return json_res
|
||||
except:
|
||||
abort(500)
|
||||
|
||||
|
||||
@app.route('/bcirtest/rmImg')
|
||||
def remove_img():
|
||||
try:
|
||||
id = request.args.get('id')
|
||||
searcher.remove(id)
|
||||
json_res = json.dumps("done")
|
||||
return json_res
|
||||
except:
|
||||
abort(500)
|
||||
|
||||
@app.route('/bcirtest/<path:filename>')
|
||||
def download_file(filename):
|
||||
print(filename)
|
||||
values = filename.split('/')
|
||||
print(values)
|
||||
print(settings.img_folder)
|
||||
|
||||
return send_from_directory(settings.img_folder, filename, as_attachment=False)
|
||||
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = BeniCulturaliSearcher()
|
||||
|
||||
#app.run(host='0.0.0.0', port=8090, ssl_context='adhoc')
|
||||
app.run(host='0.0.0.0', port=settings.port)
|
||||
|
||||
# app.run(host='0.0.0.0', port=settings.port)
|
||||
"""
|
||||
|
||||
def start_tornado(app, port=8190):
|
||||
http_server = tornado.httpserver.HTTPServer(tornado.wsgi.WSGIContainer(app))
|
||||
http_server.listen(port)
|
||||
app.logger.info("Tornado server starting on port {}".format(port))
|
||||
tornado.ioloop.IOLoop.instance().start()
|
||||
|
||||
|
||||
def start_from_terminal(app):
|
||||
parser = argparse.ArgumentParser(description='Reading configuration file')
|
||||
parser.add_argument('conf', type=str, help='Configuration file path')
|
||||
|
||||
args = parser.parse_args()
|
||||
settings.load_setting(args.conf)
|
||||
global searcher
|
||||
searcher = Searcher()
|
||||
|
||||
#if args.debug:
|
||||
# app.run(debug=True, host='0.0.0.0', port=settings.port)
|
||||
# else:
|
||||
#start_tornado(app, settings.port)
|
||||
|
||||
app.run(debug=True, host='0.0.0.0', port=8290)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_from_terminal(app)
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8030/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 15,
|
||||
"k_reorder": 15,
|
||||
"working_folder": "/workspace/data",
|
||||
"img_folder": "/workspace/data/data/img/dataset",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8190/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 15,
|
||||
"k_reorder": 15,
|
||||
"working_folder": "/media/Data/data/extension/img_recognition",
|
||||
"img_folder": "/media/Data/data/extension/datasetMerged",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8190/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 15,
|
||||
"k_reorder": 15,
|
||||
"working_folder": "/media/Data/data/extension/img_recognition",
|
||||
"img_folder": "/media/Data/data/extension/img_recognition/data/img/dataset",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8190/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 500,
|
||||
"k_reorder": 500,
|
||||
"working_folder": "/media/Data/data/extension/datasetEnriched",
|
||||
"img_folder": "/media/Data/data/extension/datasetEnriched/img",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8190/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 15,
|
||||
"k_reorder": 15,
|
||||
"working_folder": "/media/Data/data/extension/datasetMerged",
|
||||
"img_folder": "/media/Data/data/extension/datasetMerged",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"port": 8190,
|
||||
"img_host": "http://bilioso.isti.cnr.it:8190/bcimages",
|
||||
"fe_service": "http://localhost:5000/extract",
|
||||
"k": 15,
|
||||
"k_reorder": 15,
|
||||
"working_folder": "/media/Data/data/extension/merged_train_test",
|
||||
"img_folder": "/media/Data/data/extension/merged_train_test/train",
|
||||
"log_folder": "logs",
|
||||
"data_folder": "data"
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 MiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
|
@ -0,0 +1,105 @@
|
|||
function changeImage(imageURL, objectID) {
|
||||
//alert(imageURL + " - " + objectID);
|
||||
if (document.getElementById('objId').value==objectID || objectID == "" || imageURL == "null" || objectID == "null") {
|
||||
document.getElementById('advSearch').style.display = 'none';
|
||||
//document.getElementById('comboInfo').style.display = 'none';
|
||||
document.getElementById('queryImage').src='queryImage';
|
||||
document.getElementById('objId').value='';
|
||||
document.getElementById('objId').name="disabled";
|
||||
}
|
||||
else {
|
||||
document.getElementById('advSearch').style.display = '';
|
||||
//document.getElementById('comboInfo').style.display = '';
|
||||
document.getElementById('queryImage').src=imageURL;
|
||||
document.getElementById('objId').value=objectID;
|
||||
document.getElementById('objId').name="id";
|
||||
|
||||
//document.getElementById('imageQueryCheckbox').checked='checked';
|
||||
document.getElementById('objId').name="id";
|
||||
document.getElementById('queryImage').style.display = '';
|
||||
|
||||
if (document.getElementById('imageToUpload') != null) {
|
||||
document.getElementById('imageToUpload').value="";
|
||||
}
|
||||
}
|
||||
// if (imageURL != "null" && imageURL != "" && imageURL == objectID) {
|
||||
// document.getElementById('objId').name="url";
|
||||
// }
|
||||
}
|
||||
|
||||
function imageQuery() {
|
||||
//alert(imageURL + " - " + objectID);
|
||||
if (!document.getElementById('imageQueryCheckbox').checked) {
|
||||
document.getElementById('objId').name="disabled";
|
||||
document.getElementById('queryImage').style.display = 'none';
|
||||
}
|
||||
else {
|
||||
document.getElementById('objId').name="id";
|
||||
document.getElementById('queryImage').style.display = '';
|
||||
}
|
||||
}
|
||||
|
||||
function changeQueryBySampleMod(mode) {
|
||||
if (mode == "url") {
|
||||
document.getElementById("uploadText").style.display = 'none';
|
||||
document.getElementById("uploadLink").style.display = '';
|
||||
document.getElementById("urlText").style.display = '';
|
||||
document.getElementById("urlLink").style.display = 'none';
|
||||
document.getElementById("imageToUpload").style.display = 'none';
|
||||
document.getElementById("urlToUpload").style.display = '';
|
||||
document.getElementById("imageToUpload").value = '';
|
||||
|
||||
// document.getElementById("imageToUpload").type="text";
|
||||
// document.getElementById("imageToUpload").name="url";
|
||||
// document.getElementById("imageToUpload").size="49";
|
||||
document.getElementById("searchbar").action="./searchByURL"
|
||||
document.getElementById("searchbar").enctype="";
|
||||
document.getElementById("searchbar").method="GET";
|
||||
|
||||
|
||||
} else {
|
||||
document.getElementById("uploadText").style.display = '';
|
||||
document.getElementById("uploadLink").style.display = 'none';
|
||||
document.getElementById("urlText").style.display = 'none';
|
||||
document.getElementById("urlLink").style.display = '';
|
||||
|
||||
document.getElementById("urlToUpload").style.display = 'none';
|
||||
document.getElementById("imageToUpload").style.display = '';
|
||||
document.getElementById("urlToUpload").value = '';
|
||||
|
||||
// document.getElementById("imageToUpload").type="file";
|
||||
// document.getElementById("imageToUpload").name="imgFile";
|
||||
// document.getElementById("imageToUpload").size="38";
|
||||
|
||||
document.getElementById("searchbar").action="./searchByImg"
|
||||
document.getElementById("searchbar").enctype="multipart/form-data";
|
||||
document.getElementById("searchbar").method="POST";
|
||||
}
|
||||
}
|
||||
|
||||
function trim(str) {
|
||||
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
}
|
||||
|
||||
function getWindowHeight() {
|
||||
var windowHeight = 0;
|
||||
if (typeof(window.innerHeight) == 'number') {
|
||||
windowHeight = window.innerHeight;
|
||||
}
|
||||
else {
|
||||
if (document.documentElement && document.documentElement.clientHeight) {
|
||||
windowHeight = document.documentElement.clientHeight;
|
||||
}
|
||||
else {
|
||||
if (document.body && document.body.clientHeight) {
|
||||
windowHeight = document.body.clientHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
return windowHeight;
|
||||
}
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min);
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
|
||||
|
||||
a.polaroid {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: #333;
|
||||
padding: 10px 10px 20px 10px;
|
||||
width: 150px;
|
||||
border: 1px solid #BFBFBF;
|
||||
background-color: white;
|
||||
z-index: 2;
|
||||
font-size: 0.7em;
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
-webkit-transition: all 0.5s ease-in;
|
||||
}
|
||||
a.polaroid:hover,
|
||||
a.polaroid:focus,
|
||||
a.polaroid:active {
|
||||
z-index: 999;
|
||||
border-color: #6A6A6A;
|
||||
-webkit-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
|
||||
-moz-box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
|
||||
box-shadow: 15px 15px 20px rgba(0,0, 0, 0.4);
|
||||
-webkit-transform: rotate(0deg) scale(1.05);
|
||||
-moz-transform: rotate(0deg) scale(1.05);
|
||||
transform: rotate(0deg) scale(1.05);
|
||||
}
|
||||
.polaroid img {
|
||||
margin: 0 0 15px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.photo-album {
|
||||
position: relative;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
max-width: 70em;
|
||||
height: 450px;
|
||||
margin-top: 5em;
|
||||
min-width: 800px;
|
||||
max-width: 900px;
|
||||
}
|
||||
.photo-album .polaroid {
|
||||
position: absolute;
|
||||
}
|
||||
.photo-album h1 {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
top: 150px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
line-height: 1.9;
|
||||
}
|
||||
.photo-album h1 span {
|
||||
background-color: white;
|
||||
font-family: "Helvetica Neue",Arial,Helvetica,sans-serif;
|
||||
padding: 0.4em 0.8em 0.3em 0.8em;
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
-moz-box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
box-shadow: 2px 2px 4px rgba(0,0, 0, 0.3);
|
||||
border: 1px solid #6A6A6A;
|
||||
}
|
||||
.photo-album .small {
|
||||
width: 75px;
|
||||
padding: 6px 6px 12px 6px;
|
||||
font-size: 0.6em;
|
||||
}
|
||||
.photo-album .small img {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
}
|
||||
.photo-album .medium {
|
||||
width: 200px;
|
||||
padding: 13px 13px 26px 13px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.photo-album .medium img {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
.photo-album .large {
|
||||
width: 300px;
|
||||
padding: 20px 20px 30px 20px;
|
||||
font-size: 1em;
|
||||
}
|
||||
.photo-album .large img {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
.photo-album .img1 {
|
||||
bottom: 10px;
|
||||
right: 365px;
|
||||
-webkit-transform: rotate(10deg);
|
||||
-moz-transform: rotate(10deg);
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
.photo-album .img2 {
|
||||
top: 50px;
|
||||
right: 20px;
|
||||
-webkit-transform: rotate(-4deg);
|
||||
-moz-transform: rotate(-4deg);
|
||||
transform: rotate(-4deg);
|
||||
}
|
||||
.photo-album .img3 {
|
||||
left: 400px;
|
||||
top: 0;
|
||||
-webkit-transform: rotate(-5deg);
|
||||
-moz-transform: rotate(-5deg);
|
||||
transform: rotate(-5deg);
|
||||
}
|
||||
.photo-album .img4 {
|
||||
top: 10px;
|
||||
left: 495px;
|
||||
-webkit-transform: rotate(-20deg);
|
||||
-moz-transform: rotate(-20deg);
|
||||
transform: rotate(-20deg);
|
||||
}
|
||||
.photo-album .img5 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
-webkit-transform: rotate(1deg);
|
||||
-moz-transform: rotate(1deg);
|
||||
transform: rotate(1deg);
|
||||
}
|
||||
.photo-album .img6 {
|
||||
bottom: 10px;
|
||||
right: 156px;
|
||||
-webkit-transform: rotate(6deg);
|
||||
-moz-transform: rotate(6deg);
|
||||
transform: rotate(6deg);
|
||||
}
|
||||
.photo-album .img7 {
|
||||
bottom:0;
|
||||
left:400px;
|
||||
-webkit-transform: rotate(-10deg);
|
||||
-moz-transform: rotate(-10deg);
|
||||
transform: rotate(-10deg);
|
||||
}
|
||||
.photo-album .img8 {
|
||||
bottom: -20px;
|
||||
left: 700px;
|
||||
-webkit-transform: rotate(-8deg);
|
||||
-moz-transform: rotate(-8deg);
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
.photo-album .img9 {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
-webkit-transform: rotate(-8deg);
|
||||
-moz-transform: rotate(-8deg);
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
.photo-album .img10 {
|
||||
top: 0;
|
||||
left: 20px;
|
||||
-webkit-transform: rotate(8deg);
|
||||
-moz-transform: rotate(8deg);
|
||||
transform: rotate(8deg);
|
||||
}
|
||||
.photo-album .img11 {
|
||||
top: 0;
|
||||
right: 0;
|
||||
-webkit-transform: rotate(-8deg);
|
||||
-moz-transform: rotate(-8deg);
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
.photo-album .img12 {
|
||||
top: 0;
|
||||
left: 680px;
|
||||
-webkit-transform: rotate(18deg);
|
||||
-moz-transform: rotate(18deg);
|
||||
transform: rotate(18deg);
|
||||
}
|
||||
.photo-album .img13 {
|
||||
bottom: -20px;
|
||||
right: 630px;
|
||||
-webkit-transform: rotate(4deg);
|
||||
-moz-transform: rotate(4deg);
|
||||
transform: rotate(4deg);
|
||||
}
|
||||
.photo-album .img14 {
|
||||
top: 90px;
|
||||
left: 430px;
|
||||
-webkit-transform: rotate(15deg);
|
||||
-moz-transform: rotate(15deg);
|
||||
transform: rotate(15deg);
|
||||
}
|
||||
.photo-album .img15 {
|
||||
left:176px;
|
||||
top:20px;
|
||||
-webkit-transform: rotate(-8deg);
|
||||
-moz-transform: rotate(-8deg);
|
||||
transform: rotate(-8deg);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
z-index: 5;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Deep Image Search</title>
|
||||
|
||||
<link rel="icon" href="{{ url_for('static',filename='img/favicon.ico') }}" />
|
||||
|
||||
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='styles/polaroidStyle.css') }}">
|
||||
<script src= "{{ url_for('static',filename='js/ui.js') }}"></script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div align="center" id="header"><br>
|
||||
<div style="margin-bottom: 10px; vertical-align: middle;"><img class="header"
|
||||
src="{{ url_for('static',filename='img/aimh_logo.png') }}" style="max-width: 100%; height: auto; width: 400px;" alt=""></div>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div id="searchForm" style="">
|
||||
<span id="urlText" style="display: none;"><b>Paste image URL</b></span>
|
||||
<a href="#" id="urlLink" onclick="changeQueryBySampleMod('url')" >Paste image URL</a>
|
||||
<span id="uploadText"><b>Upload an image</b></span>
|
||||
<a href="#" id="uploadLink" onclick="changeQueryBySampleMod('upload')" style="display: none;">Upload an image</a>
|
||||
<form id="searchbar" method="POST" enctype="multipart/form-data" name="form1" action="./searchByImg">
|
||||
<table cellspacing="1" cellpadding="1" border="0">
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<input type="hidden" value="" name="" id="objId">
|
||||
<input type="hidden" value="true" name="tohtml">
|
||||
|
||||
<input style="display: none;" id="urlToUpload" name="url" type="text" size="49" onclick="" onchange="document.getElementById('queryImage').value=''">
|
||||
<input id="imageToUpload" name="image" type="file" size="38" onclick="" onchange="document.getElementById('queryImage').value=''">
|
||||
</td>
|
||||
<td valign="top">
|
||||
<input type="image" src="{{ url_for('static',filename='img/Search.png') }}" value="Search" title="Search" onclick="if (trim(document.getElementById('urlToUpload').value)=='' && trim(document.getElementById('imageToUpload').value)=='')return false;">
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
{%
|
||||
set css_classes = ["", "large polaroid img1","polaroid img2","small polaroid img3","medium polaroid img4","polaroid img5","polaroid img6","polaroid img7","small polaroid img8","medium polaroid img9","polaroid img10","small polaroid img11","small polaroid img12","small polaroid img13","small polaroid img14","polaroid img15"]
|
||||
|
||||
%}
|
||||
|
||||
<!-- <div align="center" class="photo-album">
|
||||
{% for i in range(0, 15) %}
|
||||
{% set id = random_ids[i] %}
|
||||
{% set objectUrlSmall = id%}
|
||||
{% set title = id.split("/")[0] %}
|
||||
<a href="searchById?tohtml=true&rescorer=false&bw=false&id={%print(id)%}" title="Click To Search" class="{%print(css_classes[i%15+1])%}"><img src="{%print(objectUrlSmall)%}" border="0">
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div align="center" style="padding-top: 40px;">
|
||||
<a href="./" title="more random images"><img src="{{ url_for('static',filename='img/refresh.png') }}" width=45></a>
|
||||
|
||||
</div>-->
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,88 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Deep Image Search</title>
|
||||
<link rel="icon" href="{{ url_for('static',filename='img/favicon.ico') }}" />
|
||||
|
||||
<script src= "{{ url_for('static',filename='js/ui.js') }}"></script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a href="." title="Home"><img
|
||||
src="{{ url_for('static',filename='img/aimh_logo.png') }}" border="0" align="bottom"
|
||||
width="160"></a></td>
|
||||
<td><img id="queryImage" src="{{session['query']}}" alt=""
|
||||
width="80" align="middle"></td>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div id="searchForm">
|
||||
<span id="urlText" style="display: none;"><b>Paste image URL</b></span>
|
||||
<a href="#" id="urlLink" onclick="changeQueryBySampleMod('url')" >Paste image URL</a>
|
||||
<span id="uploadText"><b>Upload an image</b></span>
|
||||
<a href="#" id="uploadLink" onclick="changeQueryBySampleMod('upload')" style="display: none;">Upload an image</a>
|
||||
<form id="searchbar" method="POST" enctype="multipart/form-data" name="form1" action="./searchByImg">
|
||||
<table cellspacing="1" cellpadding="1" border="0">
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<input type="hidden" value="" name="" id="objId">
|
||||
<input type="hidden" value="true" name="tohtml">
|
||||
|
||||
|
||||
<input style="display: none;" id="urlToUpload" name="url" type="text" size="49" onclick="" onchange="document.getElementById('queryImage').value=''">
|
||||
<input id="imageToUpload" name="image" type="file" size="38" onclick="" onchange="document.getElementById('queryImage').value=''">
|
||||
</td>
|
||||
<td valign="top">
|
||||
<input type="image" src="{{ url_for('static',filename='img/Search.png') }}" value="Search" title="Search" onclick="if (trim(document.getElementById('urlToUpload').value)=='' && trim(document.getElementById('imageToUpload').value)=='')return false;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<table width="800">
|
||||
{% if results != None%}
|
||||
{% set columns = 0 %}
|
||||
{% for idx in range(1) %}
|
||||
{% if idx% 6 == 0 %}
|
||||
<tr>
|
||||
{% endif %}
|
||||
{% set id = results[0] %}
|
||||
{% set objectUrlSmall = 'img4class/' + id + '.jpg'%}
|
||||
{% set title = id.split("/")[0] %}
|
||||
{% set score = results[1] %}
|
||||
<td>
|
||||
<div>
|
||||
<h2>{%print(score)%}, {%print(title)%}</h2>
|
||||
<img title={{score}} style="width: 160px;" src="{%print(objectUrlSmall)%}" border="0">
|
||||
<!--<br> <span style="font-size: x-small;"><h1>{%print(title)%}</h1></span><br>-->
|
||||
</div>
|
||||
</td>
|
||||
{% set columns = columns + 1 %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h1>Unknown class</h1>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,241 @@
|
|||
<#
|
||||
.Synopsis
|
||||
Activate a Python virtual environment for the current PowerShell session.
|
||||
|
||||
.Description
|
||||
Pushes the python executable for a virtual environment to the front of the
|
||||
$Env:PATH environment variable and sets the prompt to signify that you are
|
||||
in a Python virtual environment. Makes use of the command line switches as
|
||||
well as the `pyvenv.cfg` file values present in the virtual environment.
|
||||
|
||||
.Parameter VenvDir
|
||||
Path to the directory that contains the virtual environment to activate. The
|
||||
default value for this is the parent of the directory that the Activate.ps1
|
||||
script is located within.
|
||||
|
||||
.Parameter Prompt
|
||||
The prompt prefix to display when this virtual environment is activated. By
|
||||
default, this prompt is the name of the virtual environment folder (VenvDir)
|
||||
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
||||
|
||||
.Example
|
||||
Activate.ps1
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -Verbose
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||
and shows extra information about the activation as it executes.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
||||
Activates the Python virtual environment located in the specified location.
|
||||
|
||||
.Example
|
||||
Activate.ps1 -Prompt "MyPython"
|
||||
Activates the Python virtual environment that contains the Activate.ps1 script,
|
||||
and prefixes the current prompt with the specified string (surrounded in
|
||||
parentheses) while the virtual environment is active.
|
||||
|
||||
.Notes
|
||||
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
||||
execution policy for the user. You can do this by issuing the following PowerShell
|
||||
command:
|
||||
|
||||
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
|
||||
For more information on Execution Policies:
|
||||
https://go.microsoft.com/fwlink/?LinkID=135170
|
||||
|
||||
#>
|
||||
Param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[String]
|
||||
$VenvDir,
|
||||
[Parameter(Mandatory = $false)]
|
||||
[String]
|
||||
$Prompt
|
||||
)
|
||||
|
||||
<# Function declarations --------------------------------------------------- #>
|
||||
|
||||
<#
|
||||
.Synopsis
|
||||
Remove all shell session elements added by the Activate script, including the
|
||||
addition of the virtual environment's Python executable from the beginning of
|
||||
the PATH variable.
|
||||
|
||||
.Parameter NonDestructive
|
||||
If present, do not remove this function from the global namespace for the
|
||||
session.
|
||||
|
||||
#>
|
||||
function global:deactivate ([switch]$NonDestructive) {
|
||||
# Revert to original values
|
||||
|
||||
# The prior prompt:
|
||||
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
||||
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
||||
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
||||
}
|
||||
|
||||
# The prior PYTHONHOME:
|
||||
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
||||
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
||||
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
||||
}
|
||||
|
||||
# The prior PATH:
|
||||
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
||||
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
||||
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
||||
}
|
||||
|
||||
# Just remove the VIRTUAL_ENV altogether:
|
||||
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
||||
Remove-Item -Path env:VIRTUAL_ENV
|
||||
}
|
||||
|
||||
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
||||
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
||||
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
||||
}
|
||||
|
||||
# Leave deactivate function in the global namespace if requested:
|
||||
if (-not $NonDestructive) {
|
||||
Remove-Item -Path function:deactivate
|
||||
}
|
||||
}
|
||||
|
||||
<#
|
||||
.Description
|
||||
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
||||
given folder, and returns them in a map.
|
||||
|
||||
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
||||
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
||||
then it is considered a `key = value` line. The left hand string is the key,
|
||||
the right hand is the value.
|
||||
|
||||
If the value starts with a `'` or a `"` then the first and last character is
|
||||
stripped from the value before being captured.
|
||||
|
||||
.Parameter ConfigDir
|
||||
Path to the directory that contains the `pyvenv.cfg` file.
|
||||
#>
|
||||
function Get-PyVenvConfig(
|
||||
[String]
|
||||
$ConfigDir
|
||||
) {
|
||||
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
||||
|
||||
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
||||
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
||||
|
||||
# An empty map will be returned if no config file is found.
|
||||
$pyvenvConfig = @{ }
|
||||
|
||||
if ($pyvenvConfigPath) {
|
||||
|
||||
Write-Verbose "File exists, parse `key = value` lines"
|
||||
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
||||
|
||||
$pyvenvConfigContent | ForEach-Object {
|
||||
$keyval = $PSItem -split "\s*=\s*", 2
|
||||
if ($keyval[0] -and $keyval[1]) {
|
||||
$val = $keyval[1]
|
||||
|
||||
# Remove extraneous quotations around a string value.
|
||||
if ("'""".Contains($val.Substring(0, 1))) {
|
||||
$val = $val.Substring(1, $val.Length - 2)
|
||||
}
|
||||
|
||||
$pyvenvConfig[$keyval[0]] = $val
|
||||
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
||||
}
|
||||
}
|
||||
}
|
||||
return $pyvenvConfig
|
||||
}
|
||||
|
||||
|
||||
<# Begin Activate script --------------------------------------------------- #>
|
||||
|
||||
# Determine the containing directory of this script
|
||||
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
$VenvExecDir = Get-Item -Path $VenvExecPath
|
||||
|
||||
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
||||
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
||||
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
||||
|
||||
# Set values required in priority: CmdLine, ConfigFile, Default
|
||||
# First, get the location of the virtual environment, it might not be
|
||||
# VenvExecDir if specified on the command line.
|
||||
if ($VenvDir) {
|
||||
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
||||
}
|
||||
else {
|
||||
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
||||
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
||||
Write-Verbose "VenvDir=$VenvDir"
|
||||
}
|
||||
|
||||
# Next, read the `pyvenv.cfg` file to determine any required value such
|
||||
# as `prompt`.
|
||||
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
||||
|
||||
# Next, set the prompt from the command line, or the config file, or
|
||||
# just use the name of the virtual environment folder.
|
||||
if ($Prompt) {
|
||||
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
||||
}
|
||||
else {
|
||||
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
||||
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
||||
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
||||
$Prompt = $pyvenvCfg['prompt'];
|
||||
}
|
||||
else {
|
||||
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)"
|
||||
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
||||
$Prompt = Split-Path -Path $venvDir -Leaf
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "Prompt = '$Prompt'"
|
||||
Write-Verbose "VenvDir='$VenvDir'"
|
||||
|
||||
# Deactivate any currently active virtual environment, but leave the
|
||||
# deactivate function in place.
|
||||
deactivate -nondestructive
|
||||
|
||||
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
||||
# that there is an activated venv.
|
||||
$env:VIRTUAL_ENV = $VenvDir
|
||||
|
||||
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
||||
|
||||
Write-Verbose "Setting prompt to '$Prompt'"
|
||||
|
||||
# Set the prompt to include the env name
|
||||
# Make sure _OLD_VIRTUAL_PROMPT is global
|
||||
function global:_OLD_VIRTUAL_PROMPT { "" }
|
||||
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
||||
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
||||
|
||||
function global:prompt {
|
||||
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
||||
_OLD_VIRTUAL_PROMPT
|
||||
}
|
||||
}
|
||||
|
||||
# Clear PYTHONHOME
|
||||
if (Test-Path -Path Env:PYTHONHOME) {
|
||||
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
||||
Remove-Item -Path Env:PYTHONHOME
|
||||
}
|
||||
|
||||
# Add the venv to the PATH
|
||||
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
||||
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
|
@ -0,0 +1,76 @@
|
|||
# This file must be used with "source bin/activate" *from bash*
|
||||
# you cannot run it directly
|
||||
|
||||
deactivate () {
|
||||
# reset old environment variables
|
||||
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||
export PATH
|
||||
unset _OLD_VIRTUAL_PATH
|
||||
fi
|
||||
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||
export PYTHONHOME
|
||||
unset _OLD_VIRTUAL_PYTHONHOME
|
||||
fi
|
||||
|
||||
# This should detect bash and zsh, which have a hash command that must
|
||||
# be called to get it to forget past commands. Without forgetting
|
||||
# past commands the $PATH changes we made may not be respected
|
||||
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
||||
hash -r
|
||||
fi
|
||||
|
||||
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||
export PS1
|
||||
unset _OLD_VIRTUAL_PS1
|
||||
fi
|
||||
|
||||
unset VIRTUAL_ENV
|
||||
if [ ! "${1:-}" = "nondestructive" ] ; then
|
||||
# Self destruct!
|
||||
unset -f deactivate
|
||||
fi
|
||||
}
|
||||
|
||||
# unset irrelevant variables
|
||||
deactivate nondestructive
|
||||
|
||||
VIRTUAL_ENV="/media/Data/data/extension/img_recognition/code/venv"
|
||||
export VIRTUAL_ENV
|
||||
|
||||
_OLD_VIRTUAL_PATH="$PATH"
|
||||
PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
export PATH
|
||||
|
||||
# unset PYTHONHOME if set
|
||||
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||
unset PYTHONHOME
|
||||
fi
|
||||
|
||||
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||
if [ "x(venv) " != x ] ; then
|
||||
PS1="(venv) ${PS1:-}"
|
||||
else
|
||||
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
|
||||
# special case for Aspen magic directories
|
||||
# see https://aspen.io/
|
||||
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
|
||||
else
|
||||
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
|
||||
fi
|
||||
fi
|
||||
export PS1
|
||||
fi
|
||||
|
||||
# This should detect bash and zsh, which have a hash command that must
|
||||
# be called to get it to forget past commands. Without forgetting
|
||||
# past commands the $PATH changes we made may not be respected
|
||||
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
||||
hash -r
|
||||
fi
|
|
@ -0,0 +1,37 @@
|
|||
# This file must be used with "source bin/activate.csh" *from csh*.
|
||||
# You cannot run it directly.
|
||||
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
||||
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||
|
||||
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
|
||||
|
||||
# Unset irrelevant variables.
|
||||
deactivate nondestructive
|
||||
|
||||
setenv VIRTUAL_ENV "/media/Data/data/extension/img_recognition/code/venv"
|
||||
|
||||
set _OLD_VIRTUAL_PATH="$PATH"
|
||||
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
|
||||
|
||||
|
||||
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||
|
||||
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||
if ("venv" != "") then
|
||||
set env_name = "venv"
|
||||
else
|
||||
if (`basename "VIRTUAL_ENV"` == "__") then
|
||||
# special case for Aspen magic directories
|
||||
# see https://aspen.io/
|
||||
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
|
||||
else
|
||||
set env_name = `basename "$VIRTUAL_ENV"`
|
||||
endif
|
||||
endif
|
||||
set prompt = "[$env_name] $prompt"
|
||||
unset env_name
|
||||
endif
|
||||
|
||||
alias pydoc python -m pydoc
|
||||
|
||||
rehash
|
|
@ -0,0 +1,75 @@
|
|||
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
|
||||
# you cannot run it directly
|
||||
|
||||
function deactivate -d "Exit virtualenv and return to normal shell environment"
|
||||
# reset old environment variables
|
||||
if test -n "$_OLD_VIRTUAL_PATH"
|
||||
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||
set -e _OLD_VIRTUAL_PATH
|
||||
end
|
||||
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
||||
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
||||
set -e _OLD_VIRTUAL_PYTHONHOME
|
||||
end
|
||||
|
||||
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||
functions -e fish_prompt
|
||||
set -e _OLD_FISH_PROMPT_OVERRIDE
|
||||
functions -c _old_fish_prompt fish_prompt
|
||||
functions -e _old_fish_prompt
|
||||
end
|
||||
|
||||
set -e VIRTUAL_ENV
|
||||
if test "$argv[1]" != "nondestructive"
|
||||
# Self destruct!
|
||||
functions -e deactivate
|
||||
end
|
||||
end
|
||||
|
||||
# unset irrelevant variables
|
||||
deactivate nondestructive
|
||||
|
||||
set -gx VIRTUAL_ENV "/media/Data/data/extension/img_recognition/code/venv"
|
||||
|
||||
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
|
||||
|
||||
# unset PYTHONHOME if set
|
||||
if set -q PYTHONHOME
|
||||
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
||||
set -e PYTHONHOME
|
||||
end
|
||||
|
||||
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||
# fish uses a function instead of an env var to generate the prompt.
|
||||
|
||||
# save the current fish_prompt function as the function _old_fish_prompt
|
||||
functions -c fish_prompt _old_fish_prompt
|
||||
|
||||
# with the original prompt function renamed, we can override with our own.
|
||||
function fish_prompt
|
||||
# Save the return status of the last command
|
||||
set -l old_status $status
|
||||
|
||||
# Prompt override?
|
||||
if test -n "(venv) "
|
||||
printf "%s%s" "(venv) " (set_color normal)
|
||||
else
|
||||
# ...Otherwise, prepend env
|
||||
set -l _checkbase (basename "$VIRTUAL_ENV")
|
||||
if test $_checkbase = "__"
|
||||
# special case for Aspen magic directories
|
||||
# see https://aspen.io/
|
||||
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
|
||||
else
|
||||
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
|
||||
end
|
||||
end
|
||||
|
||||
# Restore the return status of the previous command.
|
||||
echo "exit $old_status" | .
|
||||
_old_fish_prompt
|
||||
end
|
||||
|
||||
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
#!/media/Data/data/extension/img_recognition/code/venv/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install'
|
||||
__requires__ = 'setuptools==40.8.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('setuptools==40.8.0', 'console_scripts', 'easy_install')()
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
#!/media/Data/data/extension/img_recognition/code/venv/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==40.8.0','console_scripts','easy_install-3.8'
|
||||
__requires__ = 'setuptools==40.8.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('setuptools==40.8.0', 'console_scripts', 'easy_install-3.8')()
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
#!/media/Data/data/extension/img_recognition/code/venv/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip'
|
||||
__requires__ = 'pip==19.0.3'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('pip==19.0.3', 'console_scripts', 'pip')()
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
#!/media/Data/data/extension/img_recognition/code/venv/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3'
|
||||
__requires__ = 'pip==19.0.3'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('pip==19.0.3', 'console_scripts', 'pip3')()
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
#!/media/Data/data/extension/img_recognition/code/venv/bin/python
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==19.0.3','console_scripts','pip3.8'
|
||||
__requires__ = 'pip==19.0.3'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('pip==19.0.3', 'console_scripts', 'pip3.8')()
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
python3.8
|
|
@ -0,0 +1 @@
|
|||
python3.8
|
|
@ -0,0 +1 @@
|
|||
/usr/bin/python3.8
|
|
@ -0,0 +1,2 @@
|
|||
./setuptools-40.8.0-py3.8.egg
|
||||
./pip-19.0.3-py3.8.egg
|
|
@ -0,0 +1,73 @@
|
|||
Metadata-Version: 1.2
|
||||
Name: pip
|
||||
Version: 19.0.3
|
||||
Summary: The PyPA recommended tool for installing Python packages.
|
||||
Home-page: https://pip.pypa.io/
|
||||
Author: The pip developers
|
||||
Author-email: pypa-dev@groups.google.com
|
||||
License: MIT
|
||||
Description: pip - The Python Package Installer
|
||||
==================================
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/pip.svg
|
||||
:target: https://pypi.org/project/pip/
|
||||
|
||||
.. image:: https://readthedocs.org/projects/pip/badge/?version=latest
|
||||
:target: https://pip.pypa.io/en/latest
|
||||
|
||||
pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
|
||||
|
||||
Please take a look at our documentation for how to install and use pip:
|
||||
|
||||
* `Installation`_
|
||||
* `Usage`_
|
||||
* `Release notes`_
|
||||
|
||||
If you find bugs, need help, or want to talk to the developers please use our mailing lists or chat rooms:
|
||||
|
||||
* `Issue tracking`_
|
||||
* `Discourse channel`_
|
||||
* `User IRC`_
|
||||
|
||||
If you want to get involved head over to GitHub to get the source code and feel free to jump on the developer mailing lists and chat rooms:
|
||||
|
||||
* `GitHub page`_
|
||||
* `Dev mailing list`_
|
||||
* `Dev IRC`_
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
|
||||
Everyone interacting in the pip project's codebases, issue trackers, chat
|
||||
rooms, and mailing lists is expected to follow the `PyPA Code of Conduct`_.
|
||||
|
||||
.. _package installer: https://packaging.python.org/en/latest/current/
|
||||
.. _Python Package Index: https://pypi.org
|
||||
.. _Installation: https://pip.pypa.io/en/stable/installing.html
|
||||
.. _Usage: https://pip.pypa.io/en/stable/
|
||||
.. _Release notes: https://pip.pypa.io/en/stable/news.html
|
||||
.. _GitHub page: https://github.com/pypa/pip
|
||||
.. _Issue tracking: https://github.com/pypa/pip/issues
|
||||
.. _Discourse channel: https://discuss.python.org/c/packaging
|
||||
.. _Dev mailing list: https://groups.google.com/forum/#!forum/pypa-dev
|
||||
.. _User IRC: https://webchat.freenode.net/?channels=%23pypa
|
||||
.. _Dev IRC: https://webchat.freenode.net/?channels=%23pypa-dev
|
||||
.. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/
|
||||
|
||||
Keywords: distutils easy_install egg setuptools wheel virtualenv
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Topic :: Software Development :: Build Tools
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
|
|
@ -0,0 +1,391 @@
|
|||
AUTHORS.txt
|
||||
LICENSE.txt
|
||||
MANIFEST.in
|
||||
NEWS.rst
|
||||
README.rst
|
||||
pyproject.toml
|
||||
setup.cfg
|
||||
setup.py
|
||||
docs/pip_sphinxext.py
|
||||
docs/html/conf.py
|
||||
docs/html/cookbook.rst
|
||||
docs/html/index.rst
|
||||
docs/html/installing.rst
|
||||
docs/html/logic.rst
|
||||
docs/html/news.rst
|
||||
docs/html/quickstart.rst
|
||||
docs/html/usage.rst
|
||||
docs/html/user_guide.rst
|
||||
docs/html/development/configuration.rst
|
||||
docs/html/development/contributing.rst
|
||||
docs/html/development/getting-started.rst
|
||||
docs/html/development/index.rst
|
||||
docs/html/development/release-process.rst
|
||||
docs/html/development/vendoring-policy.rst
|
||||
docs/html/reference/index.rst
|
||||
docs/html/reference/pip.rst
|
||||
docs/html/reference/pip_check.rst
|
||||
docs/html/reference/pip_config.rst
|
||||
docs/html/reference/pip_download.rst
|
||||
docs/html/reference/pip_freeze.rst
|
||||
docs/html/reference/pip_hash.rst
|
||||
docs/html/reference/pip_install.rst
|
||||
docs/html/reference/pip_list.rst
|
||||
docs/html/reference/pip_search.rst
|
||||
docs/html/reference/pip_show.rst
|
||||
docs/html/reference/pip_uninstall.rst
|
||||
docs/html/reference/pip_wheel.rst
|
||||
docs/man/index.rst
|
||||
docs/man/commands/check.rst
|
||||
docs/man/commands/config.rst
|
||||
docs/man/commands/download.rst
|
||||
docs/man/commands/freeze.rst
|
||||
docs/man/commands/hash.rst
|
||||
docs/man/commands/help.rst
|
||||
docs/man/commands/install.rst
|
||||
docs/man/commands/list.rst
|
||||
docs/man/commands/search.rst
|
||||
docs/man/commands/show.rst
|
||||
docs/man/commands/uninstall.rst
|
||||
docs/man/commands/wheel.rst
|
||||
src/pip/__init__.py
|
||||
src/pip/__main__.py
|
||||
src/pip.egg-info/PKG-INFO
|
||||
src/pip.egg-info/SOURCES.txt
|
||||
src/pip.egg-info/dependency_links.txt
|
||||
src/pip.egg-info/entry_points.txt
|
||||
src/pip.egg-info/not-zip-safe
|
||||
src/pip.egg-info/top_level.txt
|
||||
src/pip/_internal/__init__.py
|
||||
src/pip/_internal/build_env.py
|
||||
src/pip/_internal/cache.py
|
||||
src/pip/_internal/configuration.py
|
||||
src/pip/_internal/download.py
|
||||
src/pip/_internal/exceptions.py
|
||||
src/pip/_internal/index.py
|
||||
src/pip/_internal/locations.py
|
||||
src/pip/_internal/pep425tags.py
|
||||
src/pip/_internal/pyproject.py
|
||||
src/pip/_internal/resolve.py
|
||||
src/pip/_internal/wheel.py
|
||||
src/pip/_internal/cli/__init__.py
|
||||
src/pip/_internal/cli/autocompletion.py
|
||||
src/pip/_internal/cli/base_command.py
|
||||
src/pip/_internal/cli/cmdoptions.py
|
||||
src/pip/_internal/cli/main_parser.py
|
||||
src/pip/_internal/cli/parser.py
|
||||
src/pip/_internal/cli/status_codes.py
|
||||
src/pip/_internal/commands/__init__.py
|
||||
src/pip/_internal/commands/check.py
|
||||
src/pip/_internal/commands/completion.py
|
||||
src/pip/_internal/commands/configuration.py
|
||||
src/pip/_internal/commands/download.py
|
||||
src/pip/_internal/commands/freeze.py
|
||||
src/pip/_internal/commands/hash.py
|
||||
src/pip/_internal/commands/help.py
|
||||
src/pip/_internal/commands/install.py
|
||||
src/pip/_internal/commands/list.py
|
||||
src/pip/_internal/commands/search.py
|
||||
src/pip/_internal/commands/show.py
|
||||
src/pip/_internal/commands/uninstall.py
|
||||
src/pip/_internal/commands/wheel.py
|
||||
src/pip/_internal/models/__init__.py
|
||||
src/pip/_internal/models/candidate.py
|
||||
src/pip/_internal/models/format_control.py
|
||||
src/pip/_internal/models/index.py
|
||||
src/pip/_internal/models/link.py
|
||||
src/pip/_internal/operations/__init__.py
|
||||
src/pip/_internal/operations/check.py
|
||||
src/pip/_internal/operations/freeze.py
|
||||
src/pip/_internal/operations/prepare.py
|
||||
src/pip/_internal/req/__init__.py
|
||||
src/pip/_internal/req/constructors.py
|
||||
src/pip/_internal/req/req_file.py
|
||||
src/pip/_internal/req/req_install.py
|
||||
src/pip/_internal/req/req_set.py
|
||||
src/pip/_internal/req/req_tracker.py
|
||||
src/pip/_internal/req/req_uninstall.py
|
||||
src/pip/_internal/utils/__init__.py
|
||||
src/pip/_internal/utils/appdirs.py
|
||||
src/pip/_internal/utils/compat.py
|
||||
src/pip/_internal/utils/deprecation.py
|
||||
src/pip/_internal/utils/encoding.py
|
||||
src/pip/_internal/utils/filesystem.py
|
||||
src/pip/_internal/utils/glibc.py
|
||||
src/pip/_internal/utils/hashes.py
|
||||
src/pip/_internal/utils/logging.py
|
||||
src/pip/_internal/utils/misc.py
|
||||
src/pip/_internal/utils/models.py
|
||||
src/pip/_internal/utils/outdated.py
|
||||
src/pip/_internal/utils/packaging.py
|
||||
src/pip/_internal/utils/setuptools_build.py
|
||||
src/pip/_internal/utils/temp_dir.py
|
||||
src/pip/_internal/utils/typing.py
|
||||
src/pip/_internal/utils/ui.py
|
||||
src/pip/_internal/vcs/__init__.py
|
||||
src/pip/_internal/vcs/bazaar.py
|
||||
src/pip/_internal/vcs/git.py
|
||||
src/pip/_internal/vcs/mercurial.py
|
||||
src/pip/_internal/vcs/subversion.py
|
||||
src/pip/_vendor/README.rst
|
||||
src/pip/_vendor/__init__.py
|
||||
src/pip/_vendor/appdirs.LICENSE.txt
|
||||
src/pip/_vendor/appdirs.py
|
||||
src/pip/_vendor/distro.LICENSE
|
||||
src/pip/_vendor/distro.py
|
||||
src/pip/_vendor/ipaddress.LICENSE
|
||||
src/pip/_vendor/ipaddress.py
|
||||
src/pip/_vendor/pyparsing.LICENSE
|
||||
src/pip/_vendor/pyparsing.py
|
||||
src/pip/_vendor/retrying.LICENSE
|
||||
src/pip/_vendor/retrying.py
|
||||
src/pip/_vendor/six.LICENSE
|
||||
src/pip/_vendor/six.py
|
||||
src/pip/_vendor/vendor.txt
|
||||
src/pip/_vendor/cachecontrol/LICENSE.txt
|
||||
src/pip/_vendor/cachecontrol/__init__.py
|
||||
src/pip/_vendor/cachecontrol/_cmd.py
|
||||
src/pip/_vendor/cachecontrol/adapter.py
|
||||
src/pip/_vendor/cachecontrol/cache.py
|
||||
src/pip/_vendor/cachecontrol/compat.py
|
||||
src/pip/_vendor/cachecontrol/controller.py
|
||||
src/pip/_vendor/cachecontrol/filewrapper.py
|
||||
src/pip/_vendor/cachecontrol/heuristics.py
|
||||
src/pip/_vendor/cachecontrol/serialize.py
|
||||
src/pip/_vendor/cachecontrol/wrapper.py
|
||||
src/pip/_vendor/cachecontrol/caches/__init__.py
|
||||
src/pip/_vendor/cachecontrol/caches/file_cache.py
|
||||
src/pip/_vendor/cachecontrol/caches/redis_cache.py
|
||||
src/pip/_vendor/certifi/LICENSE
|
||||
src/pip/_vendor/certifi/__init__.py
|
||||
src/pip/_vendor/certifi/__main__.py
|
||||
src/pip/_vendor/certifi/cacert.pem
|
||||
src/pip/_vendor/certifi/core.py
|
||||
src/pip/_vendor/chardet/LICENSE
|
||||
src/pip/_vendor/chardet/__init__.py
|
||||
src/pip/_vendor/chardet/big5freq.py
|
||||
src/pip/_vendor/chardet/big5prober.py
|
||||
src/pip/_vendor/chardet/chardistribution.py
|
||||
src/pip/_vendor/chardet/charsetgroupprober.py
|
||||
src/pip/_vendor/chardet/charsetprober.py
|
||||
src/pip/_vendor/chardet/codingstatemachine.py
|
||||
src/pip/_vendor/chardet/compat.py
|
||||
src/pip/_vendor/chardet/cp949prober.py
|
||||
src/pip/_vendor/chardet/enums.py
|
||||
src/pip/_vendor/chardet/escprober.py
|
||||
src/pip/_vendor/chardet/escsm.py
|
||||
src/pip/_vendor/chardet/eucjpprober.py
|
||||
src/pip/_vendor/chardet/euckrfreq.py
|
||||
src/pip/_vendor/chardet/euckrprober.py
|
||||
src/pip/_vendor/chardet/euctwfreq.py
|
||||
src/pip/_vendor/chardet/euctwprober.py
|
||||
src/pip/_vendor/chardet/gb2312freq.py
|
||||
src/pip/_vendor/chardet/gb2312prober.py
|
||||
src/pip/_vendor/chardet/hebrewprober.py
|
||||
src/pip/_vendor/chardet/jisfreq.py
|
||||
src/pip/_vendor/chardet/jpcntx.py
|
||||
src/pip/_vendor/chardet/langbulgarianmodel.py
|
||||
src/pip/_vendor/chardet/langcyrillicmodel.py
|
||||
src/pip/_vendor/chardet/langgreekmodel.py
|
||||
src/pip/_vendor/chardet/langhebrewmodel.py
|
||||
src/pip/_vendor/chardet/langhungarianmodel.py
|
||||
src/pip/_vendor/chardet/langthaimodel.py
|
||||
src/pip/_vendor/chardet/langturkishmodel.py
|
||||
src/pip/_vendor/chardet/latin1prober.py
|
||||
src/pip/_vendor/chardet/mbcharsetprober.py
|
||||
src/pip/_vendor/chardet/mbcsgroupprober.py
|
||||
src/pip/_vendor/chardet/mbcssm.py
|
||||
src/pip/_vendor/chardet/sbcharsetprober.py
|
||||
src/pip/_vendor/chardet/sbcsgroupprober.py
|
||||
src/pip/_vendor/chardet/sjisprober.py
|
||||
src/pip/_vendor/chardet/universaldetector.py
|
||||
src/pip/_vendor/chardet/utf8prober.py
|
||||
src/pip/_vendor/chardet/version.py
|
||||
src/pip/_vendor/chardet/cli/__init__.py
|
||||
src/pip/_vendor/chardet/cli/chardetect.py
|
||||
src/pip/_vendor/colorama/LICENSE.txt
|
||||
src/pip/_vendor/colorama/__init__.py
|
||||
src/pip/_vendor/colorama/ansi.py
|
||||
src/pip/_vendor/colorama/ansitowin32.py
|
||||
src/pip/_vendor/colorama/initialise.py
|
||||
src/pip/_vendor/colorama/win32.py
|
||||
src/pip/_vendor/colorama/winterm.py
|
||||
src/pip/_vendor/distlib/LICENSE.txt
|
||||
src/pip/_vendor/distlib/__init__.py
|
||||
src/pip/_vendor/distlib/compat.py
|
||||
src/pip/_vendor/distlib/database.py
|
||||
src/pip/_vendor/distlib/index.py
|
||||
src/pip/_vendor/distlib/locators.py
|
||||
src/pip/_vendor/distlib/manifest.py
|
||||
src/pip/_vendor/distlib/markers.py
|
||||
src/pip/_vendor/distlib/metadata.py
|
||||
src/pip/_vendor/distlib/resources.py
|
||||
src/pip/_vendor/distlib/scripts.py
|
||||
src/pip/_vendor/distlib/t32.exe
|
||||
src/pip/_vendor/distlib/t64.exe
|
||||
src/pip/_vendor/distlib/util.py
|
||||
src/pip/_vendor/distlib/version.py
|
||||
src/pip/_vendor/distlib/w32.exe
|
||||
src/pip/_vendor/distlib/w64.exe
|
||||
src/pip/_vendor/distlib/wheel.py
|
||||
src/pip/_vendor/distlib/_backport/__init__.py
|
||||
src/pip/_vendor/distlib/_backport/misc.py
|
||||
src/pip/_vendor/distlib/_backport/shutil.py
|
||||
src/pip/_vendor/distlib/_backport/sysconfig.cfg
|
||||
src/pip/_vendor/distlib/_backport/sysconfig.py
|
||||
src/pip/_vendor/distlib/_backport/tarfile.py
|
||||
src/pip/_vendor/html5lib/LICENSE
|
||||
src/pip/_vendor/html5lib/__init__.py
|
||||
src/pip/_vendor/html5lib/_ihatexml.py
|
||||
src/pip/_vendor/html5lib/_inputstream.py
|
||||
src/pip/_vendor/html5lib/_tokenizer.py
|
||||
src/pip/_vendor/html5lib/_utils.py
|
||||
src/pip/_vendor/html5lib/constants.py
|
||||
src/pip/_vendor/html5lib/html5parser.py
|
||||
src/pip/_vendor/html5lib/serializer.py
|
||||
src/pip/_vendor/html5lib/_trie/__init__.py
|
||||
src/pip/_vendor/html5lib/_trie/_base.py
|
||||
src/pip/_vendor/html5lib/_trie/datrie.py
|
||||
src/pip/_vendor/html5lib/_trie/py.py
|
||||
src/pip/_vendor/html5lib/filters/__init__.py
|
||||
src/pip/_vendor/html5lib/filters/alphabeticalattributes.py
|
||||
src/pip/_vendor/html5lib/filters/base.py
|
||||
src/pip/_vendor/html5lib/filters/inject_meta_charset.py
|
||||
src/pip/_vendor/html5lib/filters/lint.py
|
||||
src/pip/_vendor/html5lib/filters/optionaltags.py
|
||||
src/pip/_vendor/html5lib/filters/sanitizer.py
|
||||
src/pip/_vendor/html5lib/filters/whitespace.py
|
||||
src/pip/_vendor/html5lib/treeadapters/__init__.py
|
||||
src/pip/_vendor/html5lib/treeadapters/genshi.py
|
||||
src/pip/_vendor/html5lib/treeadapters/sax.py
|
||||
src/pip/_vendor/html5lib/treebuilders/__init__.py
|
||||
src/pip/_vendor/html5lib/treebuilders/base.py
|
||||
src/pip/_vendor/html5lib/treebuilders/dom.py
|
||||
src/pip/_vendor/html5lib/treebuilders/etree.py
|
||||
src/pip/_vendor/html5lib/treebuilders/etree_lxml.py
|
||||
src/pip/_vendor/html5lib/treewalkers/__init__.py
|
||||
src/pip/_vendor/html5lib/treewalkers/base.py
|
||||
src/pip/_vendor/html5lib/treewalkers/dom.py
|
||||
src/pip/_vendor/html5lib/treewalkers/etree.py
|
||||
src/pip/_vendor/html5lib/treewalkers/etree_lxml.py
|
||||
src/pip/_vendor/html5lib/treewalkers/genshi.py
|
||||
src/pip/_vendor/idna/LICENSE.rst
|
||||
src/pip/_vendor/idna/__init__.py
|
||||
src/pip/_vendor/idna/codec.py
|
||||
src/pip/_vendor/idna/compat.py
|
||||
src/pip/_vendor/idna/core.py
|
||||
src/pip/_vendor/idna/idnadata.py
|
||||
src/pip/_vendor/idna/intranges.py
|
||||
src/pip/_vendor/idna/package_data.py
|
||||
src/pip/_vendor/idna/uts46data.py
|
||||
src/pip/_vendor/lockfile/LICENSE
|
||||
src/pip/_vendor/lockfile/__init__.py
|
||||
src/pip/_vendor/lockfile/linklockfile.py
|
||||
src/pip/_vendor/lockfile/mkdirlockfile.py
|
||||
src/pip/_vendor/lockfile/pidlockfile.py
|
||||
src/pip/_vendor/lockfile/sqlitelockfile.py
|
||||
src/pip/_vendor/lockfile/symlinklockfile.py
|
||||
src/pip/_vendor/msgpack/COPYING
|
||||
src/pip/_vendor/msgpack/__init__.py
|
||||
src/pip/_vendor/msgpack/_version.py
|
||||
src/pip/_vendor/msgpack/exceptions.py
|
||||
src/pip/_vendor/msgpack/fallback.py
|
||||
src/pip/_vendor/packaging/LICENSE
|
||||
src/pip/_vendor/packaging/LICENSE.APACHE
|
||||
src/pip/_vendor/packaging/LICENSE.BSD
|
||||
src/pip/_vendor/packaging/__about__.py
|
||||
src/pip/_vendor/packaging/__init__.py
|
||||
src/pip/_vendor/packaging/_compat.py
|
||||
src/pip/_vendor/packaging/_structures.py
|
||||
src/pip/_vendor/packaging/markers.py
|
||||
src/pip/_vendor/packaging/requirements.py
|
||||
src/pip/_vendor/packaging/specifiers.py
|
||||
src/pip/_vendor/packaging/utils.py
|
||||
src/pip/_vendor/packaging/version.py
|
||||
src/pip/_vendor/pep517/LICENSE
|
||||
src/pip/_vendor/pep517/__init__.py
|
||||
src/pip/_vendor/pep517/_in_process.py
|
||||
src/pip/_vendor/pep517/build.py
|
||||
src/pip/_vendor/pep517/check.py
|
||||
src/pip/_vendor/pep517/colorlog.py
|
||||
src/pip/_vendor/pep517/compat.py
|
||||
src/pip/_vendor/pep517/envbuild.py
|
||||
src/pip/_vendor/pep517/wrappers.py
|
||||
src/pip/_vendor/pkg_resources/LICENSE
|
||||
src/pip/_vendor/pkg_resources/__init__.py
|
||||
src/pip/_vendor/pkg_resources/py31compat.py
|
||||
src/pip/_vendor/progress/LICENSE
|
||||
src/pip/_vendor/progress/__init__.py
|
||||
src/pip/_vendor/progress/bar.py
|
||||
src/pip/_vendor/progress/counter.py
|
||||
src/pip/_vendor/progress/helpers.py
|
||||
src/pip/_vendor/progress/spinner.py
|
||||
src/pip/_vendor/pytoml/LICENSE
|
||||
src/pip/_vendor/pytoml/__init__.py
|
||||
src/pip/_vendor/pytoml/core.py
|
||||
src/pip/_vendor/pytoml/parser.py
|
||||
src/pip/_vendor/pytoml/test.py
|
||||
src/pip/_vendor/pytoml/utils.py
|
||||
src/pip/_vendor/pytoml/writer.py
|
||||
src/pip/_vendor/requests/LICENSE
|
||||
src/pip/_vendor/requests/__init__.py
|
||||
src/pip/_vendor/requests/__version__.py
|
||||
src/pip/_vendor/requests/_internal_utils.py
|
||||
src/pip/_vendor/requests/adapters.py
|
||||
src/pip/_vendor/requests/api.py
|
||||
src/pip/_vendor/requests/auth.py
|
||||
src/pip/_vendor/requests/certs.py
|
||||
src/pip/_vendor/requests/compat.py
|
||||
src/pip/_vendor/requests/cookies.py
|
||||
src/pip/_vendor/requests/exceptions.py
|
||||
src/pip/_vendor/requests/help.py
|
||||
src/pip/_vendor/requests/hooks.py
|
||||
src/pip/_vendor/requests/models.py
|
||||
src/pip/_vendor/requests/packages.py
|
||||
src/pip/_vendor/requests/sessions.py
|
||||
src/pip/_vendor/requests/status_codes.py
|
||||
src/pip/_vendor/requests/structures.py
|
||||
src/pip/_vendor/requests/utils.py
|
||||
src/pip/_vendor/urllib3/LICENSE.txt
|
||||
src/pip/_vendor/urllib3/__init__.py
|
||||
src/pip/_vendor/urllib3/_collections.py
|
||||
src/pip/_vendor/urllib3/connection.py
|
||||
src/pip/_vendor/urllib3/connectionpool.py
|
||||
src/pip/_vendor/urllib3/exceptions.py
|
||||
src/pip/_vendor/urllib3/fields.py
|
||||
src/pip/_vendor/urllib3/filepost.py
|
||||
src/pip/_vendor/urllib3/poolmanager.py
|
||||
src/pip/_vendor/urllib3/request.py
|
||||
src/pip/_vendor/urllib3/response.py
|
||||
src/pip/_vendor/urllib3/contrib/__init__.py
|
||||
src/pip/_vendor/urllib3/contrib/_appengine_environ.py
|
||||
src/pip/_vendor/urllib3/contrib/appengine.py
|
||||
src/pip/_vendor/urllib3/contrib/ntlmpool.py
|
||||
src/pip/_vendor/urllib3/contrib/pyopenssl.py
|
||||
src/pip/_vendor/urllib3/contrib/securetransport.py
|
||||
src/pip/_vendor/urllib3/contrib/socks.py
|
||||
src/pip/_vendor/urllib3/contrib/_securetransport/__init__.py
|
||||
src/pip/_vendor/urllib3/contrib/_securetransport/bindings.py
|
||||
src/pip/_vendor/urllib3/contrib/_securetransport/low_level.py
|
||||
src/pip/_vendor/urllib3/packages/__init__.py
|
||||
src/pip/_vendor/urllib3/packages/six.py
|
||||
src/pip/_vendor/urllib3/packages/backports/__init__.py
|
||||
src/pip/_vendor/urllib3/packages/backports/makefile.py
|
||||
src/pip/_vendor/urllib3/packages/ssl_match_hostname/__init__.py
|
||||
src/pip/_vendor/urllib3/packages/ssl_match_hostname/_implementation.py
|
||||
src/pip/_vendor/urllib3/util/__init__.py
|
||||
src/pip/_vendor/urllib3/util/connection.py
|
||||
src/pip/_vendor/urllib3/util/queue.py
|
||||
src/pip/_vendor/urllib3/util/request.py
|
||||
src/pip/_vendor/urllib3/util/response.py
|
||||
src/pip/_vendor/urllib3/util/retry.py
|
||||
src/pip/_vendor/urllib3/util/ssl_.py
|
||||
src/pip/_vendor/urllib3/util/timeout.py
|
||||
src/pip/_vendor/urllib3/util/url.py
|
||||
src/pip/_vendor/urllib3/util/wait.py
|
||||
src/pip/_vendor/webencodings/LICENSE
|
||||
src/pip/_vendor/webencodings/__init__.py
|
||||
src/pip/_vendor/webencodings/labels.py
|
||||
src/pip/_vendor/webencodings/mklabels.py
|
||||
src/pip/_vendor/webencodings/tests.py
|
||||
src/pip/_vendor/webencodings/x_user_defined.py
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
[console_scripts]
|
||||
pip = pip._internal:main
|
||||
pip3 = pip._internal:main
|
||||
pip3.8 = pip._internal:main
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1 @@
|
|||
pip
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue