From c74cbcef8e44206324ca92aaa11e99d75738b750 Mon Sep 17 00:00:00 2001 From: ND Date: Wed, 3 Jan 2018 11:15:28 +0530 Subject: [PATCH 1/5] python 3 port and requirements.txt file --- colorize3_poisson.py | 61 +++++++++++++++++++++++------------------- common.py | 6 ++--- gen.py | 22 +++++++-------- poisson_reconstruct.py | 4 +-- ransac.py | 4 +-- requirements.txt | 13 +++++++++ synth_utils.py | 2 +- synthgen.py | 47 ++++++++++++++++---------------- text_utils.py | 43 +++++++++++++++++------------ 9 files changed, 115 insertions(+), 87 deletions(-) create mode 100644 requirements.txt diff --git a/colorize3_poisson.py b/colorize3_poisson.py index 37ef94a..e4f32af 100644 --- a/colorize3_poisson.py +++ b/colorize3_poisson.py @@ -6,11 +6,12 @@ import scipy.ndimage.interpolation as sii import os import os.path as osp -import cPickle as cp +#import cPickle as cp +import _pickle as cp #import Image from PIL import Image from poisson_reconstruct import blit_images - +import pickle def sample_weighted(p_dict): ps = p_dict.keys() @@ -38,20 +39,24 @@ def __init__(self,alpha,color): elif color.ndim==3: #rgb image self.color = color.copy().astype('uint8') else: - print color.shape + print (color.shape) raise Exception("color datatype not understood") class FontColor(object): def __init__(self, col_file): - with open(col_file,'r') as f: - self.colorsRGB = cp.load(f) + with open(col_file,'rb') as f: + #self.colorsRGB = cp.load(f) + u = pickle._Unpickler(f) + u.encoding = 'latin1' + p = u.load() + self.colorsRGB = p self.ncol = self.colorsRGB.shape[0] # convert color-means from RGB to LAB for better nearest neighbour # computations: self.colorsLAB = np.r_[self.colorsRGB[:,0:3], self.colorsRGB[:,6:9]].astype('uint8') - self.colorsLAB = np.squeeze(cv.cvtColor(self.colorsLAB[None,:,:],cv.cv.CV_RGB2Lab)) + self.colorsLAB = np.squeeze(cv.cvtColor(self.colorsLAB[None,:,:],cv.COLOR_RGB2Lab)) def sample_normal(self, col_mean, col_std): @@ -70,7 +75,7 @@ def sample_from_data(self, bg_mat): each of these is a 3-vector. """ bg_orig = bg_mat.copy() - bg_mat = cv.cvtColor(bg_mat, cv.cv.CV_RGB2Lab) + bg_mat = cv.cvtColor(bg_mat, cv.COLOR_RGB2Lab) bg_mat = np.reshape(bg_mat, (np.prod(bg_mat.shape[:2]),3)) bg_mean = np.mean(bg_mat,axis=0) @@ -92,10 +97,10 @@ def sample_from_data(self, bg_mat): return (col1, col2) def mean_color(self, arr): - col = cv.cvtColor(arr, cv.cv.CV_RGB2HSV) + col = cv.cvtColor(arr, cv.COLOR_RGB2HSV) col = np.reshape(col, (np.prod(col.shape[:2]),3)) col = np.mean(col,axis=0).astype('uint8') - return np.squeeze(cv.cvtColor(col[None,None,:],cv.cv.CV_HSV2RGB)) + return np.squeeze(cv.cvtColor(col[None,None,:],cv.COLOR_HSV2RGB)) def invert(self, rgb): rgb = 127 + rgb @@ -105,9 +110,9 @@ def complement(self, rgb_color): """ return a color which is complementary to the RGB_COLOR. """ - col_hsv = np.squeeze(cv.cvtColor(rgb_color[None,None,:], cv.cv.CV_RGB2HSV)) + col_hsv = np.squeeze(cv.cvtColor(rgb_color[None,None,:], cv.COLOR_RGB2HSV)) col_hsv[0] = col_hsv[0] + 128 #uint8 mods to 255 - col_comp = np.squeeze(cv.cvtColor(col_hsv[None,None,:],cv.cv.CV_HSV2RGB)) + col_comp = np.squeeze(cv.cvtColor(col_hsv[None,None,:],cv.COLOR_HSV2RGB)) return col_comp def triangle_color(self, col1, col2): @@ -115,24 +120,24 @@ def triangle_color(self, col1, col2): Returns a color which is "opposite" to both col1 and col2. """ col1, col2 = np.array(col1), np.array(col2) - col1 = np.squeeze(cv.cvtColor(col1[None,None,:], cv.cv.CV_RGB2HSV)) - col2 = np.squeeze(cv.cvtColor(col2[None,None,:], cv.cv.CV_RGB2HSV)) + col1 = np.squeeze(cv.cvtColor(col1[None,None,:], cv.COLOR_RGB2HSV)) + col2 = np.squeeze(cv.cvtColor(col2[None,None,:], cv.COLOR_RGB2HSV)) h1, h2 = col1[0], col2[0] if h2 < h1 : h1,h2 = h2,h1 #swap dh = h2-h1 if dh < 127: dh = 255-dh col1[0] = h1 + dh/2 - return np.squeeze(cv.cvtColor(col1[None,None,:],cv.cv.CV_HSV2RGB)) + return np.squeeze(cv.cvtColor(col1[None,None,:],cv.COLOR_HSV2RGB)) def change_value(self, col_rgb, v_std=50): - col = np.squeeze(cv.cvtColor(col_rgb[None,None,:], cv.cv.CV_RGB2HSV)) + col = np.squeeze(cv.cvtColor(col_rgb[None,None,:], cv.COLOR_RGB2HSV)) x = col[2] vs = np.linspace(0,1) ps = np.abs(vs - x/255.0) ps /= np.sum(ps) v_rand = np.clip(np.random.choice(vs,p=ps) + 0.1*np.random.randn(),0,1) col[2] = 255*v_rand - return np.squeeze(cv.cvtColor(col[None,None,:],cv.cv.CV_HSV2RGB)) + return np.squeeze(cv.cvtColor(col[None,None,:],cv.COLOR_HSV2RGB)) class Colorize(object): @@ -253,7 +258,7 @@ def color_border(self, col_text, col_bg): """ choice = np.random.choice(3) - col_text = cv.cvtColor(col_text, cv.cv.CV_RGB2HSV) + col_text = cv.cvtColor(col_text, cv.COLOR_RGB2HSV) col_text = np.reshape(col_text, (np.prod(col_text.shape[:2]),3)) col_text = np.mean(col_text,axis=0).astype('uint8') @@ -268,24 +273,24 @@ def get_sample(x): if choice==0: # increase/decrease saturation: col_text[0] = get_sample(col_text[0]) # saturation - col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.cv.CV_HSV2RGB)) + col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.COLOR_HSV2RGB)) elif choice==1: # get the complementary color to text: - col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.cv.CV_HSV2RGB)) + col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.COLOR_HSV2RGB)) col_text = self.font_color.complement(col_text) else: # choose a mid-way color: - col_bg = cv.cvtColor(col_bg, cv.cv.CV_RGB2HSV) + col_bg = cv.cvtColor(col_bg, cv.COLOR_RGB2HSV) col_bg = np.reshape(col_bg, (np.prod(col_bg.shape[:2]),3)) col_bg = np.mean(col_bg,axis=0).astype('uint8') - col_bg = np.squeeze(cv.cvtColor(col_bg[None,None,:],cv.cv.CV_HSV2RGB)) - col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.cv.CV_HSV2RGB)) + col_bg = np.squeeze(cv.cvtColor(col_bg[None,None,:],cv.COLOR_HSV2RGB)) + col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.COLOR_HSV2RGB)) col_text = self.font_color.triangle_color(col_text,col_bg) # now change the VALUE channel: - col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.cv.CV_RGB2HSV)) + col_text = np.squeeze(cv.cvtColor(col_text[None,None,:],cv.COLOR_RGB2HSV)) col_text[2] = get_sample(col_text[2]) # value - return np.squeeze(cv.cvtColor(col_text[None,None,:],cv.cv.CV_HSV2RGB)) + return np.squeeze(cv.cvtColor(col_text[None,None,:],cv.COLOR_HSV2RGB)) def color_text(self, text_arr, h, bg_arr): """ @@ -393,8 +398,8 @@ def check_perceptible(self, txt_mask, bg, txt_bg): """ bgo,txto = bg.copy(), txt_bg.copy() txt_mask = txt_mask.astype('bool') - bg = cv.cvtColor(bg.copy(), cv.cv.CV_RGB2Lab) - txt_bg = cv.cvtColor(txt_bg.copy(), cv.cv.CV_RGB2Lab) + bg = cv.cvtColor(bg.copy(), cv.COLOR_RGB2Lab) + txt_bg = cv.cvtColor(txt_bg.copy(), cv.COLOR_RGB2Lab) bg_px = bg[txt_mask,:] txt_px = txt_bg[txt_mask,:] bg_px[:,0] *= 100.0/255.0 #rescale - L channel @@ -402,7 +407,7 @@ def check_perceptible(self, txt_mask, bg, txt_bg): diff = np.linalg.norm(bg_px-txt_px,ord=None,axis=1) diff = np.percentile(diff,[10,30,50,70,90]) - print "color diff percentile :", diff + print ("color diff percentile :", diff) return diff, (bgo,txto) def color(self, bg_arr, text_arr, hs, place_order=None, pad=20): @@ -425,7 +430,7 @@ def color(self, bg_arr, text_arr, hs, place_order=None, pad=20): # initialize the placement order: if place_order is None: - place_order = np.array(xrange(len(text_arr))) + place_order = np.array(range(len(text_arr))) rendered = [] for i in place_order[::-1]: diff --git a/common.py b/common.py index b217734..4982573 100644 --- a/common.py +++ b/common.py @@ -25,17 +25,17 @@ def colorprint(colorcode, text, o=sys.stdout, bold=False): o.write(colorize(colorcode, text, bold=bold)) def warn(msg): - print colorize(Color.YELLOW, msg) + print (colorize(Color.YELLOW, msg)) def error(msg): - print colorize(Color.RED, msg) + print (colorize(Color.RED, msg)) # http://stackoverflow.com/questions/366682/how-to-limit-execution-time-of-a-function-call-in-python class TimeoutException(Exception): pass @contextmanager def time_limit(seconds): def signal_handler(signum, frame): - raise TimeoutException, colorize(Color.RED, " *** Timed out!", highlight=True) + raise TimeoutException(colorize(Color.RED, " *** Timed out!", highlight=True)) signal.signal(signal.SIGALRM, signal_handler) signal.alarm(seconds) try: diff --git a/gen.py b/gen.py index 9ff3f4b..0fb997f 100644 --- a/gen.py +++ b/gen.py @@ -41,7 +41,7 @@ def get_data(): if not osp.exists(DB_FNAME): try: colorprint(Color.BLUE,'\tdownloading data (56 M) from: '+DATA_URL,bold=True) - print + print() sys.stdout.flush() out_fname = 'data.tar.gz' wget.download(DATA_URL,out=out_fname) @@ -52,7 +52,7 @@ def get_data(): colorprint(Color.BLUE,'\n\tdata saved at:'+DB_FNAME,bold=True) sys.stdout.flush() except: - print colorize(Color.RED,'Data not found and have problems downloading.',bold=True) + print (colorize(Color.RED,'Data not found and have problems downloading.',bold=True)) sys.stdout.flush() sys.exit(-1) # open the h5 file and return: @@ -65,7 +65,7 @@ def add_res_to_db(imgname,res,db): and other metadata to the dataset. """ ninstance = len(res) - for i in xrange(ninstance): + for i in range(ninstance): dname = "%s_%d"%(imgname, i) db['data'].create_dataset(dname,data=res[i]['img']) db['data'][dname].attrs['charBB'] = res[i]['charBB'] @@ -75,14 +75,14 @@ def add_res_to_db(imgname,res,db): def main(viz=False): # open databases: - print colorize(Color.BLUE,'getting data..',bold=True) + print (colorize(Color.BLUE,'getting data..',bold=True)) db = get_data() - print colorize(Color.BLUE,'\t-> done',bold=True) + print (colorize(Color.BLUE,'\t-> done',bold=True)) # open the output h5 file: out_db = h5py.File(OUT_FILE,'w') out_db.create_group('/data') - print colorize(Color.GREEN,'Storing the output in: '+OUT_FILE, bold=True) + print (colorize(Color.GREEN,'Storing the output in: '+OUT_FILE, bold=True)) # get the names of the image files in the dataset: imnames = sorted(db['image'].keys()) @@ -93,7 +93,7 @@ def main(viz=False): start_idx,end_idx = 0,min(NUM_IMG, N) RV3 = RendererV3(DATA_PATH,max_time=SECS_PER_IMG) - for i in xrange(start_idx,end_idx): + for i in range(start_idx,end_idx): imname = imnames[i] try: # get the image: @@ -114,7 +114,7 @@ def main(viz=False): img = np.array(img.resize(sz,Image.ANTIALIAS)) seg = np.array(Image.fromarray(seg).resize(sz,Image.NEAREST)) - print colorize(Color.RED,'%d of %d'%(i,end_idx-1), bold=True) + print (colorize(Color.RED,'%d of %d'%(i,end_idx-1), bold=True)) res = RV3.render_text(img,depth,seg,area,label, ninstance=INSTANCE_PER_IMAGE,viz=viz) if len(res) > 0: @@ -122,11 +122,11 @@ def main(viz=False): add_res_to_db(imname,res,out_db) # visualize the output: if viz: - if 'q' in raw_input(colorize(Color.RED,'continue? (enter to continue, q to exit): ',True)): + if 'q' in input(colorize(Color.RED,'continue? (enter to continue, q to exit): ',True)): break except: traceback.print_exc() - print colorize(Color.GREEN,'>>>> CONTINUING....', bold=True) + print (colorize(Color.GREEN,'>>>> CONTINUING....', bold=True)) continue db.close() out_db.close() @@ -137,4 +137,4 @@ def main(viz=False): parser = argparse.ArgumentParser(description='Genereate Synthetic Scene-Text Images') parser.add_argument('--viz',action='store_true',dest='viz',default=False,help='flag for turning on visualizations') args = parser.parse_args() - main(args.viz) \ No newline at end of file + main(args.viz) diff --git a/poisson_reconstruct.py b/poisson_reconstruct.py index 5b1daa8..7f90899 100644 --- a/poisson_reconstruct.py +++ b/poisson_reconstruct.py @@ -99,7 +99,7 @@ def blit_images(im_top,im_back,scale_grad=1.0,mode='max'): im_res = np.zeros_like(im_top) # frac of gradients which come from source: - for ch in xrange(im_top.shape[2]): + for ch in range(im_top.shape[2]): ims = im_top[:,:,ch] imd = im_back[:,:,ch] @@ -203,7 +203,7 @@ def contiguous_regions(mask): # plt.imshow(im_alpha_L) # plt.show() - for i in xrange(500,im_alpha_L.shape[1],5): + for i in range(500,im_alpha_L.shape[1],5): l_actual = im_actual_L[i,:]#-im_actual_L[i,:-1] l_alpha = im_alpha_L[i,:]#-im_alpha_L[i,:-1] l_poisson = im_poisson_L[i,:]#-im_poisson_L[i,:-1] diff --git a/ransac.py b/ransac.py index cb5b1fc..5bd271d 100644 --- a/ransac.py +++ b/ransac.py @@ -30,7 +30,7 @@ def fit_plane_ransac(pts, neighbors=None,z_pos=None, dist_inlier=0.05, """ n,_ = pts.shape ninlier,models = [],[] - for i in xrange(max_iter): + for i in range(max_iter): if neighbors is None: p = pts[np.random.choice(pts.shape[0],nsample,replace=False),:] else: @@ -43,7 +43,7 @@ def fit_plane_ransac(pts, neighbors=None,z_pos=None, dist_inlier=0.05, models.append(m) if models == []: - print "RANSAC plane fitting failed!" + print ("RANSAC plane fitting failed!") return #None else: #refit the model to inliers: ninlier = np.array(ninlier) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1b855ae --- /dev/null +++ b/requirements.txt @@ -0,0 +1,13 @@ +cycler==0.10.0 +h5py==2.7.1 +matplotlib==2.1.1 +numpy==1.13.3 +Pillow==5.0.0 +pkg-resources==0.0.0 +pygame==1.9.3 +pyparsing==2.2.0 +python-dateutil==2.6.1 +pytz==2017.3 +scipy==1.0.0 +six==1.11.0 +wget==3.2 diff --git a/synth_utils.py b/synth_utils.py index ed8adc4..badc2bb 100644 --- a/synth_utils.py +++ b/synth_utils.py @@ -271,7 +271,7 @@ def unrotate2d(pts): elif R[1,1]<0: R[:,1] *= -1 else: - print "Rotation matrix not understood" + print ("Rotation matrix not understood") return if R[0,0]<0 and R[1,1]<0: R *= -1 diff --git a/synthgen.py b/synthgen.py index dfa688a..2fda5e9 100644 --- a/synthgen.py +++ b/synthgen.py @@ -78,7 +78,8 @@ def filter(seg,area,label): coords = np.c_[xs,ys].astype('float32') rect = cv2.minAreaRect(coords) - box = np.array(cv2.cv.BoxPoints(rect)) + #box = np.array(cv2.cv.BoxPoints(rect)) + box = np.array(cv2.boxPoints(rect)) h,w,rot = TextRegions.get_hw(box,return_rot=True) f = (h > TextRegions.minHeight @@ -91,7 +92,7 @@ def filter(seg,area,label): # filter bad regions: filt = np.array(filt) area = area[filt] - R = [R[i] for i in xrange(len(R)) if filt[i]] + R = [R[i] for i in range(len(R)) if filt[i]] # sort the regions based on areas: aidx = np.argsort(-area) @@ -111,7 +112,7 @@ def sample_grid_neighbours(mask,nsample,step=3): y_m,x_m = np.where(mask) mask_idx = np.zeros_like(mask,'int32') - for i in xrange(len(y_m)): + for i in range(len(y_m)): mask_idx[y_m[i],x_m[i]] = i xp,xn = np.zeros_like(mask), np.zeros_like(mask) @@ -136,7 +137,7 @@ def sample_grid_neighbours(mask,nsample,step=3): Y = np.transpose(np.c_[ys,ys+s,ys-s,ys+s,ys-s][:,:,None],(1,2,0)) sample_idx = np.concatenate([Y,X],axis=1) mask_nn_idx = np.zeros((5,sample_idx.shape[-1]),'int32') - for i in xrange(sample_idx.shape[-1]): + for i in range(sample_idx.shape[-1]): mask_nn_idx[:,i] = mask_idx[sample_idx[:,:,i][:,0],sample_idx[:,:,i][:,1]] return mask_nn_idx @@ -215,9 +216,9 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): REGION : DICT output of TextRegions.get_regions PAD : number of pixels to pad the placement-mask by """ - contour,hier = cv2.findContours(mask.copy().astype('uint8'), - mode=cv2.cv.CV_RETR_CCOMP, - method=cv2.cv.CV_CHAIN_APPROX_SIMPLE) + _,contour,hier = cv2.findContours(mask.copy().astype('uint8'), + mode=cv2.RETR_CCOMP, + method=cv2.CHAIN_APPROX_SIMPLE) contour = [np.squeeze(c).astype('float') for c in contour] #plane = np.array([plane[1],plane[0],plane[2],plane[3]]) H,W = mask.shape[:2] @@ -226,7 +227,7 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): pts,pts_fp = [],[] center = np.array([W,H])/2 n_front = np.array([0.0,0.0,-1.0]) - for i in xrange(len(contour)): + for i in range(len(contour)): cnt_ij = contour[i] xyz = su.DepthCamera.plane2xyz(center, cnt_ij, plane) R = su.rot3d(plane[:3],n_front) @@ -236,7 +237,7 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): # unrotate in 2D plane: rect = cv2.minAreaRect(pts_fp[0].copy().astype('float32')) - box = np.array(cv2.cv.BoxPoints(rect)) + box = np.array(cv2.boxPoints(rect)) R2d = su.unrotate2d(box.copy()) box = np.vstack([box,box[0,:]]) #close the box for visualization @@ -248,7 +249,7 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): # the same scale as the target region: s = rescale_frontoparallel(pts_tmp,boxR,pts[0]) boxR *= s - for i in xrange(len(pts_fp)): + for i in range(len(pts_fp)): pts_fp[i] = s*((pts_fp[i]-mu[None,:]).dot(R2d.T) + mu[None,:]) # paint the unrotated contour points: @@ -258,9 +259,9 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): place_mask = 255*np.ones((int(np.ceil(COL))+pad, int(np.ceil(ROW))+pad), 'uint8') - pts_fp_i32 = [(pts_fp[i]+minxy[None,:]).astype('int32') for i in xrange(len(pts_fp))] + pts_fp_i32 = [(pts_fp[i]+minxy[None,:]).astype('int32') for i in range(len(pts_fp))] cv2.drawContours(place_mask,pts_fp_i32,-1,0, - thickness=cv2.cv.CV_FILLED, + thickness=cv2.FILLED, lineType=8,hierarchy=hier) if not TextRegions.filter_rectified((~place_mask).astype('float')/255): @@ -280,7 +281,7 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): plt.subplot(1,2,2) plt.imshow(~place_mask) plt.hold(True) - for i in xrange(len(pts_fp_i32)): + for i in range(len(pts_fp_i32)): plt.scatter(pts_fp_i32[i][:,0],pts_fp_i32[i][:,1], edgecolors='none',facecolor='g',alpha=0.5) plt.show() @@ -318,7 +319,7 @@ def mean_seg(rgb,seg,label): plt.close(fignum) plt.figure(fignum) ims = [rgb,mim,depth,img] - for i in xrange(len(ims)): + for i in range(len(ims)): plt.subplot(2,2,i+1) plt.imshow(ims[i]) plt.show(block=False) @@ -351,10 +352,10 @@ def viz_textbb(fignum,text_im, bb_list,alpha=1.0): plt.imshow(text_im) plt.hold(True) H,W = text_im.shape[:2] - for i in xrange(len(bb_list)): + for i in range(len(bb_list)): bbs = bb_list[i] ni = bbs.shape[-1] - for j in xrange(ni): + for j in range(ni): bb = bbs[:,:,j] bb = np.c_[bb,bb[:,0]] plt.plot(bb[0,:], bb[1,:], 'r', linewidth=2, alpha=alpha) @@ -552,14 +553,14 @@ def char2wordBB(self, charBB, text): bb_idx = np.r_[0, np.cumsum([len(w) for w in wrds])] wordBB = np.zeros((2,4,len(wrds)), 'float32') - for i in xrange(len(wrds)): + for i in range(len(wrds)): cc = charBB[:,:,bb_idx[i]:bb_idx[i+1]] # fit a rotated-rectangle: # change shape from 2x4xn_i -> (4*n_i)x2 cc = np.squeeze(np.concatenate(np.dsplit(cc,cc.shape[-1]),axis=1)).T.astype('float32') rect = cv2.minAreaRect(cc.copy()) - box = np.array(cv2.cv.BoxPoints(rect)) + box = np.array(cv2.boxPoints(rect)) # find the permutation of box-coordinates which # are "aligned" appropriately with the character-bb. @@ -570,7 +571,7 @@ def char2wordBB(self, charBB, text): cc[3,:]].T perm4 = np.array(list(itertools.permutations(np.arange(4)))) dists = [] - for pidx in xrange(perm4.shape[0]): + for pidx in range(perm4.shape[0]): d = np.sum(np.linalg.norm(box[perm4[pidx],:]-cc_tblr,axis=1)) dists.append(d) wordBB[:,:,i] = box[perm4[np.argmin(dists)],:].T @@ -626,10 +627,10 @@ def render_text(self,rgb,depth,seg,area,label,ninstance=1,viz=False): return [] res = [] - for i in xrange(ninstance): + for i in range(ninstance): place_masks = copy.deepcopy(regions['place_mask']) - print colorize(Color.CYAN, " ** instance # : %d"%i) + print (colorize(Color.CYAN, " ** instance # : %d"%i)) idict = {'img':[], 'charBB':None, 'wordBB':None, 'txt':None} @@ -659,8 +660,8 @@ def render_text(self,rgb,depth,seg,area,label,ninstance=1,viz=False): txt_render_res = self.place_text(img,place_masks[ireg], regions['homography'][ireg], regions['homography_inv'][ireg]) - except TimeoutException, msg: - print msg + except TimeoutException as msg: + print (msg) continue except: traceback.print_exc() diff --git a/text_utils.py b/text_utils.py index 5aab5b3..1814eda 100644 --- a/text_utils.py +++ b/text_utils.py @@ -5,7 +5,8 @@ import os.path as osp import random, os import cv2 -import cPickle as cp +#import cPickle as cp +import _pickle as cp import scipy.signal as ssig import scipy.stats as sstat import pygame, pygame.locals @@ -14,10 +15,10 @@ from PIL import Image import math from common import * - +import pickle def sample_weighted(p_dict): - ps = p_dict.keys() + ps = list(p_dict.keys()) return p_dict[np.random.choice(ps,p=ps)] def move_bb(bbs, t): @@ -45,7 +46,7 @@ def crop_safe(arr, rect, bbs=[], pad=0): v1 = [min(arr.shape[0], rect[0]+rect[2]), min(arr.shape[1], rect[1]+rect[3])] arr = arr[v0[0]:v1[0],v0[1]:v1[1],...] if len(bbs) > 0: - for i in xrange(len(bbs)): + for i in range(len(bbs)): bbs[i,0] -= v0[0] bbs[i,1] -= v0[1] return arr, bbs @@ -182,9 +183,9 @@ def render_curved(self, font, word_text): # baseline state mid_idx = wl//2 BS = self.baselinestate.get_sample() - curve = [BS['curve'](i-mid_idx) for i in xrange(wl)] + curve = [BS['curve'](i-mid_idx) for i in range(wl)] curve[mid_idx] = -np.sum(curve) / (wl-1) - rots = [-int(math.degrees(math.atan(BS['diff'](i-mid_idx)/(font.size/2)))) for i in xrange(wl)] + rots = [-int(math.degrees(math.atan(BS['diff'](i-mid_idx)/(font.size/2)))) for i in range(wl)] bbs = [] # place middle char @@ -200,7 +201,7 @@ def render_curved(self, font, word_text): # render chars to the left and right: last_rect = rect ch_idx = [] - for i in xrange(wl): + for i in range(wl): #skip the middle character if i==mid_idx: bbs.append(mid_ch_bb) @@ -312,7 +313,7 @@ def bb_xywh2coords(self,bbs): """ n,_ = bbs.shape coords = np.zeros((2,4,n)) - for i in xrange(n): + for i in range(n): coords[:,:,i] = bbs[i,:2][:,None] coords[0,1,i] += bbs[i,2] coords[:,2,i] += bbs[i,2:4] @@ -417,13 +418,21 @@ def __init__(self, data_dir='data'): font_model_path = osp.join(data_dir, 'models/font_px2pt.cp') # get character-frequencies in the English language: - with open(char_freq_path,'r') as f: - self.char_freq = cp.load(f) + with open(char_freq_path,'rb') as f: + #self.char_freq = cp.load(f) + u = pickle._Unpickler(f) + u.encoding = 'latin1' + p = u.load() + self.char_freq = p # get the model to convert from pixel to font pt size: - with open(font_model_path,'r') as f: - self.font_model = cp.load(f) - + with open(font_model_path,'rb') as f: + #self.font_model = cp.load(f) + u = pickle._Unpickler(f) + u.encoding = 'latin1' + p = u.load() + self.font_model = p + # get the names of fonts to use: self.FONT_LIST = osp.join(data_dir, 'fonts/fontlist.txt') self.fonts = [os.path.join(data_dir,'fonts',f.strip()) for f in open(self.FONT_LIST)] @@ -441,7 +450,7 @@ def get_aspect_ratio(self, font, size=None): # get the [height,width] of each character: try: sizes = font.get_metrics(chars,size) - good_idx = [i for i in xrange(len(sizes)) if sizes[i] is not None] + good_idx = [i for i in range(len(sizes)) if sizes[i] is not None] sizes,w = [sizes[i] for i in good_idx], w[good_idx] sizes = np.array(sizes).astype('float')[:,[3,4]] r = np.abs(sizes[:,1]/sizes[:,0]) # width/height @@ -559,7 +568,7 @@ def center_align(self, lines): """ ls = [len(l) for l in lines] max_l = max(ls) - for i in xrange(len(lines)): + for i in range(len(lines)): l = lines[i].strip() dl = max_l-ls[i] lspace = dl//2 @@ -630,7 +639,7 @@ def sample_line(self,nline_max,nchar_max): # get number of words: nword = [self.p_line_nword[2]*sstat.beta.rvs(a=self.p_line_nword[0], b=self.p_line_nword[1]) - for _ in xrange(nline)] + for _ in range(nline)] nword = [max(1,int(np.ceil(n))) for n in nword] lines = self.get_lines(nline, nword, nchar_max, f=0.35) @@ -646,7 +655,7 @@ def sample_para(self,nline_max,nchar_max): # get number of words: nword = [self.p_para_nword[2]*sstat.beta.rvs(a=self.p_para_nword[0], b=self.p_para_nword[1]) - for _ in xrange(nline)] + for _ in range(nline)] nword = [max(1,int(np.ceil(n))) for n in nword] lines = self.get_lines(nline, nword, nchar_max, f=0.35) From b6246f90124084c870dcbed3e1da3c0ef4d35da7 Mon Sep 17 00:00:00 2001 From: ND Date: Wed, 3 Jan 2018 11:33:19 +0530 Subject: [PATCH 2/5] list of strings encoding h5py bug fix --- gen.py | 5 ++++- visualize_results.py | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/gen.py b/gen.py index 0fb997f..ffaf995 100644 --- a/gen.py +++ b/gen.py @@ -70,7 +70,10 @@ def add_res_to_db(imgname,res,db): db['data'].create_dataset(dname,data=res[i]['img']) db['data'][dname].attrs['charBB'] = res[i]['charBB'] db['data'][dname].attrs['wordBB'] = res[i]['wordBB'] - db['data'][dname].attrs['txt'] = res[i]['txt'] + #db['data'][dname].attrs['txt'] = res[i]['txt'] + L = res[i]['txt'] + L = [n.encode("ascii", "ignore") for n in L] + db['data'][dname].attrs['txt'] = L def main(viz=False): diff --git a/visualize_results.py b/visualize_results.py index 92091ef..7b578c6 100644 --- a/visualize_results.py +++ b/visualize_results.py @@ -28,22 +28,22 @@ def viz_textbb(text_im, charBB_list, wordBB, alpha=1.0): H,W = text_im.shape[:2] # plot the character-BB: - for i in xrange(len(charBB_list)): + for i in range(len(charBB_list)): bbs = charBB_list[i] ni = bbs.shape[-1] - for j in xrange(ni): + for j in range(ni): bb = bbs[:,:,j] bb = np.c_[bb,bb[:,0]] plt.plot(bb[0,:], bb[1,:], 'r', alpha=alpha/2) # plot the word-BB: - for i in xrange(wordBB.shape[-1]): + for i in range(wordBB.shape[-1]): bb = wordBB[:,:,i] bb = np.c_[bb,bb[:,0]] plt.plot(bb[0,:], bb[1,:], 'g', alpha=alpha) # visualize the indiv vertices: vcol = ['r','g','b','k'] - for j in xrange(4): + for j in range(4): plt.scatter(bb[0,j],bb[1,j],color=vcol[j]) plt.gca().set_xlim([0,W-1]) @@ -53,7 +53,7 @@ def viz_textbb(text_im, charBB_list, wordBB, alpha=1.0): def main(db_fname): db = h5py.File(db_fname, 'r') dsets = sorted(db['data'].keys()) - print "total number of images : ", colorize(Color.RED, len(dsets), highlight=True) + print ("total number of images : ", colorize(Color.RED, len(dsets), highlight=True)) for k in dsets: rgb = db['data'][k][...] charBB = db['data'][k].attrs['charBB'] @@ -61,12 +61,12 @@ def main(db_fname): txt = db['data'][k].attrs['txt'] viz_textbb(rgb, [charBB], wordBB) - print "image name : ", colorize(Color.RED, k, bold=True) - print " ** no. of chars : ", colorize(Color.YELLOW, charBB.shape[-1]) - print " ** no. of words : ", colorize(Color.YELLOW, wordBB.shape[-1]) - print " ** text : ", colorize(Color.GREEN, txt) + print ("image name : ", colorize(Color.RED, k, bold=True)) + print (" ** no. of chars : ", colorize(Color.YELLOW, charBB.shape[-1])) + print (" ** no. of words : ", colorize(Color.YELLOW, wordBB.shape[-1])) + print (" ** text : ", colorize(Color.GREEN, txt)) - if 'q' in raw_input("next? ('q' to exit) : "): + if 'q' in input("next? ('q' to exit) : "): break db.close() From aacc9fdcb8d733ba44b32f48056e8fed6fda5382 Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 4 Sep 2019 23:52:22 +0100 Subject: [PATCH 3/5] Update README.md --- README.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index acb16ad..2904782 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ Code for generating synthetic text images as described in ["Synthetic Data for T **Synthetic Scene-Text Image Samples** ![Synthetic Scene-Text Samples](samples.png "Synthetic Samples") -The library is written in Python. The main dependencies are: +The code in the `master` branch is for Python2. Python3 is supported in the `python3` branch. + +The main dependencies are: ``` pygame, opencv (cv2), PIL (Image), numpy, matplotlib, h5py, scipy @@ -43,18 +45,29 @@ For an explanation of the fields in `dset.h5` (e.g.: `seg`,`area`,`label`), plea ### Pre-processed Background Images The 8,000 background images used in the paper, along with their segmentation and depth masks, have been uploaded here: -`http://zeus.robots.ox.ac.uk/textspot/static/db/`, where, `` can be: +`http://www.robots.ox.ac.uk/~vgg/data/scenetext/preproc/`, where, `` can be: + +| filenames | size | description | md5 hash | +|:--------------- | ----:|:---------------------------------------------------- |:-------------------------------- | +| `imnames.cp` | 180K | names of images which do not contain background text | | +| `bg_img.tar.gz` | 8.9G | images (filter these using `imnames.cp`) | 3eac26af5f731792c9d95838a23b5047 | +| `depth.h5` | 15G | depth maps | af97f6e6c9651af4efb7b1ff12a5dc1b | +| `seg.h5` | 6.9G | segmentation maps | 1605f6e629b2524a3902a5ea729e86b2 | -- `imnames.cp` [180K]: names of filtered files, i.e., those files which do not contain text -- `bg_img.tar.gz` [8.9G]: compressed image files (more than 8000, so only use the filtered ones in imnames.cp) -- `depth.h5` [15G]: depth maps -- `seg.h5` [6.9G]: segmentation maps +Note: due to large size, `depth.h5` is also available for download as 3-part split-files of 5G each. +These part files are named: `depth.h5-00, depth.h5-01, depth.h5-02`. Download using the path above, and put them together using `cat depth.h5-0* > depth.h5`. + +[`use_preproc_bg.py`](https://github.com/ankush-me/SynthText/blob/master/use_preproc_bg.py) provides sample code for reading this data. Note: I do not own the copyright to these images. ### Generating Samples with Text in non-Latin (English) Scripts -@JarveeLee has modified the pipeline for generating samples with Chinese text [here](https://github.com/JarveeLee/SynthText_Chinese_version). +- @JarveeLee has modified the pipeline for generating samples with Chinese text [here](https://github.com/JarveeLee/SynthText_Chinese_version). +- @adavoudi has modified it for arabic/persian script, which flows from right-to-left [here](https://github.com/adavoudi/SynthText). +- @MichalBusta has adapted it for a number of languages (e.g. Bangla, Arabic, Chinese, Japanese, Korean) [here](https://github.com/MichalBusta/E2E-MLT). +- @gachiemchiep has adapted for Japanese [here](https://github.com/gachiemchiep/SynthText). +- @gungui98 has adapted for Vietnamese [here](https://github.com/gungui98/SynthText). +- @youngkyung has adapted for Korean [here](https://github.com/youngkyung/SynthText_kr). ### Further Information Please refer to the paper for more information, or contact me (email address in the paper). - From 57242d7ff1950449b8937bf247b9e7919a5dc6a8 Mon Sep 17 00:00:00 2001 From: yashYRS Date: Thu, 2 Apr 2020 01:16:46 +0530 Subject: [PATCH 4/5] Fixed minor changes, that resulted in code crash during runtime --- invert_font_size.py | 1 - poisson_reconstruct.py | 2 -- synthgen.py | 6 ++---- visualize_results.py | 1 - 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/invert_font_size.py b/invert_font_size.py index 5697467..01c6cde 100644 --- a/invert_font_size.py +++ b/invert_font_size.py @@ -21,7 +21,6 @@ FS = FontState() #plt.figure() -#plt.hold(True) for i in xrange(len(FS.fonts)): print i font = freetype.Font(FS.fonts[i], size=12) diff --git a/poisson_reconstruct.py b/poisson_reconstruct.py index 7f90899..4030136 100644 --- a/poisson_reconstruct.py +++ b/poisson_reconstruct.py @@ -212,7 +212,6 @@ def contiguous_regions(mask): with sns.axes_style("darkgrid"): plt.subplot(2,1,2) plt.plot(l_alpha,label='alpha') - plt.hold(True) plt.plot(l_poisson,label='poisson') plt.plot(l_actual,label='actual') plt.legend() @@ -227,7 +226,6 @@ def contiguous_regions(mask): with sns.axes_style("white"): plt.subplot(2,1,1) plt.imshow(im_alpha[:,:,::-1].astype('uint8')) - plt.hold(True) plt.plot([0,im_alpha_L.shape[0]-1],[i,i],'r') plt.axis('image') plt.show() diff --git a/synthgen.py b/synthgen.py index 2fda5e9..29b7fae 100644 --- a/synthgen.py +++ b/synthgen.py @@ -216,9 +216,9 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): REGION : DICT output of TextRegions.get_regions PAD : number of pixels to pad the placement-mask by """ - _,contour,hier = cv2.findContours(mask.copy().astype('uint8'), + contour,hier = cv2.findContours(mask.copy().astype('uint8'), mode=cv2.RETR_CCOMP, - method=cv2.CHAIN_APPROX_SIMPLE) + method=cv2.CHAIN_APPROX_SIMPLE)[-2:] contour = [np.squeeze(c).astype('float') for c in contour] #plane = np.array([plane[1],plane[0],plane[2],plane[3]]) H,W = mask.shape[:2] @@ -280,7 +280,6 @@ def get_text_placement_mask(xyz,mask,plane,pad=2,viz=False): plt.imshow(mask) plt.subplot(1,2,2) plt.imshow(~place_mask) - plt.hold(True) for i in range(len(pts_fp_i32)): plt.scatter(pts_fp_i32[i][:,0],pts_fp_i32[i][:,1], edgecolors='none',facecolor='g',alpha=0.5) @@ -350,7 +349,6 @@ def viz_textbb(fignum,text_im, bb_list,alpha=1.0): plt.close(fignum) plt.figure(fignum) plt.imshow(text_im) - plt.hold(True) H,W = text_im.shape[:2] for i in range(len(bb_list)): bbs = bb_list[i] diff --git a/visualize_results.py b/visualize_results.py index 7b578c6..c143635 100644 --- a/visualize_results.py +++ b/visualize_results.py @@ -24,7 +24,6 @@ def viz_textbb(text_im, charBB_list, wordBB, alpha=1.0): plt.close(1) plt.figure(1) plt.imshow(text_im) - plt.hold(True) H,W = text_im.shape[:2] # plot the character-BB: From ecfc483252c10ab19c09f52c2957086543196d33 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 27 Apr 2022 16:41:13 +0800 Subject: [PATCH 5/5] [Python3] clean up warnings and add buffer to prevent zero-divide error --- .idea/SynthText.iml | 11 ----------- .idea/misc.xml | 4 ---- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ gen.py | 16 ++++++++-------- prep_scripts/floodFill.py | 18 +++++++++--------- synth_utils.py | 1 + 7 files changed, 18 insertions(+), 46 deletions(-) delete mode 100644 .idea/SynthText.iml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/SynthText.iml b/.idea/SynthText.iml deleted file mode 100644 index 6711606..0000000 --- a/.idea/SynthText.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index c139e1c..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 1757dd2..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/gen.py b/gen.py index fa401aa..76ef6eb 100644 --- a/gen.py +++ b/gen.py @@ -74,10 +74,10 @@ def add_res_to_db(imgname, res, db): db['data'].create_dataset(dname, data=res[i]['img']) db['data'][dname].attrs['charBB'] = res[i]['charBB'] db['data'][dname].attrs['wordBB'] = res[i]['wordBB'] - # db['data'][dname].attrs['txt'] = res[i]['txt'] - L = res[i]['txt'] - L = [n.encode("ascii", "ignore") for n in L] - db['data'][dname].attrs['txt'] = L + db['data'][dname].attrs['txt'] = res[i]['txt'] + text_utf8 = [char.encode('utf8') for char in res[i]['txt']] + db['data'][dname].attrs['txt_utf8'] = text_utf8 + def save_res_to_imgs(imgname, res): """ Add the synthetically generated text image instance @@ -128,8 +128,8 @@ def main(viz=False): # re-size uniformly: sz = depth.shape[:2][::-1] - img = np.array(img.resize(sz, Image.ANTIALIAS)) - seg = np.array(Image.fromarray(seg).resize(sz, Image.NEAREST)) + img = np.array(img.resize(sz, Image.Resampling.LANCZOS)) + seg = np.array(Image.fromarray(seg).resize(sz, Image.Resampling.NEAREST)) print('%d of %d' % (i, end_idx - 1)) res = RV3.render_text(img, depth, seg, area, label, @@ -153,10 +153,10 @@ def main(viz=False): if __name__ == '__main__': import argparse - parser = argparse.ArgumentParser(description='Genereate Synthetic Scene-Text Images') + parser = argparse.ArgumentParser(description='Generate Synthetic Scene-Text Images') parser.add_argument('--viz', action='store_true', dest='viz', default=False, help='flag for turning on visualizations') parser.add_argument('--lang', default='ENG', - help='Select language : ENG/JPN') + help='Select language : ENG or JPN') args = parser.parse_args() main(args.viz) diff --git a/prep_scripts/floodFill.py b/prep_scripts/floodFill.py index 1f61ef1..10596f6 100644 --- a/prep_scripts/floodFill.py +++ b/prep_scripts/floodFill.py @@ -13,11 +13,11 @@ import h5py import os.path as osp import multiprocessing as mp -import traceback, sys + def get_seed(sx,sy,ucm): n = sx.size - for i in xrange(n): + for i in range(n): if ucm[sx[i]+1,sy[i]+1] == 0: return (sy[i],sx[i]) @@ -41,7 +41,7 @@ def get_mask(ucm,viz=False): sx,sy = np.where(mask==0) seed = get_seed(sx,sy,ucm) i += 1 - print " > terminated in %d steps"%i + print (" > terminated in %d steps"%i) if viz: plt.imshow(mask) @@ -81,7 +81,7 @@ def get_imname(self,i): return "".join(map(chr, self.ucm_h5[self.ucm_h5['names'][0,self.i]][:])) def __stop__(self): - print "DONE" + print ("DONE") self.ucm_h5.close() raise StopIteration @@ -101,14 +101,14 @@ def get_valid_name(self): def next(self): imname = self.get_valid_name() - print "%d of %d"%(self.i+1,self.N) + print ("%d of %d"%(self.i+1,self.N)) ucm = self.ucm_h5[self.ucm_h5['ucms'][0,self.i]][:] ucm = ucm.copy() self.i += 1 return ((ucm>self.th).astype('uint8'),imname) ucm_iter = ucm_iterable(db_path,th) - print "cpu count: ", mp.cpu_count() + print ("cpu count: ", mp.cpu_count()) parpool = mp.Pool(4) ucm_result = parpool.imap_unordered(get_mask_parallel, ucm_iter, chunksize=1) @@ -116,16 +116,16 @@ def next(self): if res is None: continue ((mask,area,label),imname) = res - print "got back : ", imname + print ("got back : ", imname) mask = mask.astype('uint16') mask_dset = dbo_mask.create_dataset(imname, data=mask) mask_dset.attrs['area'] = area mask_dset.attrs['label'] = label # close the h5 files: - print "closing DB" + print ("closing DB") dbo.close() - print ">>>> DONE" + print (">>>> DONE") base_dir = '/home/' # directory containing the ucm.mat, i.e., output of run_ucm.m diff --git a/synth_utils.py b/synth_utils.py index badc2bb..b517c61 100644 --- a/synth_utils.py +++ b/synth_utils.py @@ -233,6 +233,7 @@ def ssc(v): """ Returns the skew-symmetric cross-product matrix corresponding to v. """ + v += np.finfo("float").eps v /= np.linalg.norm(v) return np.array([[ 0, -v[2], v[1]], [ v[2], 0, -v[0]],