Chris 7 роки тому
джерело
коміт
0aab1ce111
1 змінених файлів з 333 додано та 0 видалено
  1. +333
    -0
      pageCropAnnotator.py

+ 333
- 0
pageCropAnnotator.py Переглянути файл

@@ -0,0 +1,333 @@
#!/usr/bin/python

#This takes a list of image files and acts as a tool to mark the crop region of the page

import re
import xml.etree.ElementTree as ET
import os
import sys
from StringIO import StringIO
import cv2



def showControls():
print(' -----------------------------------------------')
print('| CONTROLS: |')
print('| * set new corner (base on loc): left-click |')
print('| * set new seam corner (two-page): middle-click|')
print('| * confirm corners: enter |')
print('| * mark page as abnormal: a |')
print('| * undo: backspace |')
print('| * start previous page over: backspace(+)|')
#print('| * start current page over: delete |')
print('| * exit: esc |')
print('| |')
print(' -----------------------------------------------')



lastDidList=[]
tl=(-1,-1)
tr=(-1,-1)
bl=(-1,-1)
br=(-1,-1)
tm=(-1,-1)
bm=(-1,-1)

image=None
orig=None

abnorm=False

def draw():
global image,tl,tr,bl,br,tm,bm,abnorm
if tm[0]>=0 and bm[0]>=0:
cv2.line(image, tm, bm, (0,255,0), 2)
if tm[0]>=0 and tl[0]>=0:
cv2.line(image, tm, tl, (0,255,0), 2)
if tm[0]>=0 and tr[0]>=0:
cv2.line(image, tm, tr, (0,255,0), 2)
if bm[0]>=0 and bl[0]>=0:
cv2.line(image, bm, bl, (0,255,0), 2)
if bm[0]>=0 and br[0]>=0:
cv2.line(image, bm, br, (0,255,0), 2)
if tl[0]>=0 and tr[0]>=0:
cv2.line(image, tl, tr, (255,0,0), 2)
if br[0]>=0 and tr[0]>=0:
cv2.line(image, br, tr, (255,0,0), 2)
if br[0]>=0 and bl[0]>=0:
cv2.line(image, br, bl, (255,0,0), 2)
if tl[0]>=0 and bl[0]>=0:
cv2.line(image, tl, bl, (255,0,0), 2)


if tl[0]>=0:
image[tl[1],tl[0]]=(0,0,255)
cv2.circle(image, tl, 2, (0,0,200), 1)
cv2.circle(image, tl, 5, (0,0,200), 2)
if tr[0]>=0:
image[tr[1],tr[0]]=(0,0,255)
cv2.circle(image, tr, 2, (0,0,200), 1)
cv2.circle(image, tr, 5, (0,0,200), 2)
if bl[0]>=0:
image[bl[1],bl[0]]=(0,0,255)
cv2.circle(image, bl, 2, (0,0,200), 1)
cv2.circle(image, bl, 5, (0,0,200), 2)
if br[0]>=0:
image[br[1],br[0]]=(0,0,255)
cv2.circle(image, br, 2, (0,0,200), 1)
cv2.circle(image, br, 5, (0,0,200), 2)
if tm[0]>=0:
image[tm[1],tm[0]]=(0,0,255)
cv2.circle(image, tm, 2, (0,100,200), 1)
cv2.circle(image, tm, 5, (0,100,200), 2)
if bm[0]>=0:
image[bm[1],bm[0]]=(0,0,255)
cv2.circle(image, bm, 2, (0,100,200), 1)
cv2.circle(image, bm, 5, (0,100,200), 2)

if abnorm:
cv2.putText(image, 'ABNORMAL', (image.shape[1]/2,image.shape[0]/2), cv2.FONT_HERSHEY_PLAIN, 2, (0,0,255))


cv2.imshow("image", image)

bimage=None
def clicker(event, x, y, flags, param):
# grab references to the global variables
global image,tl,tr,bl,br,tm,bm,lastDidList,orig

"""if event == cv2.EVENT_LBUTTONDOWN:
if len(segPts)>0:
#change last boundary
image=bimage.copy()
segPts[-1]=x
ll=max(0,segPts[-1]-1)
rr=min(image.shape[1], segPts[-1]+1)
image[:,ll:rr,0] = color[(colorIdx+len(color)-1)%len(color)][0] * image[:,ll:rr,0]
image[:,ll:rr,1] = color[(colorIdx+len(color)-1)%len(color)][1] * image[:,ll:rr,1]
image[:,ll:rr,2] = color[(colorIdx+len(color)-1)%len(color)][2] * image[:,ll:rr,2]
cv2.imshow("image", image)
"""
if event == cv2.EVENT_LBUTTONDOWN:
# a new boundary
if x<image.shape[1]/2 and y<image.shape[0]/2:
tl=(x,y)
if 0 in lastDidList:
image=orig.copy()
lastDidList.remove(0)
lastDidList.append(0)
if x>image.shape[1]/2 and y<image.shape[0]/2:
tr=(x,y)
if 1 in lastDidList:
image=orig.copy()
lastDidList.remove(1)
lastDidList.append(1)
if x<image.shape[1]/2 and y>image.shape[0]/2:
bl=(x,y)
if 2 in lastDidList:
image=orig.copy()
lastDidList.remove(2)
lastDidList.append(2)
if x>image.shape[1]/2 and y>image.shape[0]/2:
br=(x,y)
if 3 in lastDidList:
image=orig.copy()
lastDidList.remove(3)
lastDidList.append(3)
draw()

elif event == cv2.EVENT_MBUTTONDOWN:
# a new boundary
if y<image.shape[0]/2:
tm=(x,y)
if 1 in lastDidList:
image=orig.copy()
lastDidList.remove(1)
lastDidList.append(4)
if y>image.shape[0]/2:
bm=(x,y)
if 3 in lastDidList:
image=orig.copy()
lastDidList.remove(3)
lastDidList.append(5)
draw()

def segmenter(imDir,imagePath,dispHeight):
global image,tl,tr,bl,br,tm,bm,lastDidList,orig,abnorm
print 'opening '+imDir+imagePath
orig = cv2.imread(imDir+imagePath)
scale = orig.shape[0]/dispHeight
orig = cv2.resize(orig,(0,0),None,1.0/scale,1.0/scale)
#print 'opened'
assert orig is not None
redo=True
while redo: #undo loop
abnorm=False
lastDidList=[]
tl=(-1,-1)
tr=(-1,-1)
bl=(-1,-1)
br=(-1,-1)
tm=(-1,-1)
bm=(-1,-1)
redo=False
image = orig.copy()
draw()
while True:
# display the imageWork and wait for a keypress
key = cv2.waitKey(33) & 0xFF #so it is robust on all systems
#print key
if key == 13 and tl[0]>=0 and tr[0]>=0 and bl[0]>=0 and br[0]>=0: #enter
toWrite = imagePath+','+str(int(scale*tl[0]))+','+str(int(scale*tl[1]))+','+str(int(scale*tr[0]))+','+str(int(scale*tr[1]))+','+str(int(scale*br[0]))+','+str(int(scale*br[1]))+','+str(int(scale*bl[0]))+','+str(int(scale*bl[1]))
if abnorm:
if tm[0]>=0 and bm[0]>=0:
toWrite += ',ABNORMAL,'+str(int(scale*tm[0]))+','+str(int(scale*tm[1]))+','+str(int(scale*bm[0]))+','+str(int(scale*bm[1]))
else:
toWrite += ',ABNORMAL'
else:
if tm[0]>=0 and bm[0]>=0:
toWrite += ',DOUBLE,'+str(int(scale*tm[0]))+','+str(int(scale*tm[1]))+','+str(int(scale*bm[0]))+','+str(int(scale*bm[1]))
else:
toWrite += ',SINGLE'
toWrite+='\n';
return toWrite, False, False
elif key == 8: #backspace
if len(lastDidList)>0:
imageWork = orig.copy()
lastDid=lastDidList.pop()
if lastDid==0:
tl=(-1,-1)
elif lastDid==1:
tr=(-1,-1)
elif lastDid==2:
bl=(-1,-1)
elif lastDid==3:
br=(-1,-1)
elif lastDid==4:
tm=(-1,-1)
elif lastDid==5:
bm=(-1,-1)
image=orig.copy()
draw()
else:
return '', True, False
elif key == 127: #del
#if len(lastDidList)>0:
print('[CLEAR]')
redo=True
break
#else:
# return '', True, False
elif key == 27: #esc
print('esc')
return '', False, True
#exit(0)
#break
elif key == 97: #'a'
#return imagePath+',-1,-1,-1,-1,-1,-1,-1,-1,ABNORMAL\n', False, False
abnorm = not abnorm
image=orig.copy()
draw()

#return newWords, newWordBoxes

if len(sys.argv)<4:
print 'usage: '+sys.argv[0]+' imgDir imgList outAnn.csv [displayHeight]'
print 'output format: imageFile, tlx, tly, trx, try, brx, bry, blx, bly, type (,tmx, tmy, bmx, bmy)'
exit(0)

inFile = sys.argv[2]
imDir = sys.argv[1]
if imDir[-1]!='/':
imDir+='/'
outFile = sys.argv[3]
dispHeight=500.0
if len(sys.argv)>4:
dispHeight=float(sys.argv[4])

cv2.namedWindow("image")
cv2.setMouseCallback("image", clicker)

didCount=0
did=[]
try:
check = open(outFile,'r')
did = check.read().splitlines()
didCount=len(did)
check.close()
print 'found '+outFile+', appending. Note: this is sychronizing based on count alone, if '+inFile+' hash changed, but sure to align '+outFile
except IOError:
print ('making new out:'+outFile)

out = open(outFile,'w')

print ' =============================================== '
print ' !!! INSTRUCTIONS !!!'
print ' If the page does not contain a single page, or '
print ' an open book, mark as abnormal with INSERT (e.g.'
print ' two seperate pages).'
print ' Click on the four corners to include all the '
print ' full pages in the image (including two pages if '
print ' fully present).'
print ' If two pages a full present also mark page seam '
print ' (middle-click).'
print ' On placing points, prioritize the following to '
print ' be included/discluded from the polygons in the '
print ' following order:'
print ' 1. Including the present page(s) content.'
print ' 2. Discluding other pages and background.'
print ' 3. Discluding the present page(s) boudary.'
print ' 4. Including the present page(s) white area.'
#print ' book). If a corner is torn, click where it ought'
#print ' to be, based on page edges. The page seem on an '
#print ' open book is the page edge.'
print ' Use ESC to exit or the latest page you finished '
print ' will be lost.'

#i=didCount
i=0
#pageCount=-1
prevSeg=''
seg=''
showControls()
inF = open(inFile,'r')
images = inF.read().splitlines()
end=False
doneOne=False
while i<len(images) and not end:
if i%10==9:
showControls()
print(str(i+1)+' of '+str(len(images)))

if len(did)>i:
line = did[i].strip().split(',')
typ = line[8]
#print typ
if typ != '-1':
out.write(did[i].strip()+'\n')
i+=1
continue
seg, undo, end = segmenter(imDir, images[i],dispHeight)
out.write(seg)
seg=''
i+=1
else:


seg, undo, end = segmenter(imDir, images[i],dispHeight)
if len(seg)>0:
doneOne=True
if undo and i>0 and doneOne:
prevSeg=''
print(str(i)+' of '+str(len(images)))
prevSeg, undo, end = segmenter(imDir, images[i-1],dispHeight)
else:
out.write(prevSeg)
prevSeg=seg
seg=''
i+=1
out.write(prevSeg)
out.write(seg)

Завантаження…
Відмінити
Зберегти