def createPatchTuplesMAP(balL, attr2pat, R, flip=False): """ Sort of creates 'tasks' for groupImagesWorkerMAP, where each task is a tuple of the form: (imgpatch_i, [attrpatch_i, ...], attrval_i, side_i, isflip_i) And you create one task for each side of a voted ballot (i.e. one for side0, another for side1, ...), to figure out the imgorder. Note that there can be multiple exemplar attrpatches. Input: tuple balL: (sidepath_i, ...) dict attr2pat: maps {str attrval: [(str imgpath, obj imgpatch_i), ...]} tuple R: (y1, y2, x1, x2). A 'super' region. Output: ((obj imgpatch_i, [obj attrpatch_i0, ...], str attrval_i, int side_i, int isflip_i), ...) """ pFac = 1 patchTuples = [] for idx in range(len(balL)): balP = balL[idx] I = sh.standardImread(balP, flatten=True) if flip: I = sh.fastFlip(I) (rOut, rOff) = sh.expand(R[0], R[1], R[2], R[3], I.shape[0], I.shape[1], pFac) I1 = I[rOut[0]:rOut[1], rOut[2]:rOut[3]] for attrval, exemplar_pairs in attr2pat.iteritems(): exmpl_patches = [t[1] for t in exemplar_pairs] patchTuples.append((I1, exmpl_patches, attrval, idx, flip)) return patchTuples
def createPatchTuplesMAP(balL,attr2pat,R,flip=False): """ Sort of creates 'tasks' for groupImagesWorkerMAP, where each task is a tuple of the form: (imgpatch_i, [attrpatch_i, ...], attrval_i, side_i, isflip_i) And you create one task for each side of a voted ballot (i.e. one for side0, another for side1, ...), to figure out the imgorder. Note that there can be multiple exemplar attrpatches. Input: tuple balL: (sidepath_i, ...) dict attr2pat: maps {str attrval: [(str imgpath, obj imgpatch_i), ...]} tuple R: (y1, y2, x1, x2). A 'super' region. Output: ((obj imgpatch_i, [obj attrpatch_i0, ...], str attrval_i, int side_i, int isflip_i), ...) """ pFac=1; patchTuples=[]; for idx in range(len(balL)): balP=balL[idx] I=sh.standardImread(balP,flatten=True) if flip: I = sh.fastFlip(I) (rOut,rOff)=sh.expand(R[0],R[1],R[2],R[3],I.shape[0],I.shape[1],pFac) I1=I[rOut[0]:rOut[1],rOut[2]:rOut[3]] for attrval, exemplar_pairs in attr2pat.iteritems(): exmpl_patches = [t[1] for t in exemplar_pairs] patchTuples.append((I1, exmpl_patches, attrval, idx, flip)) return patchTuples
def main(): patchpath = 'patch_tmp.png' regionpath = 'allpatches_tmp.png' imgpatch = shared.standardImread(patchpath, flatten=True) h, w = imgpatch.shape bb = [0, h-1, 0, w-1] matches = shared.find_patch_matchesV1(imgpatch, bb, (regionpath,)) print 'Num Matches:', len(matches)
def main(): patchpath = 'patch_tmp.png' regionpath = 'allpatches_tmp.png' imgpatch = shared.standardImread(patchpath, flatten=True) h, w = imgpatch.shape bb = [0, h - 1, 0, w - 1] matches = shared.find_patch_matchesV1(imgpatch, bb, (regionpath, )) print 'Num Matches:', len(matches)
def templateSSWorker(job): # dict attr2pat: maps {str attrval: [[str imgpath_i, obj patch_i], ...]} (attr2pat, attrval, superRegion, sStep, img2flip) = job attr2pat1 = attr2pat.copy() # TODO: Arbitrarily chooses a patch_i (imgpath, patch) = attr2pat1[attrval][0] isflip = img2flip[imgpath] I = sh.standardImread(imgpath, flatten=True) superRegionNp = np.array(superRegion) patchTuples = createPatchTuples(I, attr2pat1, superRegionNp, flip=isflip) sc0 = sh.resizeOrNot(patch.shape, sh.MAX_PRECINCT_PATCH_DIM) minSc = sh.resizeOrNot(patch.shape, sh.MIN_PRECINCT_PATCH_DIM) (scores0, locs, exemplar_idxs) = dist2patches(patchTuples, sc0) sidx = np.argsort(scores0) sidx = sidx[::-1] trackIdx = sidx[0] # sc1 is the 'scale' that we're currently working with. sc1 = sc0 - sStep # Starting scale. while sc1 > minSc: try: (scores, locs, exemplar_idxs) = dist2patches(patchTuples, sc1) except Exception as e: d = {'patchTuples': patchTuples, 'sc1': sc1} path = '_errdict_0' ''' while os.path.exists(path): new_i = int(path.split("_")[-1]) + 1 path = '_errdict_{0}'.format(str(new_i)) print '...outputting debug info to:', path pickle.dump(d, open(path, 'wb')) ''' print "Exiting." exit(1) sidx = np.argsort(scores) sidx = sidx[::-1] mid = np.ceil(len(sidx) / 2.0) dumpIdx = sidx[mid:len(sidx)] if sum(0 + (dumpIdx == trackIdx)) > 0: break else: # decrease the scale sc1 = sc1 - sStep # write scale to file #toWrite={"scale": min(sc1+sStep,sc0)} #file = open(fOut, "wb") #pickle.dump(toWrite, file) #file.close() templateSSWorker.queue.put(min(sc1 + sStep, sc0))
def templateSSWorker(job): # dict attr2pat: maps {str attrval: [[str imgpath_i, obj patch_i], ...]} (attr2pat, attrval, superRegion, sStep, img2flip) = job attr2pat1=attr2pat.copy() # TODO: Arbitrarily chooses a patch_i (imgpath, patch) = attr2pat1[attrval][0] isflip = img2flip[imgpath] I=sh.standardImread(imgpath,flatten=True) superRegionNp=np.array(superRegion) patchTuples=createPatchTuples(I,attr2pat1,superRegionNp,flip=isflip) sc0=sh.resizeOrNot(patch.shape,sh.MAX_PRECINCT_PATCH_DIM) minSc=sh.resizeOrNot(patch.shape,sh.MIN_PRECINCT_PATCH_DIM) (scores0,locs,exemplar_idxs)=dist2patches(patchTuples,sc0) sidx=np.argsort(scores0) sidx=sidx[::-1] trackIdx=sidx[0] # sc1 is the 'scale' that we're currently working with. sc1=sc0-sStep # Starting scale. while sc1>minSc: try: (scores,locs, exemplar_idxs)=dist2patches(patchTuples,sc1) except Exception as e: d = {'patchTuples': patchTuples, 'sc1': sc1} path = '_errdict_0' ''' while os.path.exists(path): new_i = int(path.split("_")[-1]) + 1 path = '_errdict_{0}'.format(str(new_i)) print '...outputting debug info to:', path pickle.dump(d, open(path, 'wb')) ''' print "Exiting." exit(1) sidx=np.argsort(scores) sidx=sidx[::-1] mid=np.ceil(len(sidx)/2.0) dumpIdx=sidx[mid:len(sidx)] if sum(0+(dumpIdx==trackIdx))>0: break else: # decrease the scale sc1=sc1-sStep # write scale to file #toWrite={"scale": min(sc1+sStep,sc0)} #file = open(fOut, "wb") #pickle.dump(toWrite, file) #file.close() templateSSWorker.queue.put(min(sc1+sStep, sc0))
def main(): args = sys.argv[1:] if not args: imgA = 'imgA.png' imgB = 'imgB.png' else: imgA = args[0] imgB = args[1] Ia = shared.standardImread(imgA, True) Ib = shared.standardImread(imgB, True) print "Aligning {0} to {1}...".format(imgA, imgB) H, Ireg, err = imagesAlign.imagesAlign(Ia, Ib) Ireg_nonan = np.nan_to_num(Ireg) scipy.misc.imsave("_IregA.png", Ireg_nonan) print "Done, outputted result to: _IregA.png"
def main(): regions = ['extracted_digitpatches/precinct/0_exemplar.png', 'extracted_digitpatches/precinct/1_exemplar.png', 'extracted_digitpatches/precinct/2_exemplar.png'] img1 = shared.standardImread(img1path, flatten=True) (h,w) = img1.shape bb = [0, h-1, 0, w-1] print "bb is:", bb matches = shared.find_patch_matchesV1(img1, bb, regions, threshold=0.7) print 'Found {0} number of matches.'.format(len(matches))
def main(): I_np = shared.standardImread(Ipath, flatten=True) I_np = shared.prepOpenCV(I_np) cv_imgBAD = cv.fromarray(np.copy(I_np)) cv.SaveImage("party_CV_BAD.png", cv_imgBAD) cv_imgGOOD = cv.fromarray(np.copy(I_np) * 255.0) cv.SaveImage("party_CV_GOOD.png", cv_imgGOOD) print "Done."
def main(): regions = [ 'extracted_digitpatches/precinct/0_exemplar.png', 'extracted_digitpatches/precinct/1_exemplar.png', 'extracted_digitpatches/precinct/2_exemplar.png' ] img1 = shared.standardImread(img1path, flatten=True) (h, w) = img1.shape bb = [0, h - 1, 0, w - 1] print "bb is:", bb matches = shared.find_patch_matchesV1(img1, bb, regions, threshold=0.7) print 'Found {0} number of matches.'.format(len(matches))
def debugWorker(job): (Iref, bbs, fIn, destDir, extractedMeta, contestMeta, f1) = job I=sh.standardImread(fIn) # trim down or expand I to fit Iref I1=np.ones([Iref.shape[0],Iref.shape[1]],dtype='float32') h=min(Iref.shape[0],I.shape[0])-1; w=min(Iref.shape[1],I.shape[1])-1; I1[1:h,1:w]=I[1:h,1:w] # check if ballot is flipped res=checkBallotFlipped(I1,Iref) Ichk=res[1]; flipped=res[0] # extract target and write result return (Ichk,extractTargets(Ichk,Iref,bbs))
def debugWorker(job): (Iref, bbs, fIn, destDir, extractedMeta, contestMeta, f1) = job I = sh.standardImread(fIn) # trim down or expand I to fit Iref I1 = np.ones([Iref.shape[0], Iref.shape[1]], dtype='float32') h = min(Iref.shape[0], I.shape[0]) - 1 w = min(Iref.shape[1], I.shape[1]) - 1 I1[1:h, 1:w] = I[1:h, 1:w] # check if ballot is flipped res = checkBallotFlipped(I1, Iref) Ichk = res[1] flipped = res[0] # extract target and write result return (Ichk, extractTargets(Ichk, Iref, bbs))
def main(): patch = shared.standardImread(imgA, flatten=True) h, w = patch.shape bb = [0, h, 0, w] matches = shared.find_patch_matchesV1(patch, bb, (imgB,), threshold=0.0) filename,score1,score2,Ireg,y1,y2,x1,x2,rszFac = matches[0] print "Score1 is: {0}".format(score1) print " This is low, which is good." print "Score2 is: {0}".format(score2) print " This is super low, which is /bad/. The two patches are \ very different." print "I think this is the root of the problem: if I save the \ Ireg outputted by find_patch_matchesV1, then I get an all-black \ output image." print "Saving Ireg as: Ireg_out.png" scipy.misc.imsave('Ireg_out.png', Ireg)
def groupByAttr(bal2imgs, img2page, img2flip, attrName, side, attrMap, patchDestDir, stopped, proj, verbose=False, deleteall=True): """ Input: dict bal2imgs: maps {str ballotid: (sidepath_i, ...)} dict IMG2PAGE: dict IMG2FLIP: str attrName: the current attribute type int SIDE: dict attrMap: maps {str attrtype: {str attrval: (bb, str side, blankpath)}} str patchDestDir: A directory, i.e. 'extracted_precincts-ballottype', stores the extracted attribute image patches. fn stopped: obj proj: options: bool deleteall: if True, this will first remove all output files before computing. """ if deleteall: if os.path.exists(patchDestDir): shutil.rmtree(patchDestDir) create_dirs(patchDestDir) # maps {str attrval: [(str exmpl_imP, obj imagepatch), ...]} attr2pat = {} superRegion = (float('inf'), 0, float('inf'), 0) # attrValMap: {str attrval: (bb, str side, blankpath)} attrValMap = attrMap[attrName] # 0.) First, grab an exemplar patch for each attrval. Add them to # attr2pat. # multexemplars_map: maps {attrtype: {attrval: ((str patchpath_i, str blankpath_i, (x1,y1,x2,y2)), ...)}} multexemplars_map = pickle.load( open(pathjoin(proj.projdir_path, proj.multexemplars_map), 'rb')) exemplar_dict = multexemplars_map[attrName] for attrval, exemplars in exemplar_dict.iteritems(): # Sort, in order to provide a canonical ordering exemplars_sorted = sorted(exemplars, key=lambda t: t[0]) for (patchpath, blankpath, (x1, y1, x2, y2)) in exemplars_sorted: P = sh.standardImread(patchpath, flatten=True) attr2pat.setdefault(attrval, []).append((blankpath, P)) superRegion = sh.bbUnion(superRegion, (y1, y2, x1, x2)) for _attr, patches in attr2pat.iteritems(): print 'for attr {0}, there are {1} exemplars'.format( _attr, len(patches)) # 1.) Estimate smallest viable scale (for performance) if len(attr2pat) > 2: scale = estimateScale(attr2pat, img2flip, superRegion, sh.MAX_PRECINCT_PATCH_DIM, stopped) else: scale = sh.resizeOrNot(P.shape, sh.MAX_PRECINCT_PATCH_DIM) print 'ATTR: ', attrName, ': using starting scale:', scale # 2.) Generate jobs for the multiprocessing nProc = sh.numProcs() #nProc = 1 manager = mp.Manager() queue = manager.Queue() queue_progress = manager.Queue() # Used for MyGauge updates pool = mp.Pool(processes=nProc) jobs = [] for ballotid in bal2imgs.keys(): imgpaths = bal2imgs[ballotid] imgpaths_ordered = sorted(imgpaths, key=lambda imP: img2page[imP]) imgpath_in = imgpaths_ordered[side] isflip = img2flip[imgpath_in] jobs.append([ ballotid, [imgpath_in], attrName, superRegion, attr2pat, isflip, scale, patchDestDir, queue, queue_progress ]) print "Number of jobs:", len(jobs) # 3.) Perform jobs. if nProc < 2: # default behavior for non multiproc machines for job in jobs: if stopped(): return False groupImagesWorkerMAP(job) else: print 'using ', nProc, ' processes' it = [False] def imdone(x): it[0] = True print "I AM DONE NOW! WOW" pool.map_async(groupImagesWorkerMAP, jobs, callback=lambda x: imdone(it)) i = 0 while i < len(jobs): job_status, job_ballotid = queue_progress.get( ) # Blocks until value is ready if job_status == False: print "...Uhoh, ballotid={0} had a grouping failure.".format( job_ballotid) if wx.App.IsMainLoopRunning(): wx.CallAfter(Publisher().sendMessage, "signals.MyGauge.tick", (JOBID_GROUPING_IMGBASED, )) i += 1 while not it[0]: if stopped(): print ' UHOH, stopped' pool.terminate() return False time.sleep(.1) print "HERE" pool.close() pool.join() print "GOT HERE." # list RESULTS: [[int ballotid, attrtype, dict outdict], ...] results = [] cnt = 0 while cnt < len(jobs): res = queue.get() if type(res) in (str, unicode): print "OH NO, badness happened." else: results.append(res) cnt += 1 print 'cnt: ', cnt # TODO: quarantine on grouping errors. For now, just let alignment check handle it print 'ATTR: ', attrName, ': done' return results
def groupByAttr(bal2imgs, img2page, img2flip, attrName, side, attrMap, patchDestDir, stopped, proj, verbose=False, deleteall=True): """ Input: dict bal2imgs: maps {str ballotid: (sidepath_i, ...)} dict IMG2PAGE: dict IMG2FLIP: str attrName: the current attribute type int SIDE: dict attrMap: maps {str attrtype: {str attrval: (bb, str side, blankpath)}} str patchDestDir: A directory, i.e. 'extracted_precincts-ballottype', stores the extracted attribute image patches. fn stopped: obj proj: options: bool deleteall: if True, this will first remove all output files before computing. """ if deleteall: if os.path.exists(patchDestDir): shutil.rmtree(patchDestDir) create_dirs(patchDestDir) # maps {str attrval: [(str exmpl_imP, obj imagepatch), ...]} attr2pat={} superRegion=(float('inf'),0,float('inf'),0) # attrValMap: {str attrval: (bb, str side, blankpath)} attrValMap=attrMap[attrName] # 0.) First, grab an exemplar patch for each attrval. Add them to # attr2pat. # multexemplars_map: maps {attrtype: {attrval: ((str patchpath_i, str blankpath_i, (x1,y1,x2,y2)), ...)}} multexemplars_map = pickle.load(open(pathjoin(proj.projdir_path, proj.multexemplars_map), 'rb')) exemplar_dict = multexemplars_map[attrName] for attrval, exemplars in exemplar_dict.iteritems(): # Sort, in order to provide a canonical ordering exemplars_sorted = sorted(exemplars, key=lambda t: t[0]) for (patchpath, blankpath, (x1,y1,x2,y2)) in exemplars_sorted: P = sh.standardImread(patchpath, flatten=True) attr2pat.setdefault(attrval, []).append((blankpath, P)) superRegion = sh.bbUnion(superRegion, (y1,y2,x1,x2)) for _attr, patches in attr2pat.iteritems(): print 'for attr {0}, there are {1} exemplars'.format(_attr, len(patches)) # 1.) Estimate smallest viable scale (for performance) if len(attr2pat)>2: scale = estimateScale(attr2pat,img2flip,superRegion,sh.MAX_PRECINCT_PATCH_DIM,stopped) else: scale = sh.resizeOrNot(P.shape,sh.MAX_PRECINCT_PATCH_DIM); print 'ATTR: ', attrName,': using starting scale:',scale # 2.) Generate jobs for the multiprocessing nProc=sh.numProcs() #nProc = 1 manager = mp.Manager() queue = manager.Queue() queue_progress = manager.Queue() # Used for MyGauge updates pool = mp.Pool(processes=nProc) jobs = [] for ballotid in bal2imgs.keys(): imgpaths = bal2imgs[ballotid] imgpaths_ordered = sorted(imgpaths, key=lambda imP: img2page[imP]) imgpath_in = imgpaths_ordered[side] isflip = img2flip[imgpath_in] jobs.append([ballotid, [imgpath_in], attrName, superRegion, attr2pat, isflip, scale, patchDestDir, queue, queue_progress]) print "Number of jobs:", len(jobs) # 3.) Perform jobs. if nProc < 2: # default behavior for non multiproc machines for job in jobs: if stopped(): return False groupImagesWorkerMAP(job) else: print 'using ', nProc, ' processes' it = [False] def imdone(x): it[0] = True print "I AM DONE NOW! WOW" pool.map_async(groupImagesWorkerMAP,jobs, callback=lambda x: imdone(it)) i = 0 while i < len(jobs): job_status, job_ballotid = queue_progress.get() # Blocks until value is ready if job_status == False: print "...Uhoh, ballotid={0} had a grouping failure.".format(job_ballotid) if wx.App.IsMainLoopRunning(): wx.CallAfter(Publisher().sendMessage, "signals.MyGauge.tick", (JOBID_GROUPING_IMGBASED,)) i += 1 while not it[0]: if stopped(): print ' UHOH, stopped' pool.terminate() return False time.sleep(.1) print "HERE" pool.close() pool.join() print "GOT HERE." # list RESULTS: [[int ballotid, attrtype, dict outdict], ...] results = [] cnt = 0 while cnt < len(jobs): res = queue.get() if type(res) in (str, unicode): print "OH NO, badness happened." else: results.append(res) cnt += 1 print 'cnt: ', cnt # TODO: quarantine on grouping errors. For now, just let alignment check handle it print 'ATTR: ', attrName, ': done' return results
import shared as sh import os import numpy as np from matplotlib.pyplot import show, imshow, figure, title # load patch ballotDir = '../../test-ballots/1side_Ntemplates/cedar2008primary_full/blank' I = sh.standardImread(os.path.join(ballotDir, '20120608170512502_0001.jpg'), flatten=True) bb = [770, 800, 355, 500] patch = I[bb[0]:bb[1], bb[2]:bb[3]] #imshow(patch); show() # generate image list imList = [] for root, dirs, files in os.walk(ballotDir): for f in files: (f0, ext) = os.path.splitext(f) if ext != '.jpg': continue p1 = os.path.join(root, f) imList.append(p1) #results = sh.find_patch_matches(patch,imList,region=bb) results = sh.find_patch_matchesV1(I, bb, imList) minOverlay = [] maxOverlay = [] for r1 in results: if len(minOverlay) == 0:
import imagesAlign as lk import shared as sh import os import numpy as np from matplotlib.pyplot import show, imshow, figure, title # load patch img_dir = '../../test-ballots/carlini/' Iref = sh.standardImread(os.path.join(img_dir, '0.tif'), flatten=True) M = np.zeros((Iref.shape[0], Iref.shape[1], 11)) for i in range(11): I = sh.standardImread(os.path.join(img_dir, str(i + 1) + '.tif'), flatten=True) Inorm = np.zeros(Iref.shape) # make patch the same size as Iref min0 = min(I.shape[0], Iref.shape[0]) min1 = min(I.shape[1], Iref.shape[1]) Inorm[0:min0, 0:min1] = I[0:min0, 0:min1] diff0 = Iref.shape[0] - I.shape[0] diff1 = Iref.shape[1] - I.shape[1] if diff0 > 0: Inorm[I.shape[0]:I.shape[0] + diff0, :] = 1 if diff1 > 0: Inorm[:, I.shape[1]:I.shape[1] + diff1] = 1
def process_one(args): try: imP, digit_hash, imList, bbSearch, nDigits, hspace, rejected_hashes, accepted_hashes, flipmap, queue_progress = args I1 = sh.standardImread(imP, flatten=True) if flipmap[imP]: I1 = sh.fastFlip(I1) # 0.) For Yolo (and perhaps other elections), upside-down voted # ballots were problematic. Recall that the ballot straightener # will pad the voted ballot with a black border if the B isn't # of the specified canonical size (W,H). Currently, the straightener # adds the padding to the bottom+right of the image. However, if the # voted ballot is upside down, then the padding is added to the # top+left (after undoing the flip), which results in a large shift # which our algorithms aren't able to gracefully handle. # ROWS, COLS is number of rows/cols removed from remove_border_topleft I1, rows, cols = sh.remove_border_topleft(I1) #I1=sh.prepOpenCV(I1) E_i1 = 0.10 # factor to expand bbSearch by E_i2 = 0.33 E_j1 = 0.05 E_j2 = 0.05 h, w = int(bbSearch[1] - bbSearch[0]), int(bbSearch[3] - bbSearch[2]) amt_i1 = int(round(E_i1 * h)) amt_i2 = int(round(E_i2 * h)) amt_j1 = int(round(E_j1 * w)) amt_j2 = int(round(E_j2 * w)) if (bbSearch[0] - amt_i1) < 0: amt_i1 = bbSearch[0] if (bbSearch[1] + amt_i2) > (I1.shape[0] - 1): amt_i2 = (I1.shape[0] - 1 - bbSearch[1]) if (bbSearch[2] - amt_j1) < 0: amt_j1 = bbSearch[2] if (bbSearch[3] + amt_j2) > (I1.shape[1] - 1): amt_j2 = (I1.shape[1] - 1 - bbSearch[3]) bb_patch = [ max(0, bbSearch[0] - amt_i1), min(I1.shape[0] - 1, bbSearch[1] + amt_i2), max(0, bbSearch[2] - amt_j1), min(I1.shape[1] - 1, bbSearch[3] + amt_j2) ] #I1=I1[bbSearch[0]:bbSearch[1],bbSearch[2]:bbSearch[3]] I1_patch = I1[bb_patch[0]:bb_patch[1], bb_patch[2]:bb_patch[3]] #if do_flip == False: # misc.imsave('_{0}_{1}_bb.png'.format(os.path.splitext(os.path.split(imP)[1])[0], # str(do_flip)), # I1) rejected_hash = rejected_hashes.get(imP, None) if rejected_hashes else None accepted_hash = accepted_hashes.get(imP, None) if accepted_hashes else None # perform matching for all digits # return best matching digit # mask out # res := (str ocr_str, list patches, list bbs, list scores, list matched_keys) res = pm2(digit_hash, I1_patch, nDigits, hspace, rejected_hash=rejected_hash, accepted_hash=accepted_hash) #res = pm1(digit_hash,I1,nDigits,hspace,rejected_hash=rejected_hash,accepted_hash=accepted_hash) # 1.) Remember to correct for E_i,E_j expansion factor from earlier, # the cropped-out black border (ROWS,COLS), and also to account # for bbSearch offset. newbbs = [] for bb in res[2]: newbb0 = (max(0, bb[0] + bb_patch[0] + rows), min(I1.shape[0] - 1, bb[1] + bb_patch[0] + rows), max(0, bb[2] + bb_patch[2] + cols), min(I1.shape[1] - 1, bb[3] + bb_patch[2] + cols)) newbbs.append(newbb0) queue_progress.put((True, None)) return (imP, res[0], res[1], newbbs, res[3]) except Exception as e: traceback.print_exc() queue_progress.put((False, (imP, e.message))) return False
import shared as sh import os import numpy as np from matplotlib.pyplot import show, imshow, figure, title # load patch ballotDir = '../../test-ballots/1side_Ntemplates/cedar2008primary_full/blank' I=sh.standardImread(os.path.join(ballotDir,'20120608170512502_0001.jpg'),flatten=True) bb=[320,400,500,950] patch = I[bb[0]:bb[1],bb[2]:bb[3]] #imshow(patch); show() # generate image list imList = [] for root, dirs, files in os.walk(ballotDir): for f in files: (f0,ext)=os.path.splitext(f) if ext != '.jpg': continue p1=os.path.join(root,f) imList.append(p1) #results = sh.find_patch_matches(patch,imList,region=bb) results = sh.find_patch_matchesV1(I,bb,imList,bbSearch=list(bb),rszFac=.5) minOverlay=[] maxOverlay=[] for r1 in results: if len(minOverlay)==0: minOverlay = r1[3] maxOverlay = r1[3]
def process_one(args): try: imP, digit_hash,imList,bbSearch,nDigits, hspace, rejected_hashes,accepted_hashes, flipmap, queue_progress = args I1 = sh.standardImread(imP,flatten=True) if flipmap[imP]: I1 = sh.fastFlip(I1) # 0.) For Yolo (and perhaps other elections), upside-down voted # ballots were problematic. Recall that the ballot straightener # will pad the voted ballot with a black border if the B isn't # of the specified canonical size (W,H). Currently, the straightener # adds the padding to the bottom+right of the image. However, if the # voted ballot is upside down, then the padding is added to the # top+left (after undoing the flip), which results in a large shift # which our algorithms aren't able to gracefully handle. # ROWS, COLS is number of rows/cols removed from remove_border_topleft I1, rows, cols = sh.remove_border_topleft(I1) #I1=sh.prepOpenCV(I1) E_i1 = 0.10 # factor to expand bbSearch by E_i2 = 0.33 E_j1 = 0.05 E_j2 = 0.05 h, w = int(bbSearch[1] - bbSearch[0]), int(bbSearch[3]-bbSearch[2]) amt_i1 = int(round(E_i1*h)) amt_i2 = int(round(E_i2*h)) amt_j1 = int(round(E_j1*w)) amt_j2 = int(round(E_j2*w)) if (bbSearch[0] - amt_i1) < 0: amt_i1 = bbSearch[0] if (bbSearch[1] + amt_i2) > (I1.shape[0]-1): amt_i2 = (I1.shape[0]-1 - bbSearch[1]) if (bbSearch[2] - amt_j1) < 0: amt_j1 = bbSearch[2] if (bbSearch[3] + amt_j2) > (I1.shape[1]-1): amt_j2 = (I1.shape[1]-1 - bbSearch[3]) bb_patch = [max(0, bbSearch[0]-amt_i1), min(I1.shape[0]-1, bbSearch[1]+amt_i2), max(0, bbSearch[2]-amt_j1), min(I1.shape[1]-1, bbSearch[3]+amt_j2)] #I1=I1[bbSearch[0]:bbSearch[1],bbSearch[2]:bbSearch[3]] I1_patch = I1[bb_patch[0]:bb_patch[1], bb_patch[2]:bb_patch[3]] #if do_flip == False: # misc.imsave('_{0}_{1}_bb.png'.format(os.path.splitext(os.path.split(imP)[1])[0], # str(do_flip)), # I1) rejected_hash = rejected_hashes.get(imP, None) if rejected_hashes else None accepted_hash = accepted_hashes.get(imP, None) if accepted_hashes else None # perform matching for all digits # return best matching digit # mask out # res := (str ocr_str, list patches, list bbs, list scores, list matched_keys) res = pm2(digit_hash,I1_patch,nDigits,hspace,rejected_hash=rejected_hash,accepted_hash=accepted_hash) #res = pm1(digit_hash,I1,nDigits,hspace,rejected_hash=rejected_hash,accepted_hash=accepted_hash) # 1.) Remember to correct for E_i,E_j expansion factor from earlier, # the cropped-out black border (ROWS,COLS), and also to account # for bbSearch offset. newbbs = [] for bb in res[2]: newbb0 = (max(0, bb[0]+bb_patch[0]+rows), min(I1.shape[0]-1, bb[1]+bb_patch[0]+rows), max(0, bb[2]+bb_patch[2]+cols), min(I1.shape[1]-1, bb[3]+bb_patch[2]+cols)) newbbs.append(newbb0) queue_progress.put((True, None)) return (imP,res[0],res[1],newbbs,res[3]) except Exception as e: traceback.print_exc() queue_progress.put((False, (imP, e.message))) return False
import sys from matplotlib.pyplot import show, imshow sys.path.append('../') import shared """ Script to show a case where find_patch_matchesV1 returns an Ireg with a lot of NaN's. """ patch = shared.standardImread('lang_en.png', flatten=True) img = shared.standardImread('bad_english_nans.png', flatten=True) h, w = patch.shape x1, y1 = 0, 0 x2, y2 = w - 1, h - 1 bb = [y1, y2, x1, x2] matches = shared.find_patch_matchesV1(patch, bb, ('bad_english_nans.png', ), threshold=0.6) (path, score1, score2, Ireg, y1, y2, x1, x2, rszFac) = matches[0] print "Ireg is:" print Ireg imshow(Ireg) show()
import shared as sh import part_match as pm import os import numpy as np from matplotlib.pyplot import show, imshow, figure, title ballotDir = '../../test-ballots/small_orange/339_100/' digitDir = '../../test-ballots/small_orange/digit-source/' # load all digit patches digit_hash = {} digit_hash["0"] = sh.standardImread(os.path.join(digitDir, '0.png'), flatten=True) digit_hash["1"] = sh.standardImread(os.path.join(digitDir, '1.png'), flatten=True) digit_hash["2"] = sh.standardImread(os.path.join(digitDir, '2.png'), flatten=True) digit_hash["3"] = sh.standardImread(os.path.join(digitDir, '3.png'), flatten=True) digit_hash["4"] = sh.standardImread(os.path.join(digitDir, '4.png'), flatten=True) digit_hash["5"] = sh.standardImread(os.path.join(digitDir, '5.png'), flatten=True) digit_hash["6"] = sh.standardImread(os.path.join(digitDir, '6.png'), flatten=True) digit_hash["7"] = sh.standardImread(os.path.join(digitDir, '7.png'), flatten=True) digit_hash["8"] = sh.standardImread(os.path.join(digitDir, '8.png'), flatten=True) digit_hash["9"] = sh.standardImread(os.path.join(digitDir, '9.png'), flatten=True)
import cProfile import cv2 from scipy import misc from shared import standardImread from imagesAlign import imagesAlign, pttransform import pdb import numpy as np import matplotlib.pyplot as plt import pstats # convert to double I = standardImread('lena_t.png') Iref = standardImread('lena.png') IO = imagesAlign(I, Iref) #p = pstats.Stats('profile_imagesalign1') #p.strip_dirs().sort_stats('cumulative').print_stats(25) viz = True if viz: H = IO[0] # figure(0) # imshow(np.abs(Iref-I),cmap='gray'); plt.figure(1) plt.imshow(np.abs(Iref - IO[1]), cmap='gray') pt0 = np.array([155, 65, 1]) plt.figure(2) plt.imshow(I, cmap='gray')
import imagesAlign as lk import shared as sh import os import numpy as np from matplotlib.pyplot import show, imshow, figure, title # load patch img_dir = '../../test-ballots/carlini/' Iref=sh.standardImread(os.path.join(img_dir,'0.tif'),flatten=True) M = np.zeros((Iref.shape[0],Iref.shape[1], 11)) for i in range(11): I=sh.standardImread(os.path.join(img_dir,str(i+1)+'.tif'),flatten=True) Inorm = np.zeros(Iref.shape) # make patch the same size as Iref min0 = min(I.shape[0],Iref.shape[0]) min1 = min(I.shape[1],Iref.shape[1]) Inorm[0:min0,0:min1] = I[0:min0,0:min1] diff0 = Iref.shape[0] - I.shape[0] diff1 = Iref.shape[1] - I.shape[1] if diff0 > 0: Inorm[I.shape[0]:I.shape[0]+diff0,:] = 1 if diff1 > 0: Inorm[:,I.shape[1]:I.shape[1]+diff1] = 1 res=lk.imagesAlign(Inorm,Iref) M[:,:,i] = res[1]