Skip to content

Instantly share code, notes, and snippets.

@fanyix
Last active November 6, 2018 20:20
Show Gist options
  • Save fanyix/b9c0188aa598b265b18c73a9ad43d9ca to your computer and use it in GitHub Desktop.
Save fanyix/b9c0188aa598b265b18c73a9ad43d9ca to your computer and use it in GitHub Desktop.
demo for generating html page
# import _init_paths
import os
import re
import numpy as np
import math
import time
from PIL import Image
from scipy import misc
from skimage.draw import line_aa
def bbox_intersection(bb1, bb2):
x_left = max(bb1[0], bb2[0])
y_top = max(bb1[1], bb2[1])
x_right = min(bb1[2], bb2[2])
y_bottom = min(bb1[3], bb2[3])
if x_right < x_left or y_bottom < y_top:
return 0.0
area = (y_bottom - y_top + 1) * (x_right - x_left + 1)
return area
def bbox_transform(ex_rois, gt_rois):
reshaped = False
if ex_rois.ndim == 1 or gt_rois.ndim == 1:
ex_rois = ex_rois.reshape(1, 4)
gt_rois = gt_rois.reshape(1, 4)
reshaped = True
ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0
ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0
ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths
ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights
gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0
gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0
gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths
gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights
targets_dx = (gt_ctr_x - ex_ctr_x) / ex_widths
targets_dy = (gt_ctr_y - ex_ctr_y) / ex_heights
targets_dw = np.log(gt_widths / ex_widths)
targets_dh = np.log(gt_heights / ex_heights)
targets = np.vstack(
(targets_dx, targets_dy, targets_dw, targets_dh)).transpose()
if reshaped:
targets = targets.reshape(-1)
return targets
def bbox_transform_inv(boxes, deltas):
if boxes.shape[0] == 0:
return np.zeros((0, deltas.shape[1]), dtype=deltas.dtype)
reshaped = False
if boxes.ndim == 1 or deltas.ndim == 1:
boxes = boxes.reshape(1, 4)
deltas = deltas.reshape(1, 4)
reshaped = True
boxes = boxes.astype(deltas.dtype, copy=False)
widths = boxes[:, 2] - boxes[:, 0] + 1.0
heights = boxes[:, 3] - boxes[:, 1] + 1.0
ctr_x = boxes[:, 0] + 0.5 * widths
ctr_y = boxes[:, 1] + 0.5 * heights
dx = deltas[:, 0::4]
dy = deltas[:, 1::4]
dw = deltas[:, 2::4]
dh = deltas[:, 3::4]
pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]
pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]
pred_w = np.exp(dw) * widths[:, np.newaxis]
pred_h = np.exp(dh) * heights[:, np.newaxis]
pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype)
# x1
pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w
# y1
pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h
# x2
pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w
# y2
pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h
if reshaped:
pred_boxes = pred_boxes.reshape(-1)
return pred_boxes
class Args():
def __init__(self):
assert True
def rand_range(a, b):
x = np.random.rand()
y = x * (b - a) + a
return y
def relative_coord(box, ref_box, size):
# get height and width
hgt = size[0]
wid = size[1]
ref_wid = ref_box[2] - ref_box[0]
ref_hgt = ref_box[3] - ref_box[1]
# compute the relative coords
x1 = float(box[0]-ref_box[0]) / ref_wid * wid
y1 = float(box[1]-ref_box[1]) / ref_hgt * hgt
x2 = float(box[2]-ref_box[0]) / ref_wid * wid
y2 = float(box[3]-ref_box[1]) / ref_hgt * hgt
rel_box = np.array([x1, y1, x2, y2])
return rel_box
def crop_patch(I, box, pad_color):
img_wid = I.size[0]
img_hgt = I.size[1]
clip_box = calibrate_box(box, img_wid, img_hgt)
clip_crop = I.crop(clip_box)
R = pad_color[0]
G = pad_color[1]
B = pad_color[2]
wid = int(box[2] - box[0])
hgt = int(box[3] - box[1])
frame_size = [wid, hgt]
offset_x = int(max(-box[0], 0))
offset_y = int(max(-box[1], 0))
offset_tuple = (offset_x, offset_y) #pack x and y into a tuple
final_crop = Image.new(mode='RGB',size=frame_size,color=(R,G,B))
final_crop.paste(clip_crop, offset_tuple)
return final_crop
def rand_crop(box, min_ratio):
# crop a patch out from a box, that is at least min_ratio*size large
wid = box[2] - box[0] + 1
hgt = box[3] - box[1] + 1
ratio = rand_range(min_ratio, 1.0)
crop_wid = int(wid * ratio)
crop_hgt = int(hgt * ratio)
# x1
low = int(box[0])
high = int(box[2] - crop_wid + 1)
if high > low:
x1 = np.random.randint(low, high)
else:
x1 = low
# y1
low = int(box[1])
high = int(box[3] - crop_hgt + 1)
if high > low:
y1 = np.random.randint(low, high)
else:
y1 = low
x2 = x1 + crop_wid - 1
y2 = y1 + crop_hgt - 1
crop_box = np.array([x1, y1, x2, y2])
return crop_box
def expand_box(box, ratio):
wid = box[2] - box[0]
hgt = box[3] - box[1]
x_center = (box[2] + box[0]) / 2.0
y_center = (box[3] + box[1]) / 2.0
context_wid = wid * ratio
context_hgt = hgt * ratio
x1 = x_center - context_wid / 2.0
x2 = x_center + context_wid / 2.0
y1 = y_center - context_hgt / 2.0
y2 = y_center + context_hgt / 2.0
context_box = np.array([x1, y1, x2, y2])
return context_box
def box_rel_to_abs(box, wid, hgt):
if box.ndim == 1:
box[0] = box[0] * wid
box[2] = box[2] * wid
box[1] = box[1] * hgt
box[3] = box[3] * hgt
else:
box[:, 0] = box[:, 0] * wid
box[:, 2] = box[:, 2] * wid
box[:, 1] = box[:, 1] * hgt
box[:, 3] = box[:, 3] * hgt
return box
def sigmoid(x):
y = 1.0 / (1 + np.exp(-x))
return y
def read_or_block(filename):
while True:
if os.path.isfile(filename):
break
time.sleep(5)
# we had the file now
time.sleep(5)
res = np.load(filename)
return res
def mkdir_imwrite(fig2, img_path):
path, filename = os.path.split(img_path)
if not os.path.isdir(path):
os.makedirs(path)
fig2.savefig(img_path)
def initHTML(row_n, col_n):
im_paths = [['NA'] * col_n for idx in range(row_n)]
captions = [['NA'] * col_n for idx in range(row_n)]
return im_paths, captions
def writeHTML(file_name, im_paths, captions, height=200, width=200):
f=open(file_name, 'w')
html=[]
f.write('<!DOCTYPE html>\n')
f.write('<html><body>\n')
f.write('<table>\n')
for row in range(len(im_paths)):
f.write('<tr>\n')
for col in range(len(im_paths[row])):
f.write('<td>')
f.write(captions[row][col])
f.write('</td>')
f.write(' ')
f.write('\n</tr>\n')
f.write('<tr>\n')
for col in range(len(im_paths[row])):
f.write('<td><img src="')
f.write(im_paths[row][col])
f.write('" height='+str(height)+' width='+str(width)+'"/></td>')
f.write(' ')
f.write('\n</tr>\n')
f.write('<p></p>')
f.write('</table>\n')
f.close()
def writeSeqHTML(file_name, im_paths, captions, col_n, height=200, width=200):
total_n = len(im_paths)
row_n = int(math.ceil(float(total_n) / col_n))
f=open(file_name, 'w')
html=[]
f.write('<!DOCTYPE html>\n')
f.write('<html><body>\n')
f.write('<table>\n')
for row in range(row_n):
base_count = row * col_n
f.write('<tr>\n')
for col in range(col_n):
if base_count + col < total_n:
f.write('<td>')
f.write(captions[base_count + col])
f.write('</td>')
f.write(' ')
f.write('\n</tr>\n')
f.write('<tr>\n')
for col in range(col_n):
if base_count + col < total_n:
f.write('<td><img src="')
f.write(im_paths[base_count + col])
f.write('" height='+str(height)+' width='+str(width)+'"/></td>')
f.write(' ')
f.write('\n</tr>\n')
f.write('<p></p>')
f.write('</table>\n')
f.close()
def flip_box(box, wid):
flipped_box = box.copy()
if flipped_box.ndim == 1:
start = flipped_box[0]
flipped_box[0] = wid - flipped_box[2]
flipped_box[2] = wid - start
else:
start = flipped_box[:, 0].copy()
flipped_box[:, 0] = wid - flipped_box[:, 2]
flipped_box[:, 2] = wid - start
return flipped_box
def normalize_coord(x, size):
return float(x) / size * 2 - 1
def shear_and_rotate(shr=0.1, rot=math.pi/4):
sh_x = rand_range(-shr,shr)
sh_y = rand_range(-shr,shr)
sh_theta = np.array([1,sh_y,0,
sh_x,1,0,
0,0,1]).reshape(3, 3)
rot_angle = rand_range(-rot,rot)
cos = math.cos(rot_angle)
sin = math.sin(rot_angle)
rot_theta = np.array([cos,sin,0,
-sin,cos,0,
0,0,1]).reshape(3, 3)
theta = np.matmul(rot_theta, sh_theta)
return theta
def box_to_theta(box, im_wid, im_hgt):
x1 = box[0]
y1 = box[1]
x2 = box[2]
y2 = box[3]
# compute the baseline theta, which gives us exactly the box
norm_x1 = normalize_coord(x1, im_wid)
norm_x2 = normalize_coord(x2, im_wid)
norm_y1 = normalize_coord(y1, im_hgt)
norm_y2 = normalize_coord(y2, im_hgt)
half_wid = (norm_x2 - norm_x1) / 2
x_center = (norm_x2 + norm_x1) / 2
half_hgt = (norm_y2 - norm_y1) / 2
y_center = (norm_y2 + norm_y1) / 2
theta = np.array([half_wid,0,x_center,0,half_hgt,y_center,0,0,1], dtype=np.float).reshape(3, 3)
return theta, half_wid, half_hgt, x_center, y_center
def relative_path(ref_path, target_path):
# common_prefix = os.path.commonprefix([ref_path, target_path])
return os.path.relpath(target_path, ref_path)
def check_tokens(word1, word2):
match = 0
for counter1, token1 in enumerate(word1[0]):
for counter2, token2 in enumerate(word2[0]):
if pattern.search(word1[1][counter1]) != None and \
pattern.search(word2[1][counter2]) != None and \
stemmer.stem(token1) == stemmer.stem(token2):
match += 1
return match
def shape2str(shape):
str = ''
for idx, i in enumerate(shape):
if idx == len(shape)-1:
str += '%d' % i
else:
str += '%d,' % i
return str
def calibrate_box(box, wid, hgt):
new_box = box.copy().astype(np.int)
if box.ndim == 1:
new_box[0] = max(round(box[0]), 0)
new_box[1] = max(round(box[1]), 0)
new_box[2] = min(round(box[2]), wid-1)
new_box[3] = min(round(box[3]), hgt-1)
elif box.ndim == 2:
new_box[:, 0] = np.maximum(np.round(box[:, 0]), 0)
new_box[:, 1] = np.maximum(np.round(box[:, 1]), 0)
new_box[:, 2] = np.minimum(np.round(box[:, 2]), wid-1)
new_box[:, 3] = np.minimum(np.round(box[:, 3]), hgt-1)
return new_box
def softmax(w):
maxes = np.amax(w, axis=1)
maxes = np.tile(maxes[:, np.newaxis], [1, w.shape[1]])
e = np.exp(w - maxes)
dist = e / np.tile(np.sum(e, axis=1)[:, np.newaxis], [1, w.shape[1]])
return dist
def truncate(annot, num):
new_annot = {}
annot_keys = annot.keys()
for idx in range(num):
key = annot_keys[idx]
new_annot[key] = annot[key]
return new_annot
def mkdir_imwrite(fig2, img_path):
path, filename = os.path.split(img_path)
if not os.path.isdir(path):
os.makedirs(path)
fig2.savefig(img_path, bbox_inches='tight', pad_inches=0)
def unique_row(a):
order = np.lexsort(a.T)
a = a[order]
diff = np.diff(a, axis=0)
ui = np.ones(len(a), 'bool')
ui[1:] = (diff != 0).any(axis=1)
ui = order[ui]
return ui
def ismember(a, b, bind = None):
if bind is None:
bind = {}
for i, elt in enumerate(b):
if elt not in bind:
bind[elt] = i
return (np.array([bind.get(itm, -1) for itm in a]), bind) # None can be replaced by any other "not in b" value
def get_data_base(arr):
"""For a given Numpy array, finds the
base array that "owns" the actual data."""
base = arr
while isinstance(base.base, np.ndarray):
base = base.base
return base
def arrays_share_data(x, y):
return get_data_base(x) is get_data_base(y)
v = 1.0
s = 1.0
p = 0.0
def rgbcolor(h, f):
"""Convert a color specified by h-value and f-value to an RGB
three-tuple."""
# q = 1 - f
# t = f
if h == 0:
return v, f, p
elif h == 1:
return 1 - f, v, p
elif h == 2:
return p, v, f
elif h == 3:
return p, 1 - f, v
elif h == 4:
return f, p, v
elif h == 5:
return v, p, 1 - f
def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
def uniquecolors(n):
"""Compute a list of distinct colors, ecah of which is
represented as an RGB three-tuple"""
hues = [360.0 / n * i for i in range(n)]
hs = [math.floor(hue / 60) % 6 for hue in hues]
fs = [hue / 60 - math.floor(hue / 60) for hue in hues]
return [rgbcolor(h, f) for h, f in zip(hs, fs)]
def heatmap_calib(map):
# this only works for numpy
minval = np.min(map)
maxval = np.max(map)
gap = (maxval - minval + 1e-8)
# linear interpolation
map = ((map - minval) / gap)
return map
def tree_to_list(t):
# convert tree to list
if isinstance(t, Tree):
return [t.label()] + map(tree_to_list, t)
else:
return t
## functions for operating a loss recorder
def init_recorder(T):
recorder = {'smoothed_loss_arr' : [], 'raw_loss_arr' : [], 'loss_iter_arr': [], 'ptr' : 0, 'T' : T}
return recorder
def retrieve_loss(struct, start_round):
loss, iter = struct['smoothed_loss_arr'], struct['loss_iter_arr']
return loss, iter
def update_loss(struct, loss, iter):
raw_loss_arr = struct['raw_loss_arr']
smoothed_loss_arr = struct['smoothed_loss_arr']
loss_iter_arr = struct['loss_iter_arr']
T = struct['T']
ptr = struct['ptr']
if len(smoothed_loss_arr) > 0:
smoothed_loss = smoothed_loss_arr[-1]
else:
smoothed_loss = 0
cur_len = len(raw_loss_arr)
if cur_len < T:
smoothed_loss = (smoothed_loss * cur_len + loss) / (cur_len + 1)
raw_loss_arr.append(loss)
else:
smoothed_loss = smoothed_loss + (loss - raw_loss_arr[ptr]) / T
raw_loss_arr[ptr] = loss
ptr = (ptr + 1) % T
smoothed_loss_arr.append(smoothed_loss)
loss_iter_arr.append(iter)
# stuff info into struct
struct['ptr'] = ptr
struct['raw_loss_arr'] = raw_loss_arr
struct['smoothed_loss_arr'] = smoothed_loss_arr
struct['loss_iter_arr'] = loss_iter_arr
return struct
def vis_link(src, tgt, links):
# visualize the link between src and tgt
pic = []
N = src.size(0)
# ship all data to cpu
src = src.cpu().numpy()
tgt = tgt.cpu().numpy()
# loop
out = []
for idx in range(N):
shift = src[idx].shape[2]
whole = np.concatenate((src[idx], tgt[idx]), axis=2)
link = links[idx]
for pair_idx in range(link.size(1)):
src_x, src_y, tgt_x, tgt_y = link[:, pair_idx]
tgt_x += shift
rr, cc, val = line_aa(src_y, src_x, tgt_y, tgt_x)
# val = np.tile(val.reshape(1, -1), (3, 1))
val = np.tile(np.array([0,0,1]).reshape(3, 1), (1, cc.shape[0]))
whole[:, rr, cc] = val
out.append(whole)
return out
### demo for generating html files
import os
import numpy as np
import futils
from scipy.misc import imsave
# params
html_file = 'demo.html' # path of the html file
img_dir = './data' # path to save the images
col = 5 # number of columns to display
N = 20
# init vars
im_paths, captions = [], []
# create dir
if not os.path.exists(img_dir):
os.mkdir(img_dir)
# loop over different images
for idx in range(N):
im_name = os.path.join(img_dir, '%d.png' % idx)
I = np.ndarray((128, 128))
val = int(255.0 / N * idx)
I[:] = val
imsave(im_name, I.astype(np.uint8))
im_paths.append(im_name)
captions.append('color %d' % val)
# write html
futils.writeSeqHTML(html_file, im_paths, captions, col, 200, 200)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment