def align_strong(I, Iref, scales=(0.15, 0.2, 0.25, 0.3), crop_I=(0.05, 0.05, 0.05, 0.05), crop_Iref=None, do_nan_to_num=False): """ Alignment strategy: First, crop out 5% from each side of I. Then, try a range of scales, and choose the alignment that minimizes the error. CURRENTLY NOT USED. """ if crop_I != None: Icrop = cropout_stuff(I, crop_I[0], crop_I[1], crop_I[2], crop_I[3]) else: Icrop = I if crop_Iref != None: Iref_crop = cropout_stuff(Iref, crop_Iref[0], crop_Iref[1], crop_Iref[2], crop_Iref[3]) else: Iref_crop = Iref H_best, Ireg_best, err_best = None, None, None scale_best = None for scale in scales: H, Ireg, err = imagesAlign.imagesAlign(Icrop, Iref_crop, fillval=1, trfm_type='rigid', rszFac=scale) if err_best == None or err < err_best: H_best = H Ireg_best = Ireg err_best = err scale_best = scale # Finally, apply H_BEST to I Ireg = sh.imtransform(I, H_best) if do_nan_to_num: Ireg = np.nan_to_num(Ireg) return H_best, Ireg, err_best
def minmax_cv_V2(imgs, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16)): """ Just like minmax_cv(), but accepts a list of cvMat's instead of a list of imgpaths. If you're planning on generating overlays of tens-of-thousands of images, calling this function might result in a gross-amount of memory usage (since this function keeps them all in memory at once). """ Imin = cv.CloneImage(imgs[0]) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for I in imgs[1:]: Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=trfm_type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def make_minmax_overlay2(imgs, do_align=False, rszFac=1.0): overlayMin, overlayMax = None, None Iref = None for img in imgs: if do_align and Iref == None: Iref = img elif do_align: (H, img, err) = imagesAlign(img, Iref, fillval=0, rszFac=rszFac) if (overlayMin == None): overlayMin = img else: if overlayMin.shape != img.shape: h, w = overlayMin.shape img = resize_img_norescale(img, (w, h)) overlayMin = np.fmin(overlayMin, img) if (overlayMax == None): overlayMax = img else: if overlayMax.shape != img.shape: h, w = overlayMax.shape img = resize_img_norescale(img, (w, h)) overlayMax = np.fmax(overlayMax, img) #rszFac=sh.resizeOrNot(overlayMax.shape,sh.MAX_PRECINCT_PATCH_DISPLAY) #overlayMax = sh.fastResize(overlayMax, rszFac) #/ 255.0 #overlayMin = sh.fastResize(overlayMin, rszFac) #/ 255.0 return overlayMin, overlayMax
def make_minmax_overlay2(imgs, do_align=False, rszFac=1.0): overlayMin, overlayMax = None, None Iref = None for img in imgs: if do_align and Iref == None: Iref = img elif do_align: (H, img, err) = imagesAlign(img, Iref, fillval=0, rszFac=rszFac) if (overlayMin == None): overlayMin = img else: if overlayMin.shape != img.shape: h, w = overlayMin.shape img = resize_img_norescale(img, (w,h)) overlayMin = np.fmin(overlayMin, img) if (overlayMax == None): overlayMax = img else: if overlayMax.shape != img.shape: h, w = overlayMax.shape img = resize_img_norescale(img, (w,h)) overlayMax = np.fmax(overlayMax, img) #rszFac=sh.resizeOrNot(overlayMax.shape,sh.MAX_PRECINCT_PATCH_DISPLAY) #overlayMax = sh.fastResize(overlayMax, rszFac) #/ 255.0 #overlayMin = sh.fastResize(overlayMin, rszFac) #/ 255.0 return overlayMin, overlayMax
def align_image(I, Iref, crop=True, verbose=False, CROPX=0.02, CROPY=0.02, ERR_REL_THR=1.001, RSZFAC=0.15, MINAREA=None): """ Aligns I to IREF (e.g. 'global' alignment). Both IREF and I must be correctly 'flipped' before you pass it to this function. Input: nparray IREF The reference image that we are aligning against. nparray I The image that we want to align. float CROPX, CROPY, OR tuple CROPX, tuple CROPY The amount to crop off the top+bottom and left+right of the image (used with CROP=True). If CROPX, CROPY are tuples, they must be the same length, and we will try all sequential pairs until we get a relative error that is <= ERR_REL_THR. If none are <= ERR_REL_THR, then we output the alignment with smallest error. float ERR_REL_THR See the docstring for the tuple-version of CROPX, CROPY. int MINAREA This parameter dictates how "far down" the pyramid optimization should downscale the image. For instance, if MINAREA is K, then a new pyramid level will be created by downscaling the image by a factor of 2.0 until the image area is <= K. Larger values of MINAREA mean that alignment is done at larger scales, which will lead to better accuracy, but may take more time. Smaller values of MINAREA incur better speedsup, but potentially at the cost of accuracy. The default value 2**16 is a reasonable value for accuracy. Output: (nparray H, nparray IREG, float err) where H is the transformation matrix, IREG is the result of aligning I to IREF, and ERR is the alignment error (a float from [0.0, 1.0]). """ if MINAREA is None: MINAREA = np.power(2, 16) if crop and type(CROPX) in (list, tuple): return _align_image_mult(I, Iref, CROPX, CROPY, ERR_REL_THR) if crop == True: Iref_crop = cropout_stuff(Iref, CROPY, CROPY, CROPX, CROPX) Icrop = cropout_stuff(I, CROPY, CROPY, CROPX, CROPX) else: Icrop, Iref_crop = I, Iref H, err = imagesAlign.imagesAlign(Icrop, Iref_crop, trfm_type='rigid', rszFac=RSZFAC, applyWarp=False, minArea=MINAREA) if verbose: print "Alignment Err: ", err Ireg = sh.imtransform(I, H) # Ireg = np.nan_to_num(Ireg) return H, Ireg, err
def minmax_cv(imgpaths, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16), bbs_map=None, imgCache=None): """ Generates min/max overlays for IMGPATHS. If DO_ALIGN is True, then this also aligns every image to the first image in IMGPATHS. Input: list IMGPATHS: [str imgpath_i, ...] bool DO_ALIGN: float RSZFAC: Resizing factor for alignment. dict BBS_MAP: maps {str imgpath: (x1,y1,x2,y2)} Output: cvMat minimg, cvMat maximg. """ def load_image(imgpath): if imgCache == None: return cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) else: ((img, imgpath), isHit) = imgCache.load(imgpath) return img if bbs_map == None: bbs_map = {} imgpath = imgpaths[0] bb0 = bbs_map.get(imgpath, None) Imin = load_image(imgpath) if bb0: coords = (bb0[0], bb0[1], bb0[2] - bb0[0], bb0[3] - bb0[1]) coords = tuple(map(int, coords)) cv.SetImageROI(Imin, coords) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = load_image(imgpath) bb = bbs_map.get(imgpath, None) if bb: bb = tuple(map(int, bb)) cv.SetImageROI(I, (bb[0], bb[1], bb[2] - bb[0], bb[3] - bb[1])) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=trfm_type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def minmax_cv_v2(imgpaths, Iref_imP=None, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16), bbs_map=None): """ Computes the overlays of IMGPATHS, but uses the IREF_IMP as the reference image to align against, if DO_ALIGN is True. Mainly a function written for the parallel version (minmax_cv is still fine for single-process use). """ bbs_map = {} if bbs_map == None else bbs_map if do_align: Iref = cv.LoadImage(Iref_imP, cv.CV_LOAD_IMAGE_GRAYSCALE) bbRef = bbs_map.get(Iref_imP, None) if bbRef: coords = tuple( map(int, (bbRef[0], bbRef[1], bbRef[2] - bbRef[0], bbRef[3] - bbRef[1]))) cv.SetImageROI(Iref) else: Iref = None # 0.) Prep first image imgpath0 = imgpaths[0] Imin = cv.LoadImage(imgpath0, cv.CV_LOAD_IMAGE_GRAYSCALE) bb0 = bbs_map.get(imgpath0, None) if bb0: coords = tuple( map(int, (bb0[0], bb0[1], bb0[2] - bb0[0], bb0[3] - bb0[1]))) cv.SetImageROI(Imin) Imax = cv.CloneImage(Imin) Iref_np = (iplimage2np(cv.CloneImage(Iref)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) bb = bbs_map.get(imgpath, None) if bb: bb = tuple(map(int, bb)) cv.SetImageROI(I, (bb[0], bb[1], bb[2] - bb[0], bb[3] - bb[1])) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin.tostring(), Imax.tostring(), cv.GetSize(Imin)
def align(groupid, dat): res = [] translations = [] for i, group in enumerate(zip(*dat)): if i == 0: # We want to look at everything for the title left_border = 0 else: # Skip the voting target for the rest #left_border = 80 left_border = 0 Iref_orig = sh.standardImread(group[0], flatten=True) Iref = Iref_orig[:, left_border:] r = [] r_img = [] for i in range(len(group)): I_orig = sh.standardImread(group[i], flatten=True) I = I_orig[:, left_border:] Inorm = make_norm(I, Iref) (H, imres, err) = imagesAlign.imagesAlign(Inorm, Iref, trfm_type='translation') r_img.append((make_norm(I_orig, Iref_orig), H)) r.append(translate(group[i])) translations.append(r_img) res.append(r) translated_images = [] for contest in zip(*translations): c_res = [] """ print 'new' arr = np.zeros((3,3)) for _,H in contest: arr += H arr /= len(contest) print arr """ for img, H in contest: translated = sh.imtransform(np.copy(img), H, fillval=np.nan) align_res = np.nan_to_num(translated) c_res.append(align_res) translated_images.append(c_res) translated_images = zip(*translated_images) return res, translated_images
def align(groupid, dat): res = [] translations = [] for i,group in enumerate(zip(*dat)): if i == 0: # We want to look at everything for the title left_border = 0 else: # Skip the voting target for the rest #left_border = 80 left_border = 0 Iref_orig=sh.standardImread(group[0],flatten=True) Iref = Iref_orig[:,left_border:] r = [] r_img = [] for i in range(len(group)): I_orig=sh.standardImread(group[i],flatten=True) I=I_orig[:,left_border:] Inorm = make_norm(I, Iref) (H,imres,err)=imagesAlign.imagesAlign(Inorm,Iref,trfm_type='translation') r_img.append((make_norm(I_orig, Iref_orig), H)) r.append(translate(group[i])) translations.append(r_img) res.append(r) translated_images = [] for contest in zip(*translations): c_res = [] """ print 'new' arr = np.zeros((3,3)) for _,H in contest: arr += H arr /= len(contest) print arr """ for img,H in contest: translated = sh.imtransform(np.copy(img), H, fillval=np.nan) align_res = np.nan_to_num(translated) c_res.append(align_res) translated_images.append(c_res) translated_images = zip(*translated_images) return res, translated_images
def minmax_cv(imgpaths, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16), bbs_map=None, imgCache=None): """ Generates min/max overlays for IMGPATHS. If DO_ALIGN is True, then this also aligns every image to the first image in IMGPATHS. Input: list IMGPATHS: [str imgpath_i, ...] bool DO_ALIGN: float RSZFAC: Resizing factor for alignment. dict BBS_MAP: maps {str imgpath: (x1,y1,x2,y2)} Output: cvMat minimg, cvMat maximg. """ def load_image(imgpath): if imgCache == None: return cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) else: ((img, imgpath), isHit) = imgCache.load(imgpath) return img if bbs_map == None: bbs_map = {} imgpath = imgpaths[0] bb0 = bbs_map.get(imgpath, None) Imin = load_image(imgpath) if bb0: coords = (bb0[0], bb0[1], bb0[2]-bb0[0], bb0[3]-bb0[1]) coords = tuple(map(int, coords)) cv.SetImageROI(Imin, coords) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = load_image(imgpath) bb = bbs_map.get(imgpath, None) if bb: bb = tuple(map(int, bb)) cv.SetImageROI(I, (bb[0], bb[1], bb[2]-bb[0], bb[3]-bb[1])) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=trfm_type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def align_image(I, Iref, crop=True, verbose=False, CROPX=0.02, CROPY=0.02, ERR_REL_THR=1.001, RSZFAC=0.15, MINAREA=None): """ Aligns I to IREF (e.g. 'global' alignment). Both IREF and I must be correctly 'flipped' before you pass it to this function. Input: nparray IREF The reference image that we are aligning against. nparray I The image that we want to align. float CROPX, CROPY, OR tuple CROPX, tuple CROPY The amount to crop off the top+bottom and left+right of the image (used with CROP=True). If CROPX, CROPY are tuples, they must be the same length, and we will try all sequential pairs until we get a relative error that is <= ERR_REL_THR. If none are <= ERR_REL_THR, then we output the alignment with smallest error. float ERR_REL_THR See the docstring for the tuple-version of CROPX, CROPY. int MINAREA This parameter dictates how "far down" the pyramid optimization should downscale the image. For instance, if MINAREA is K, then a new pyramid level will be created by downscaling the image by a factor of 2.0 until the image area is <= K. Larger values of MINAREA mean that alignment is done at larger scales, which will lead to better accuracy, but may take more time. Smaller values of MINAREA incur better speedsup, but potentially at the cost of accuracy. The default value 2**16 is a reasonable value for accuracy. Output: (nparray H, nparray IREG, float err) where H is the transformation matrix, IREG is the result of aligning I to IREF, and ERR is the alignment error (a float from [0.0, 1.0]). """ if MINAREA == None: MINAREA = np.power(2, 16) if crop and type(CROPX) in (list, tuple): return _align_image_mult(I, Iref, CROPX, CROPY, ERR_REL_THR) if crop == True: Iref_crop = cropout_stuff(Iref, CROPY, CROPY, CROPX, CROPX) Icrop = cropout_stuff(I, CROPY, CROPY, CROPX, CROPX) else: Icrop, Iref_crop = I, Iref H, err = imagesAlign.imagesAlign(Icrop, Iref_crop, trfm_type='rigid', rszFac=RSZFAC, applyWarp=False, minArea=MINAREA) if verbose: print "Alignment Err: ", err Ireg = sh.imtransform(I, H) #Ireg = np.nan_to_num(Ireg) return H, Ireg, err
def _align_image_mult(I, Iref, CROPX, CROPY, ERR_REL_THR): """ Helper function for align_image. Handles trying multiple crop parameters until an err_rel is found that is <= ERR_REL_THR. """ best_H, best_Ireg, best_err = None, None, None err_orig = np.mean(np.abs(I - Iref).flatten()) # L1 error, normalized by area for i, cropx in enumerate(CROPX): cropy = CROPY[i] I_crop = cropout_stuff(I, cropy, cropy, cropx, cropx) Iref_crop = cropout_stuff(Iref, cropy, cropy, cropx, cropx) H, err = imagesAlign.imagesAlign(I_crop, Iref_crop, trfm_type='rigid', rszFac=0.15, applyWarp=False) Ireg = sh.imtransform(I, H) err_galign = np.mean(np.abs(Ireg - Iref).flatten()) err_rel = err_galign / err_orig if err_orig != 0.0 else 0.0 if err_rel <= ERR_REL_THR: return H, Ireg, err_galign elif best_H == None or err_galign < best_err: best_H, best_Ireg, best_err = H, Ireg, err_galign return best_H, best_Ireg, best_err
def overlay_minmax_cv(imgpaths, do_align=False, rszFac=1.0): imgpath = imgpaths[0] Imin = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign.imagesAlign(tmp_np, Iref, fillval=0, rszFac=rszFac) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def minmax_cv_v2(imgpaths, Iref_imP=None, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16), bbs_map=None): """ Computes the overlays of IMGPATHS, but uses the IREF_IMP as the reference image to align against, if DO_ALIGN is True. Mainly a function written for the parallel version (minmax_cv is still fine for single-process use). """ bbs_map = {} if bbs_map == None else bbs_map if do_align: Iref = cv.LoadImage(Iref_imP, cv.CV_LOAD_IMAGE_GRAYSCALE) bbRef = bbs_map.get(Iref_imP, None) if bbRef: coords = tuple(map(int, (bbRef[0], bbRef[1], bbRef[2]-bbRef[0], bbRef[3]-bbRef[1]))) cv.SetImageROI(Iref) else: Iref = None # 0.) Prep first image imgpath0 = imgpaths[0] Imin = cv.LoadImage(imgpath0, cv.CV_LOAD_IMAGE_GRAYSCALE) bb0 = bbs_map.get(imgpath0, None) if bb0: coords = tuple(map(int, (bb0[0], bb0[1], bb0[2]-bb0[0], bb0[3]-bb0[1]))) cv.SetImageROI(Imin) Imax = cv.CloneImage(Imin) Iref_np = (iplimage2np(cv.CloneImage(Iref)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) bb = bbs_map.get(imgpath, None) if bb: bb = tuple(map(int, bb)) cv.SetImageROI(I, (bb[0], bb[1], bb[2]-bb[0], bb[3]-bb[1])) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin.tostring(), Imax.tostring(), cv.GetSize(Imin)
def global_align(Iref, imgpaths): """ Using IREF as a reference, aligns every image in IMGPATHS to IREF. Input: IplImage IREF: An OpenCV IplImage instance, i.e. the reference image we will align against. list IMGPATHS: A list of image paths. Output: list IOUTS. [(str imgpath, nparray H, IplImage Ireg, float err), ...]. IOUTS: A list of tuples containing the aligned image Ireg, along with the discovered transformation matrix H, alignment error ERR, and the path to the ballot image IMGPATH. """ Iouts = [] # [(imgpath, H, Ireg, err), ...] for imgpath in imgpaths: I = shared.standardImread(imgpath, flatten=True) Icrop = cropout_stuff(I, 0.2, 0.2, 0.2, 0.2) H, Ireg, err = imagesAlign(Icrop, Iref, trfm_type='rigid', rszFac=0.25) Ireg = np.nan_to_num(Ireg) Iouts.append((imgpath, H, Ireg, err)) return Iouts
def global_align(Iref, imgpaths): """ Using IREF as a reference, aligns every image in IMGPATHS to IREF. Input: IplImage IREF: An OpenCV IplImage instance, i.e. the reference image we will align against. list IMGPATHS: A list of image paths. Output: list IOUTS. [(str imgpath, nparray H, IplImage Ireg, float err), ...]. IOUTS: A list of tuples containing the aligned image Ireg, along with the discovered transformation matrix H, alignment error ERR, and the path to the ballot image IMGPATH. """ Iouts = [] # [(imgpath, H, Ireg, err), ...] for imgpath in imgpaths: I = shared.standardImread(imgpath, flatten=True) Icrop = cropout_stuff(I, 0.2, 0.2, 0.2, 0.2) H, Ireg, err = imagesAlign(Icrop, Iref, trfm_type='rigid', rszFac=0.25) Ireg = np.nan_to_num(Ireg) Iouts.append((imgpath, H, Ireg, err)) return Iouts
def overlay_minmax_cv(imgpaths, do_align=False, rszFac=1.0): imgpath = imgpaths[0] Imin = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for imgpath in imgpaths[1:]: I = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign.imagesAlign(tmp_np, Iref, fillval=0, rszFac=rszFac) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def align_strong(I, Iref, scales=(0.15, 0.2, 0.25, 0.3), crop_I=(0.05, 0.05, 0.05, 0.05), crop_Iref=None, do_nan_to_num=False): """ Alignment strategy: First, crop out 5% from each side of I. Then, try a range of scales, and choose the alignment that minimizes the error. CURRENTLY NOT USED. """ if crop_I != None: Icrop = cropout_stuff(I, crop_I[0], crop_I[1], crop_I[2], crop_I[3]) else: Icrop = I if crop_Iref != None: Iref_crop = cropout_stuff(Iref, crop_Iref[0], crop_Iref[1], crop_Iref[2], crop_Iref[3]) else: Iref_crop = Iref H_best, Ireg_best, err_best = None, None, None scale_best = None for scale in scales: H, Ireg, err = imagesAlign.imagesAlign(Icrop, Iref_crop, fillval=1, trfm_type='rigid', rszFac=scale) if err_best == None or err < err_best: H_best = H Ireg_best = Ireg err_best = err scale_best = scale # Finally, apply H_BEST to I Ireg = sh.imtransform(I, H_best) if do_nan_to_num: Ireg = np.nan_to_num(Ireg) return H_best, Ireg, err_best
def _align_image_mult(I, Iref, CROPX, CROPY, ERR_REL_THR): """ Helper function for align_image. Handles trying multiple crop parameters until an err_rel is found that is <= ERR_REL_THR. """ best_H, best_Ireg, best_err = None, None, None # L1 error, normalized by area err_orig = np.mean(np.abs(I - Iref).flatten()) for i, cropx in enumerate(CROPX): cropy = CROPY[i] I_crop = cropout_stuff(I, cropy, cropy, cropx, cropx) Iref_crop = cropout_stuff(Iref, cropy, cropy, cropx, cropx) H, err = imagesAlign.imagesAlign(I_crop, Iref_crop, trfm_type='rigid', rszFac=0.15, applyWarp=False) Ireg = sh.imtransform(I, H) err_galign = np.mean(np.abs(Ireg - Iref).flatten()) err_rel = err_galign / err_orig if err_orig != 0.0 else 0.0 if err_rel <= ERR_REL_THR: return H, Ireg, err_galign elif best_H is None or err_galign < best_err: best_H, best_Ireg, best_err = H, Ireg, err_galign return best_H, best_Ireg, best_err
def minmax_cv_V2(imgs, do_align=False, rszFac=1.0, trfm_type='rigid', minArea=np.power(2, 16)): """ Just like minmax_cv(), but accepts a list of cvMat's instead of a list of imgpaths. If you're planning on generating overlays of tens-of-thousands of images, calling this function might result in a gross-amount of memory usage (since this function keeps them all in memory at once). """ Imin = cv.CloneImage(imgs[0]) Imax = cv.CloneImage(Imin) #Iref = np.asarray(cv.CloneImage(Imin)) if do_align else None Iref = (iplimage2np(cv.CloneImage(Imin)) / 255.0) if do_align else None for I in imgs[1:]: Iout = matchsize(I, Imax) if do_align: tmp_np = iplimage2np(cv.CloneImage(Iout)) / 255.0 H, Ireg, err = imagesAlign(tmp_np, Iref, trfm_type=trfm_type, fillval=0, rszFac=rszFac, minArea=minArea) Ireg *= 255.0 Ireg = Ireg.astype('uint8') Iout = np2iplimage(Ireg) cv.Max(Iout, Imax, Imax) cv.Min(Iout, Imin, Imin) return Imin, Imax
def main(): def isimgext(f): return os.path.splitext(f)[1].lower() in ('.png', '.tif', '.tiff', '.jpg', '.jpeg') args = sys.argv[1:] imgsdir = args[0] vendor = args[1] outdir = args[2] try: N = int(args[3]) except: N = -1 if 'align' in args: # Align the barcodes when computing Min/Max overlays do_align = True else: do_align = False if 'do_cpyimg' in args: # Copy the entire images to OUTDIR (don't do this for large N!) do_cpyimg = True else: do_cpyimg = False if 'just_grouping' in args: # Just compute the barcodes + group, don't compute overlays just_grouping = True else: just_grouping = False if args[-2] == 'load': grouping = pickle.load(open(args[-1], 'rb')) else: grouping = None do_profile = True if 'profile' in args else False imgpaths = [] cnt = 0 for dirpath, dirnames, filenames in os.walk(imgsdir): for imgname in [f for f in filenames if isimgext(f)]: if N > 0 and cnt >= N: break imgpath = os.path.join(dirpath, imgname) imgpaths.append(imgpath) cnt += 1 if N > 0 and cnt >= N: break print "Starting partition_imgs..." t = time.time() if do_profile: cProfile.runctx('partition_imgs(imgpaths, vendor=vendor)', {}, {'imgpaths': imgpaths, 'vendor': vendor, 'partition_imgs': partition_imgs}) return if grouping == None: grouping = partask.do_partask(_do_partition_imgs, imgpaths, _args=(vendor, None), combfn="dict", N=None) try: os.makedirs(outdir) except: pass pickle.dump(grouping, open(os.path.join(outdir, 'grouping.p'), 'wb'), pickle.HIGHEST_PROTOCOL) dur = time.time() - t print "...Finished partition_imgs ({0} s).".format(dur) print " Avg. Time per ballot: {0} s".format(dur / len(imgpaths)) print "Copying groups to outdir {0}...".format(outdir) t = time.time() errcount = 0 for barcodes, group in grouping.iteritems(): if len(group) == 1: errcount += 1 if ("ERR0" in barcodes or "ERR1" in barcodes) else 0 continue elif "ERR0" in barcodes or "ERR1" in barcodes: #continue errcount += len(group) pass if just_grouping: continue bcs = '_'.join([thing for thing in barcodes if type(thing) == str]) rootdir = os.path.join(outdir, bcs) try: os.makedirs(rootdir) except: pass Imins = [None for _ in barcodes] Imaxes = [None for _ in barcodes] Irefs = [None for _ in barcodes] for i, (imgpath, isflip, bbs) in enumerate(group): if do_cpyimg: imgname = os.path.split(imgpath)[1] outpath_foo = os.path.join(rootdir, imgname) shutil.copy(imgpath, outpath_foo) img = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) if isflip: cv.Flip(img, img, flipMode=-1) for j, bb in enumerate(bbs): outpath = os.path.join(rootdir, str(j), "{0}_{1}.png".format(i, j)) try: os.makedirs(os.path.split(outpath)[0]) except: pass x, y, w, h = bb cv.SetImageROI(img, (x, y, w, h)) wbig, hbig = int(round(w*2.0)), int(round(h*2.0)) bcBig = cv.CreateImage((wbig, hbig), img.depth, img.channels) cv.Resize(img, bcBig, interpolation=cv.CV_INTER_CUBIC) cv.SaveImage(outpath, bcBig) if Imins[j] == None: Imins[j] = cv.CloneImage(bcBig) Imaxes[j] = cv.CloneImage(bcBig) if do_align: Irefs[j] = make_overlays.iplimage2np(cv.CloneImage(bcBig)) / 255.0 else: bcBig_sized = make_overlays.matchsize(bcBig, Imins[j]) if do_align: tmp_np = make_overlays.iplimage2np(cv.CloneImage(bcBig_sized)) / 255.0 H, Ireg, err = imagesAlign.imagesAlign(tmp_np, Irefs[j], fillval=0.2, rszFac=0.75) Ireg *= 255.0 Ireg = Ireg.astype('uint8') bcBig_sized = make_overlays.np2iplimage(Ireg) cv.Min(bcBig_sized, Imins[j], Imins[j]) cv.Max(bcBig_sized, Imaxes[j], Imaxes[j]) for idx, Imin in enumerate(Imins): Imax = Imaxes[idx] cv.SaveImage(os.path.join(rootdir, "_{0}_minimg.png".format(idx)), Imin) cv.SaveImage(os.path.join(rootdir, "_{0}_maximg.png".format(idx)), Imax) dur = time.time() - t print "...Finished Copying groups to outdir {0} ({1} s).".format(outdir, dur) print "Number of error ballots:", errcount print "Done."
def main(): def isimgext(f): return os.path.splitext(f)[1].lower() in ('.png', '.tif', '.tiff', '.jpg', '.jpeg') args = sys.argv[1:] imgsdir = args[0] vendor = args[1] outdir = args[2] try: N = int(args[3]) except: N = -1 if 'align' in args: # Align the barcodes when computing Min/Max overlays do_align = True else: do_align = False if 'do_cpyimg' in args: # Copy the entire images to OUTDIR (don't do this for large N!) do_cpyimg = True else: do_cpyimg = False if 'just_grouping' in args: # Just compute the barcodes + group, don't compute overlays just_grouping = True else: just_grouping = False if args[-2] == 'load': grouping = pickle.load(open(args[-1], 'rb')) else: grouping = None do_profile = True if 'profile' in args else False imgpaths = [] cnt = 0 for dirpath, dirnames, filenames in os.walk(imgsdir): for imgname in [f for f in filenames if isimgext(f)]: if N > 0 and cnt >= N: break imgpath = os.path.join(dirpath, imgname) imgpaths.append(imgpath) cnt += 1 if N > 0 and cnt >= N: break print "Starting partition_imgs..." t = time.time() if do_profile: cProfile.runctx('partition_imgs(imgpaths, vendor=vendor)', {}, { 'imgpaths': imgpaths, 'vendor': vendor, 'partition_imgs': partition_imgs }) return if grouping == None: grouping = partask.do_partask(_do_partition_imgs, imgpaths, _args=(vendor, None), combfn="dict", N=None) try: os.makedirs(outdir) except: pass pickle.dump(grouping, open(os.path.join(outdir, 'grouping.p'), 'wb'), pickle.HIGHEST_PROTOCOL) dur = time.time() - t print "...Finished partition_imgs ({0} s).".format(dur) print " Avg. Time per ballot: {0} s".format(dur / len(imgpaths)) print "Copying groups to outdir {0}...".format(outdir) t = time.time() errcount = 0 for barcodes, group in grouping.iteritems(): if len(group) == 1: errcount += 1 if ("ERR0" in barcodes or "ERR1" in barcodes) else 0 continue elif "ERR0" in barcodes or "ERR1" in barcodes: #continue errcount += len(group) pass if just_grouping: continue bcs = '_'.join([thing for thing in barcodes if type(thing) == str]) rootdir = os.path.join(outdir, bcs) try: os.makedirs(rootdir) except: pass Imins = [None for _ in barcodes] Imaxes = [None for _ in barcodes] Irefs = [None for _ in barcodes] for i, (imgpath, isflip, bbs) in enumerate(group): if do_cpyimg: imgname = os.path.split(imgpath)[1] outpath_foo = os.path.join(rootdir, imgname) shutil.copy(imgpath, outpath_foo) img = cv.LoadImage(imgpath, cv.CV_LOAD_IMAGE_GRAYSCALE) if isflip: cv.Flip(img, img, flipMode=-1) for j, bb in enumerate(bbs): outpath = os.path.join(rootdir, str(j), "{0}_{1}.png".format(i, j)) try: os.makedirs(os.path.split(outpath)[0]) except: pass x, y, w, h = bb cv.SetImageROI(img, (x, y, w, h)) wbig, hbig = int(round(w * 2.0)), int(round(h * 2.0)) bcBig = cv.CreateImage((wbig, hbig), img.depth, img.channels) cv.Resize(img, bcBig, interpolation=cv.CV_INTER_CUBIC) cv.SaveImage(outpath, bcBig) if Imins[j] == None: Imins[j] = cv.CloneImage(bcBig) Imaxes[j] = cv.CloneImage(bcBig) if do_align: Irefs[j] = make_overlays.iplimage2np( cv.CloneImage(bcBig)) / 255.0 else: bcBig_sized = make_overlays.matchsize(bcBig, Imins[j]) if do_align: tmp_np = make_overlays.iplimage2np( cv.CloneImage(bcBig_sized)) / 255.0 H, Ireg, err = imagesAlign.imagesAlign(tmp_np, Irefs[j], fillval=0.2, rszFac=0.75) Ireg *= 255.0 Ireg = Ireg.astype('uint8') bcBig_sized = make_overlays.np2iplimage(Ireg) cv.Min(bcBig_sized, Imins[j], Imins[j]) cv.Max(bcBig_sized, Imaxes[j], Imaxes[j]) for idx, Imin in enumerate(Imins): Imax = Imaxes[idx] cv.SaveImage(os.path.join(rootdir, "_{0}_minimg.png".format(idx)), Imin) cv.SaveImage(os.path.join(rootdir, "_{0}_maximg.png".format(idx)), Imax) dur = time.time() - t print "...Finished Copying groups to outdir {0} ({1} s).".format( outdir, dur) print "Number of error ballots:", errcount print "Done."
def make_minmax_overlay(imgpaths, do_align=False, rszFac=1.0, imgCache=None, queue_mygauge=None, bindataP=None): """ Generates the min/max overlays of a set of imagepaths. If the images in IMGPATHS are of different size, then this function arbitrarily chooses the first image to be the size of the output IMIN, IMAX. Input: list IMGPATHS: bool DO_ALIGN: If True, then this will choose an arbitrary image A as a reference image, and align every image in IMGPATHS to A. float RSZFAC: Which scale to perform image alignment at. obj IMGCACHE: If given, the function will use IMGCACHE, an instance of the ImageCache class, to load images. Otherwise, it will always read each image from disk. Output: (nparray Imin, nparray Imax). """ # TODO: Implement with bbs_map def load_image(imgpath): if imgCache == None: return misc.imread(imgpath, flatten=True) elif bindataP != None: (img, tag), isHit = imgCache.load_binarydat(imgpath, bindataP) return img else: (img, imgpath), isHit = imgCache.load(imgpath) return img overlayMin, overlayMax = None, None Iref = None for path in imgpaths: img = load_image(path) if do_align and Iref == None: Iref = img elif do_align: (H, img, err) = imagesAlign(img, Iref, fillval=0, rszFac=rszFac) if (overlayMin == None): overlayMin = img else: if overlayMin.shape != img.shape: h, w = overlayMin.shape img = resize_img_norescale(img, (w,h)) overlayMin = np.fmin(overlayMin, img) if (overlayMax == None): overlayMax = img else: if overlayMax.shape != img.shape: h, w = overlayMax.shape img = resize_img_norescale(img, (w,h)) overlayMax = np.fmax(overlayMax, img) if queue_mygauge != None: queue_mygauge.put(True) # HACK: To prevent auto-dynamic-rescaling bugs, where an all-white # image is interpreted as all-black, artificially insert a 0.0 at (0,0). # See: http://stefaanlippens.net/scipy_unscaledimsave overlayMin[0,0] = 0.0 overlayMax[0,0] = 0.0 return overlayMin, overlayMax
def imgpaths_to_mat2D(imgpaths, bb_map=None, do_align=False, return_align_errs=False, do_edgedetect=False, LOW_T=75, RATIO=3, BORDER=5): """ Converts imgpaths into an NxHxW matrix, where N is the number of images, and (H,W) is the shape of each image. Input: list imgpaths: dict bb_map: bool do_align: If True, then this will align all images to an arbitrary image. bool return_align_errs: If True, then this function will also return the alignment error for each image. bool do_edgedetect: Perform Canny edge detection (with params LOW_T, RATIO) on IMGPATHS as a pre-processing step. int BORDER: How many pixels to remove from the borders of the image. """ if bb_map == None: bb_map = {} h_big, w_big = get_largest_img_dims(imgpaths) else: bb_big = get_largest_bb(bb_map.values()) h_big = int(abs(bb_big[0] - bb_big[1])) w_big = int(abs(bb_big[2] - bb_big[3])) # 0.) First, convert images into MxHxW array, where M is the number # of images, and (H,W) are image sizes. data = np.zeros((len(imgpaths), h_big-(2*BORDER), w_big-(2*BORDER))) #data = np.zeros((len(imgpaths), h_big, w_big)) Iref = None alignerrs = [None] * len(imgpaths) # [float err_i, ...] alignerrs = np.zeros((len(imgpaths), 1)) for row, imgpath in enumerate(imgpaths): img = scipy.misc.imread(imgpath, flatten=True) bb = bb_map.get(imgpath, None) if bb == None: patch = resize_mat(img, (h_big, w_big)) else: # Must make sure that all patches are the same shape. patch = resize_mat(img[bb[0]:bb[1], bb[2]:bb[3]], (h_big, w_big)) if do_edgedetect: patch = edgedetect(patch) if do_align and Iref == None: Iref = patch elif do_align: H, patch, err = imagesAlign.imagesAlign(patch, Iref) patch_img = np.nan_to_num(patch) #patch = patch_img try: os.makedirs("alignedimgs") except: pass #scipy.misc.imsave(os.path.join("alignedimgs", "{0}_{1}.png".format(row, err)), # patch_img) scipy.misc.imsave(os.path.join("alignedimgs", "{0}.png".format(row)), patch_img) print "alignment err:", err if return_align_errs: alignerrs[row] = err # Crop out window patch = patch[BORDER:patch.shape[0]-BORDER, BORDER:patch.shape[1]-BORDER] data[row,:,:] = patch if return_align_errs: return data, alignerrs return data
def make_minmax_overlay(imgpaths, do_align=False, rszFac=1.0, imgCache=None, queue_mygauge=None, bindataP=None): """ Generates the min/max overlays of a set of imagepaths. If the images in IMGPATHS are of different size, then this function arbitrarily chooses the first image to be the size of the output IMIN, IMAX. Input: list IMGPATHS: bool DO_ALIGN: If True, then this will choose an arbitrary image A as a reference image, and align every image in IMGPATHS to A. float RSZFAC: Which scale to perform image alignment at. obj IMGCACHE: If given, the function will use IMGCACHE, an instance of the ImageCache class, to load images. Otherwise, it will always read each image from disk. Output: (nparray Imin, nparray Imax). """ # TODO: Implement with bbs_map def load_image(imgpath): if imgCache == None: return misc.imread(imgpath, flatten=True) elif bindataP != None: (img, tag), isHit = imgCache.load_binarydat(imgpath, bindataP) return img else: (img, imgpath), isHit = imgCache.load(imgpath) return img overlayMin, overlayMax = None, None Iref = None for path in imgpaths: img = load_image(path) if do_align and Iref == None: Iref = img elif do_align: (H, img, err) = imagesAlign(img, Iref, fillval=0, rszFac=rszFac) if (overlayMin == None): overlayMin = img else: if overlayMin.shape != img.shape: h, w = overlayMin.shape img = resize_img_norescale(img, (w, h)) overlayMin = np.fmin(overlayMin, img) if (overlayMax == None): overlayMax = img else: if overlayMax.shape != img.shape: h, w = overlayMax.shape img = resize_img_norescale(img, (w, h)) overlayMax = np.fmax(overlayMax, img) if queue_mygauge != None: queue_mygauge.put(True) # HACK: To prevent auto-dynamic-rescaling bugs, where an all-white # image is interpreted as all-black, artificially insert a 0.0 at (0,0). # See: http://stefaanlippens.net/scipy_unscaledimsave overlayMin[0, 0] = 0.0 overlayMax[0, 0] = 0.0 return overlayMin, overlayMax
def imgpaths_to_mat(imgpaths, bb_map=None, do_align=False, return_align_errs=False, rszFac=None, MIN_DIM=None, MAX_DIM=None, imgCache=None, bindataP=None, VERBOSE=False): """ Reads in a series of imagepaths, and converts it to an NxM matrix, where N is the number of images, and M is the (w*h), where w,h are the width/height of the largest image in IMGPATHS. If BB_MAP is given, then this will extract a patch from the associated IMGPATH. Two different resize modes: RSZFAC, and the (MIN_DIM, MAX_DIM). """ def load_image(imgpath): if imgCache is None: return scipy.misc.imread(imgpath, flatten=True) elif bindataP is not None: (Inp, tag), isHit = imgCache.load_binarydat(imgpath, dataP=bindataP) return Inp else: (Inp, imgpath), isHit = imgCache.load(imgpath) return Inp if bb_map is None: bb_map = {} if bindataP is not None: w_big, h_big = imgCache.binarydats_map[bindataP][1] else: h_big, w_big = get_largest_img_dims(imgpaths) else: bb_big = get_largest_bb(bb_map.values()) h_big = int(abs(bb_big[0] - bb_big[1])) w_big = int(abs(bb_big[2] - bb_big[3])) # 0.) First, convert images into MxN array, where M is the number # of images, and N is the number of pixels of each image. if rszFac is not None: w_out, h_out = int(round(rszFac * w_big)), int(round(rszFac * h_big)) elif MIN_DIM is not None and MAX_DIM is not None: if h_big <= MIN_DIM or w_big <= MIN_DIM: rszFac = 1.0 else: rszFac = min(1.0, MAX_DIM / float(max(w_big, h_big))) if (rszFac * w_big) <= MIN_DIM or (rszFac * h_big) <= MIN_DIM: rszFac = float(MIN_DIM / float(min(w_big, h_big))) w_out, h_out = int(round(rszFac * w_big)), int(round(rszFac * h_big)) else: w_out, h_out = w_big, h_big debug("imgpaths_to_mat -- using rszFac={0}", rszFac) data = np.zeros((len(imgpaths), h_out * w_out), dtype='float32') Iref = None if return_align_errs: alignerrs = [None] * len(imgpaths) # [float err_i, ...] alignerrs = np.zeros((len(imgpaths), 1)) else: alignerrs = None for row, imgpath in enumerate(imgpaths): img = load_image(imgpath) bb = bb_map.get(imgpath, None) if bb is None: patch = resize_mat(img, (h_out, w_out), rszFac=rszFac) else: # Must make sure that all patches are the same shape. patch = resize_mat(img[bb[0]:bb[1], bb[2]:bb[3]], (h_out, w_out), rszFac=rszFac) if do_align and Iref is None: Iref = patch elif do_align: # Looks like imagesAlign requires input images to be of dtype # float32, to allow usage of NaN's. if patch.dtype != 'float32': patch = patch.astype('float32') if Iref.dtype != 'float32': Iref = Iref.astype('float32') H, patch, err = imagesAlign.imagesAlign(patch, Iref) if return_align_errs: alignerrs[row] = err patch = np.nan_to_num(patch) # Reshape 'patch' to be a single row of pixels, instead of rows # of pixels. patch = patch.reshape(1, patch.shape[0] * patch.shape[1]) data[row, :] = patch if return_align_errs: return data, alignerrs return data
def imgpaths_to_mat2D(imgpaths, bb_map=None, do_align=False, return_align_errs=False, do_edgedetect=False, LOW_T=75, RATIO=3, BORDER=5): """ Converts imgpaths into an NxHxW matrix, where N is the number of images, and (H,W) is the shape of each image. Input: list imgpaths: dict bb_map: bool do_align: If True, then this will align all images to an arbitrary image. bool return_align_errs: If True, then this function will also return the alignment error for each image. bool do_edgedetect: Perform Canny edge detection (with params LOW_T, RATIO) on IMGPATHS as a pre-processing step. int BORDER: How many pixels to remove from the borders of the image. """ if bb_map is None: bb_map = {} h_big, w_big = get_largest_img_dims(imgpaths) else: bb_big = get_largest_bb(bb_map.values()) h_big = int(abs(bb_big[0] - bb_big[1])) w_big = int(abs(bb_big[2] - bb_big[3])) # 0.) First, convert images into MxHxW array, where M is the number # of images, and (H,W) are image sizes. data = np.zeros( (len(imgpaths), h_big - (2 * BORDER), w_big - (2 * BORDER))) # data = np.zeros((len(imgpaths), h_big, w_big)) Iref = None alignerrs = [None] * len(imgpaths) # [float err_i, ...] alignerrs = np.zeros((len(imgpaths), 1)) for row, imgpath in enumerate(imgpaths): img = scipy.misc.imread(imgpath, flatten=True) bb = bb_map.get(imgpath, None) if bb is None: patch = resize_mat(img, (h_big, w_big)) else: # Must make sure that all patches are the same shape. patch = resize_mat(img[bb[0]:bb[1], bb[2]:bb[3]], (h_big, w_big)) if do_edgedetect: patch = edgedetect(patch) if do_align and Iref is None: Iref = patch elif do_align: H, patch, err = imagesAlign.imagesAlign(patch, Iref) patch_img = np.nan_to_num(patch) # patch = patch_img try: os.makedirs("alignedimgs") except: pass # scipy.misc.imsave(os.path.join("alignedimgs", "{0}_{1}.png".format(row, err)), # patch_img) scipy.misc.imsave( os.path.join("alignedimgs", "{0}.png".format(row)), patch_img) error("alignment err: {0}", err) if return_align_errs: alignerrs[row] = err # Crop out window patch = patch[BORDER:patch.shape[0] - BORDER, BORDER:patch.shape[1] - BORDER] data[row, :, :] = patch if return_align_errs: return data, alignerrs return data
def imgpaths_to_mat(imgpaths, bb_map=None, do_align=False, return_align_errs=False, rszFac=None, MIN_DIM=None, MAX_DIM=None, imgCache=None, bindataP=None, VERBOSE=False): """ Reads in a series of imagepaths, and converts it to an NxM matrix, where N is the number of images, and M is the (w*h), where w,h are the width/height of the largest image in IMGPATHS. If BB_MAP is given, then this will extract a patch from the associated IMGPATH. Two different resize modes: RSZFAC, and the (MIN_DIM, MAX_DIM). """ def load_image(imgpath): if imgCache == None: return scipy.misc.imread(imgpath, flatten=True) elif bindataP != None: (Inp, tag), isHit = imgCache.load_binarydat(imgpath, dataP=bindataP) return Inp else: (Inp, imgpath), isHit = imgCache.load(imgpath) return Inp if bb_map == None: bb_map = {} if bindataP != None: w_big, h_big = imgCache.binarydats_map[bindataP][1] else: h_big, w_big = get_largest_img_dims(imgpaths) else: bb_big = get_largest_bb(bb_map.values()) h_big = int(abs(bb_big[0] - bb_big[1])) w_big = int(abs(bb_big[2] - bb_big[3])) # 0.) First, convert images into MxN array, where M is the number # of images, and N is the number of pixels of each image. if rszFac != None: w_out, h_out = int(round(rszFac*w_big)), int(round(rszFac*h_big)) elif MIN_DIM != None and MAX_DIM != None: if h_big <= MIN_DIM or w_big <= MIN_DIM: rszFac = 1.0 else: rszFac = min(1.0, MAX_DIM / float(max(w_big, h_big))) if (rszFac * w_big) <= MIN_DIM or (rszFac * h_big) <= MIN_DIM: rszFac = float(MIN_DIM / float(min(w_big, h_big))) w_out, h_out = int(round(rszFac * w_big)), int(round(rszFac * h_big)) else: w_out, h_out = w_big, h_big printv("imgpaths_to_mat -- using rszFac={0}".format(rszFac), VERBOSE) data = np.zeros((len(imgpaths), h_out*w_out), dtype='float32') Iref = None if return_align_errs: alignerrs = [None] * len(imgpaths) # [float err_i, ...] alignerrs = np.zeros((len(imgpaths), 1)) else: alignerrs = None for row, imgpath in enumerate(imgpaths): img = load_image(imgpath) bb = bb_map.get(imgpath, None) if bb == None: patch = resize_mat(img, (h_out, w_out), rszFac=rszFac) else: # Must make sure that all patches are the same shape. patch = resize_mat(img[bb[0]:bb[1], bb[2]:bb[3]], (h_out, w_out), rszFac=rszFac) if do_align and Iref == None: Iref = patch elif do_align: # Looks like imagesAlign requires input images to be of dtype # float32, to allow usage of NaN's. if patch.dtype != 'float32': patch = patch.astype('float32') if Iref.dtype != 'float32': Iref = Iref.astype('float32') H, patch, err = imagesAlign.imagesAlign(patch, Iref) if return_align_errs: alignerrs[row] = err patch = np.nan_to_num(patch) # Reshape 'patch' to be a single row of pixels, instead of rows # of pixels. patch = patch.reshape(1, patch.shape[0]*patch.shape[1]) data[row,:] = patch if return_align_errs: return data, alignerrs return data