transform image
This commit is contained in:
@@ -30,6 +30,26 @@ import pylab as plt #used for the colormaps
|
|||||||
#The source of the DraggableColorbar is from:
|
#The source of the DraggableColorbar is from:
|
||||||
#http://www.ster.kuleuven.be/~pieterd/python/html/plotting/interactive_colorbar.html
|
#http://www.ster.kuleuven.be/~pieterd/python/html/plotting/interactive_colorbar.html
|
||||||
|
|
||||||
|
class MouseData: #data structure for mouse events on image
|
||||||
|
usageStr='unknown mode. available m:move t: transform'
|
||||||
|
def __init__(self):
|
||||||
|
self.mode=None
|
||||||
|
|
||||||
|
def addTrfPt(self,p1):
|
||||||
|
try:
|
||||||
|
p0=self.btnPress
|
||||||
|
del self.btnPress
|
||||||
|
except AttributeError: return
|
||||||
|
try:
|
||||||
|
trf=self.trfPts
|
||||||
|
except AttributeError:
|
||||||
|
trf=self.trfPts=[]
|
||||||
|
|
||||||
|
p=p0+p1
|
||||||
|
print('add trf: {}'.format(p))
|
||||||
|
trf.append(p)
|
||||||
|
|
||||||
|
|
||||||
class MPLCanvasImg(FigureCanvas):
|
class MPLCanvasImg(FigureCanvas):
|
||||||
def __init__(self,parent,SetStatusCB=None):
|
def __init__(self,parent,SetStatusCB=None):
|
||||||
if SetStatusCB:
|
if SetStatusCB:
|
||||||
@@ -44,12 +64,12 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
self.mpl_connect('scroll_event', self.OnBtnScroll)
|
self.mpl_connect('scroll_event', self.OnBtnScroll)
|
||||||
self.mpl_connect('key_press_event',self.OnKeyPress)
|
self.mpl_connect('key_press_event',self.OnKeyPress)
|
||||||
#self.mpl_connect('pick_event',self.OnPick) #works but locks the screed if debugging
|
#self.mpl_connect('pick_event',self.OnPick) #works but locks the screed if debugging
|
||||||
self.fig=fig
|
|
||||||
self.ax=ax
|
self.ax=ax
|
||||||
|
self.mouseData=MouseData()
|
||||||
|
|
||||||
def InitChild(self,doc):
|
def InitChild(self,doc):
|
||||||
|
|
||||||
fig=self.fig
|
fig=self.figure
|
||||||
ax=self.ax
|
ax=self.ax
|
||||||
pts=doc.fh['pts']
|
pts=doc.fh['pts']
|
||||||
rec=doc.fh['rec']
|
rec=doc.fh['rec']
|
||||||
@@ -80,6 +100,33 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
hl+=ax.plot(rec[idxTrigger,1],rec[idxTrigger,0],'rx',label='trig',markeredgewidth=1.,markersize=6.)
|
hl+=ax.plot(rec[idxTrigger,1],rec[idxTrigger,0],'rx',label='trig',markeredgewidth=1.,markersize=6.)
|
||||||
|
|
||||||
#hl+=ax.plot(recPts[:,1],recPts[:,0],'g.',label='recDot')
|
#hl+=ax.plot(recPts[:,1],recPts[:,0],'g.',label='recDot')
|
||||||
|
fn=doc.fh.fid.name[:-4]+'.jpg'
|
||||||
|
try:
|
||||||
|
img=mpl.image.imread(fn)
|
||||||
|
try:
|
||||||
|
self.imgTrf=trf=doc.fh['imgTrf']
|
||||||
|
except KeyError:
|
||||||
|
mn=pts.min(0)
|
||||||
|
mx=pts.max(0)
|
||||||
|
ext=(mn[0], mx[0], mn[1], mx[1])
|
||||||
|
skew=None
|
||||||
|
else:
|
||||||
|
xmin=trf[0, 2]
|
||||||
|
ymin=trf[1, 2]
|
||||||
|
xmax=trf[0, :].sum()
|
||||||
|
ymax=trf[1, :].sum()
|
||||||
|
xskew=trf[0, 2]+trf[0, 0]
|
||||||
|
yskew=trf[1, 2]+trf[1, 0]
|
||||||
|
ext=(xmin, xmax, ymin, ymax)
|
||||||
|
skew=(xskew, yskew)
|
||||||
|
|
||||||
|
#interpolation must be none to allow skew image
|
||||||
|
himg=ax.imshow(img,extent=ext,interpolation='none')
|
||||||
|
himg._image_skew_coordinate=skew
|
||||||
|
|
||||||
|
pass
|
||||||
|
except IOError as e:
|
||||||
|
print(e)
|
||||||
ax.xaxis.set_label_text('x-pos um')
|
ax.xaxis.set_label_text('x-pos um')
|
||||||
ax.yaxis.set_label_text('y-pos um')
|
ax.yaxis.set_label_text('y-pos um')
|
||||||
ax.axis('equal')
|
ax.axis('equal')
|
||||||
@@ -99,8 +146,26 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
|
|
||||||
def OnMotion(self,event):
|
def OnMotion(self,event):
|
||||||
#print event,event.x,event.y,event.inaxes,event.xdata,event.ydata
|
#print event,event.x,event.y,event.inaxes,event.xdata,event.ydata
|
||||||
|
|
||||||
if event.inaxes==self.ax:
|
if event.inaxes==self.ax:
|
||||||
|
md=self.mouseData
|
||||||
|
if md.mode==2 and event.button==1 and self.toolbar.mode=='': # move
|
||||||
|
try:
|
||||||
|
himg=self.ax.get_images()[0]
|
||||||
|
except IndexError:
|
||||||
|
print('no image to transform')
|
||||||
|
return
|
||||||
|
trf=self.imgTrf
|
||||||
|
xOfs=event.xdata-md.btnPress[0]
|
||||||
|
yOfs=event.ydata-md.btnPress[1]
|
||||||
|
xmin=trf[0, 2]+xOfs
|
||||||
|
ymin=trf[1, 2]+yOfs
|
||||||
|
xmax=trf[0, :].sum()+xOfs
|
||||||
|
ymax=trf[1, :].sum()+yOfs
|
||||||
|
xskew=trf[0, 2]+trf[0, 0]+xOfs
|
||||||
|
yskew=trf[1, 2]+trf[1, 0]+yOfs
|
||||||
|
himg.set_extent((xmin, xmax, ymin, ymax))
|
||||||
|
himg._image_skew_coordinate=(xskew, yskew)
|
||||||
|
self.figure.canvas.draw()
|
||||||
|
|
||||||
x=int(round(event.xdata))
|
x=int(round(event.xdata))
|
||||||
y=int(round(event.ydata))
|
y=int(round(event.ydata))
|
||||||
@@ -108,8 +173,8 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
for h in self.ax.get_lines(): # to get also the ellipses: self.ax.get_children()
|
for h in self.ax.get_lines(): # to get also the ellipses: self.ax.get_children()
|
||||||
c=h.contains(event)
|
c=h.contains(event)
|
||||||
if c[0]:
|
if c[0]:
|
||||||
#s = str(h)+str(c[1])
|
s = str(h)+str(c[1])
|
||||||
#print "over %s" % s
|
#print("over %s" % s)
|
||||||
if type(h)==mpl.lines.Line2D:
|
if type(h)==mpl.lines.Line2D:
|
||||||
lbl=h.get_label()
|
lbl=h.get_label()
|
||||||
arr=h.get_data()
|
arr=h.get_data()
|
||||||
@@ -117,9 +182,7 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
s += '%s[%d] = [%.2f, %.2f]'%(lbl,idx,arr[0][idx],arr[1][idx])
|
s += '%s[%d] = [%.2f, %.2f]'%(lbl,idx,arr[0][idx],arr[1][idx])
|
||||||
else:
|
else:
|
||||||
s += str(h)+str(c[1])
|
s += str(h)+str(c[1])
|
||||||
|
|
||||||
self.SetStatusCB(self.Parent, 0, (x, y, s))
|
self.SetStatusCB(self.Parent, 0, (x, y, s))
|
||||||
|
|
||||||
#try:
|
#try:
|
||||||
# #v=self.img.get_array()[y,x]
|
# #v=self.img.get_array()[y,x]
|
||||||
# v=0;
|
# v=0;
|
||||||
@@ -142,14 +205,32 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
|
|
||||||
def OnBtnPress(self, event):
|
def OnBtnPress(self, event):
|
||||||
"""on button press we will see if the mouse is over us and store some data"""
|
"""on button press we will see if the mouse is over us and store some data"""
|
||||||
#print(dir(event.guiEvent))
|
if self.toolbar.mode!='':
|
||||||
return
|
print(self.toolbar.mode)
|
||||||
if event.inaxes == self.colBar.ax:
|
return
|
||||||
|
if event.inaxes==self.ax:
|
||||||
|
md=self.mouseData
|
||||||
|
md.mode
|
||||||
|
if md.mode==1:#transform
|
||||||
|
if event.guiEvent.RightDown()==True:
|
||||||
|
self.doTransform()
|
||||||
|
if event.guiEvent.LeftDown()==True:
|
||||||
|
p=(event.xdata,event.ydata)
|
||||||
|
md.btnPress=p
|
||||||
|
elif md.mode==2:#move
|
||||||
|
if event.guiEvent.LeftDown()==True:
|
||||||
|
p=(event.xdata,event.ydata)
|
||||||
|
md.btnPress=p
|
||||||
|
else:
|
||||||
|
print(md.usageStr)
|
||||||
|
|
||||||
|
#print('self.btnPress1', p)
|
||||||
|
#if event.inaxes == self.colBar.ax:
|
||||||
#if event.guiEvent.LeftDClick()==True:
|
#if event.guiEvent.LeftDClick()==True:
|
||||||
# print dlg
|
# print dlg
|
||||||
pt=self.colBar.ax.bbox.get_points()[:,1]
|
#pt=self.colBar.ax.bbox.get_points()[:,1]
|
||||||
nrm=self.colBar.norm
|
#nrm=self.colBar.norm
|
||||||
self.colBarPressed = (nrm.vmin,nrm.vmax,pt[0],pt[1],event.y)
|
#self.colBarPressed = (nrm.vmin,nrm.vmax,pt[0],pt[1],event.y)
|
||||||
#self.colBarPressed = event.x, event.y
|
#self.colBarPressed = event.x, event.y
|
||||||
#print self.colBarPressed
|
#print self.colBarPressed
|
||||||
#self.OnMouse(event)
|
#self.OnMouse(event)
|
||||||
@@ -157,10 +238,19 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
|
|
||||||
def OnBtnRelease(self, event):
|
def OnBtnRelease(self, event):
|
||||||
"""on release we reset the press data"""
|
"""on release we reset the press data"""
|
||||||
#self.OnMouse(event)
|
print('OnBtnRelease')
|
||||||
|
md=self.mouseData
|
||||||
|
if md.mode==1: #transform
|
||||||
|
p1=(event.xdata, event.ydata)
|
||||||
|
md.addTrfPt(p1)
|
||||||
|
elif md.mode==2:#move
|
||||||
|
trf=self.imgTrf
|
||||||
|
xOfs=event.xdata-md.btnPress[0]
|
||||||
|
yOfs=event.ydata-md.btnPress[1]
|
||||||
|
#trf[0,2]+=xOfs
|
||||||
|
#trf[1,2]+=yOfs
|
||||||
|
#trf[1,2]+=yOfs
|
||||||
return
|
return
|
||||||
try: del self.colBarPressed
|
|
||||||
except AttributeError: pass
|
|
||||||
|
|
||||||
def OnBtnScroll(self, event):
|
def OnBtnScroll(self, event):
|
||||||
return
|
return
|
||||||
@@ -183,20 +273,27 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
colBar.patch.figure.canvas.draw()
|
colBar.patch.figure.canvas.draw()
|
||||||
|
|
||||||
def OnKeyPress(self, event):
|
def OnKeyPress(self, event):
|
||||||
|
#self.trfPts=[(-1831.2063808574276, 1349.6011964107677, -1966.6001994017945, 1433.3499501495512), (-1830.4810087443084, 917.64916303133487, -1958.3629895701151, 870.93212944552363), (-1561.5041487047886, 917.17727380319548, -1445.8912878106089, 873.29157558622114)]
|
||||||
|
#self.trfPts=[(-1960., 872., -1960., 872.), (-1450., 872, -1450., 872), (-1960., 1432.,-1960., 1432.)]
|
||||||
|
#self.trfPts=[(-1960., 872., -1760., 872.), (-1450., 872, -1250., 872), (-1960., 1432.,-1760., 1432.)]
|
||||||
|
#self.doTransform()
|
||||||
|
md=self.mouseData
|
||||||
|
if event.key=='t':
|
||||||
|
md.mode=1;print('transform image mode (drag drop to add point, right mopuse to execute)')
|
||||||
|
elif event.key=='x':
|
||||||
|
self.doTransform()
|
||||||
|
elif event.key=='m':
|
||||||
|
md.mode=2;print('move image mode')
|
||||||
|
elif event.key=='s':
|
||||||
|
self.saveTransform()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
print('unknown mode. available m:move t: transform')
|
||||||
|
md.mode=None
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
return
|
return
|
||||||
colCycle=self.colCycle
|
|
||||||
colBar=self.colBar
|
|
||||||
if event.key=='down':
|
|
||||||
self.colIndex += 1
|
|
||||||
elif event.key=='up':
|
|
||||||
self.colIndex -= 1
|
|
||||||
self.colIndex%=len(colCycle)
|
|
||||||
cmap = colCycle[self.colIndex]
|
|
||||||
colBar.set_cmap(cmap)
|
|
||||||
colBar.draw_all()
|
|
||||||
self.img.set_cmap(cmap)
|
|
||||||
self.img.get_axes().set_title(cmap)
|
|
||||||
colBar.patch.figure.canvas.draw()
|
|
||||||
|
|
||||||
def OnMouse(self, event):
|
def OnMouse(self, event):
|
||||||
return
|
return
|
||||||
@@ -204,6 +301,84 @@ class MPLCanvasImg(FigureCanvas):
|
|||||||
if k[0]!='_':
|
if k[0]!='_':
|
||||||
print(k,getattr(event,k))
|
print(k,getattr(event,k))
|
||||||
|
|
||||||
|
def doTransform(self):
|
||||||
|
#print('doTransform')
|
||||||
|
try:
|
||||||
|
trfPts=self.mouseData.trfPts
|
||||||
|
del self.mouseData.trfPts
|
||||||
|
except AttributeError:
|
||||||
|
print('no transformation points')
|
||||||
|
return
|
||||||
|
print(trfPts)
|
||||||
|
trfPts=np.array(trfPts)
|
||||||
|
|
||||||
|
try:
|
||||||
|
himg=self.ax.get_images()[0]
|
||||||
|
except IndexError:
|
||||||
|
print('no image to transform')
|
||||||
|
return
|
||||||
|
xmin,xmax,ymin,ymax=himg.get_extent()
|
||||||
|
#himg.set_extent((xmin,xmax+10,ymin,ymax))
|
||||||
|
skew=himg._image_skew_coordinate
|
||||||
|
if skew is None:
|
||||||
|
xskew=xmax
|
||||||
|
yskew=ymin
|
||||||
|
else:
|
||||||
|
(xskew, yskew)=skew
|
||||||
|
|
||||||
|
trf0=np.array([[xskew-xmin,xmax-xskew,xmin],
|
||||||
|
[yskew-ymin,ymax-yskew,ymin],
|
||||||
|
[0,0,1]])
|
||||||
|
|
||||||
|
|
||||||
|
#calculate least square transformation matrix of the transformation points
|
||||||
|
n=trfPts.shape[0]
|
||||||
|
if n<3:
|
||||||
|
print('tot enough points (needs at least 3)')
|
||||||
|
return
|
||||||
|
|
||||||
|
M=np.mat(trf0).I
|
||||||
|
trfPtsImgI=M*np.vstack((trfPts[:,(0,1)].T,np.ones((1,n))))
|
||||||
|
trfPtsImgO=M*np.vstack((trfPts[:,(02,3)].T,np.ones((1,n))))
|
||||||
|
trfPtsImg=np.hstack((trfPtsImgI[0:2,:].T,trfPtsImgO[0:2,:].T))
|
||||||
|
|
||||||
|
A=np.zeros((n*2, 6))
|
||||||
|
A[0:n, (0, 1)]=trfPtsImg[:,(0,1)]
|
||||||
|
A[0:n, 2]=1
|
||||||
|
A[n:n*2, (3, 4)]=trfPtsImg[:,(0,1)]
|
||||||
|
A[n:n*2, 5]=1
|
||||||
|
A=np.mat(A)
|
||||||
|
B=trfPtsImg[:,(2,3)].T.reshape(-1, 1)
|
||||||
|
|
||||||
|
# (A'*A)^-1*A'*B
|
||||||
|
r=(A.T*A).I*A.T*B
|
||||||
|
trf1=np.hstack((r.T, [[0, 0, 1]])).reshape(3, -1)
|
||||||
|
|
||||||
|
trf=np.mat(trf0)*trf1
|
||||||
|
xmin=trf[0, 2]
|
||||||
|
ymin=trf[1, 2]
|
||||||
|
xmax=trf[0, :].sum()
|
||||||
|
ymax=trf[1, :].sum()
|
||||||
|
xskew=trf[0, 2]+trf[0, 0]
|
||||||
|
yskew=trf[1, 2]+trf[1, 0]
|
||||||
|
self.imgTrf=trf
|
||||||
|
print(trf)
|
||||||
|
himg.set_extent((xmin,xmax,ymin,ymax))
|
||||||
|
himg._image_skew_coordinate=(xskew, yskew)
|
||||||
|
self.figure.canvas.draw()
|
||||||
|
|
||||||
|
def saveTransform(self):
|
||||||
|
fhr=self.Parent.doc.fh
|
||||||
|
fn_npz=fhr.fid.name
|
||||||
|
fn_npzOrig=fn_npz+'.orig'
|
||||||
|
d=dict(fhr.items())
|
||||||
|
fhr.close()
|
||||||
|
if not os.path.exists(fn_npzOrig):
|
||||||
|
os.rename(fn_npz, fn_npzOrig)
|
||||||
|
d['imgTrf']=self.imgTrf
|
||||||
|
np.savez_compressed(fn_npz,**d)
|
||||||
|
self.Parent.doc.fh=np.load(fn_npz)
|
||||||
|
|
||||||
class MAxyPlotFrame(wx.Frame):
|
class MAxyPlotFrame(wx.Frame):
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.doc.view.remove(self)
|
self.doc.view.remove(self)
|
||||||
|
|||||||
@@ -374,10 +374,10 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
f1 = MAxyPlotFrame(frame, doc)
|
f1 = MAxyPlotFrame(frame, doc)
|
||||||
f1.Show(True)
|
f1.Show(True)
|
||||||
f2= MAErrorFrame(frame, doc)
|
#f2= MAErrorFrame(frame, doc)
|
||||||
f2.Show(True)
|
#f2.Show(True)
|
||||||
f3= MAVelocityFrame(frame, doc)
|
#f3= MAVelocityFrame(frame, doc)
|
||||||
f3.Show(True)
|
#f3.Show(True)
|
||||||
|
|
||||||
self.SetTopWindow(frame)
|
self.SetTopWindow(frame)
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user