rework graphic opbect and coordinate transformation

This commit is contained in:
2022-09-06 10:07:11 +02:00
parent d263c09028
commit cbae02c597
4 changed files with 121 additions and 77 deletions

View File

@@ -42,6 +42,7 @@ class AppCfg(QSettings):
GEO_BEAM_POS="geometry/beam_pos"
GEO_CAM_PARAM="geometry/cam_param"
GEO_CAM_TRF="geometry/cam_trf"
WINDOW_GEOMETRY="window/geometry"
WINDOW_SPLITTER="window/splitter"
@@ -129,6 +130,11 @@ class AppCfg(QSettings):
opt_ctr=np.array([603.28688025, 520.01112846])
self.setValue(AppCfg.GEO_OPT_CTR, opt_ctr)
if AppCfg.GEO_CAM_TRF not in keys:
_log.warning(f'{AppCfg.GEO_CAM_TRF} not defined. use default')
trf=np.array(((-1,0,0),(0,-1,0),(0,0,1)))
self.setValue(AppCfg.GEO_CAM_TRF, trf)
if AppCfg.DT_HOST not in keys:
_log.warning(f'{AppCfg.DT_HOST} not defined. use default')
self.setValue(AppCfg.DT_HOST,'SAR-CPPM-EXPMX1')
@@ -155,12 +161,12 @@ class AppCfg(QSettings):
def setValue(self, key: str, val): #overload to debug
# only simple lists, str, int, float can not be serialized nicely
t=type(val)
if key in (AppCfg.GEO_PIX2POS,):
if key in (AppCfg.GEO_PIX2POS,AppCfg.GEO_CAM_TRF):
val=json.dumps(val, cls=MyJsonEncoder)
elif key in (AppCfg.GEO_CAM_PARAM,AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT,):
val=json.dumps(val, cls=MyJsonEncoder)
val=val.replace('"',"'")
elif key in (AppCfg.GEO_OPT_CTR,AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS,):
elif key in (AppCfg.GEO_OPT_CTR,AppCfg.GEO_BEAM_SZ,AppCfg.GEO_BEAM_POS):
if type(val)==np.ndarray:
val=val.tolist()
elif type(val)==tuple:
@@ -172,6 +178,9 @@ class AppCfg(QSettings):
if key in (AppCfg.GEO_PIX2POS,):
val=json.loads(val)#, object_hook=MyJsonDecoder)
val=(np.array(val[0]),np.array(val[1]))
elif key in (AppCfg.GEO_CAM_TRF,):
val=json.loads(val)#, object_hook=MyJsonDecoder)
val=np.array(val)
elif key in (AppCfg.GEO_CAM_PARAM,AppCfg.DFT_POS_DET,AppCfg.DFT_POS_PST,AppCfg.DFT_POS_COL,AppCfg.DFT_POS_BKLGT,):
if val is not None:
val=val.replace("'",'"')
@@ -275,6 +284,11 @@ class WndParameter(QMainWindow):
{'name':AppCfg.DT_SHOW_PLOTS,'title':'show plots after collection' ,'value':dt_show_plots,'type':'bool' ,'tip':"This is a checkbox"},
{'name':AppCfg.DT_VEL_SCL ,'title':'velocity_scale' ,'value':dt_vel_scl ,'type':'float','limits':(0,1),'step':0.1,'tip':"This is a checkbox"},
]},
{'name':'Misc', 'type':'group', 'children':[
{'name':AppCfg.GEO_CAM_TRF, 'value':cfg.value(AppCfg.GEO_CAM_TRF), 'type':'str'},
]},
{'name':'Save/Restore functionality', 'type':'group', 'children':[
{'name':'Save State', 'type':'action'},
{'name':'Restore State', 'type':'action', 'children':[

View File

@@ -219,7 +219,6 @@ class geometry:
return
AA=np.ndarray((len(meas), 2, 2), np.float)
K=np.array(tuple(meas.keys()), np.float)
self._lut_pix2pos=(K, AA)
for i, (k, v) in enumerate(meas.items()):
m=np.array(v) # measurements
if m.shape[0]<3:
@@ -238,6 +237,14 @@ class geometry:
AA[i]=aa.reshape(2, -1)
# bx_coefs = np.polyfit(nbx[0], nbx[1], 3)
# np.poly1d(bx_coefs)
if np.diff(K).min()<0: #zoom need to be from lowest to highest ordered
_log.debug('resorting')
s=K.argsort()
K=K[s]
AA=AA[s] #resort A if needed
self._lut_pix2pos=(K, AA)
_log.debug('least square data:\nK:{}\nAA:{}'.format(K, AA))
def autofocus(self):
@@ -410,30 +417,30 @@ if __name__=="__main__":
(-3.2, -6.8, 675.10991143017, 790.3040145281),
(-3.2, -6.72, 638.98580653116, 59.3803912957)]}
measure=\
{1: [(6.4190000000000005, 6.907, 696.2976073449591, 227.76776138682274),
(5.719, 6.807, 410.67447894055806, 284.44919082240665),
(5.719, 5.207, 434.78681995014756, 938.5631353309454),
(6.619, 5.207, 808.7345059175318, 927.4590367789931)],
200: [(6.619, 6.607, 940.264899030901, 187.39774454408854),
(5.519, 6.607, 272.1925062601967, 219.8977706369289),
(5.519, 5.407, 298.31361407848783, 941.97432810785),
(6.619, 5.407, 969.4645435773624, 920.3295993015843)],
400: [(6.719, 6.707, 1099.5956451604673, 46.46696479882394),
(5.719, 6.707, 91.88845211350781, 99.00912182475837),
(5.719, 5.807, 122.49326406274122, 998.8073593766618),
(6.719, 5.807, 1137.5074440945523, 963.4302060882611)],
600: [(6.619, 6.807, 1068.8592966662907, 106.9592377596037),
(6.019, 6.807, 75.47928488084321, 151.1144445833613),
(6.019, 6.307, 103.13064811335389, 977.5525209662414),
(6.619, 6.307, 1104.9406638931132, 939.9675773457886)],
800: [(6.619, 6.307, 1160.5691045813528, 202.93697492698996),
(6.219, 6.307, 65.05964829488164, 253.28864950246646),
(6.219, 6.107, 88.00366601279788, 797.1538427010806),
(6.619, 6.107, 1180.6517090746024, 753.0303703110591)],
1000: [(6.519, 6.267, 1087.8134573150567, 183.90222416155348),
(6.319, 6.267, 160.59872007696185, 229.55456266733404),
(6.319, 6.107, 190.50887289109403, 963.1404158981525),
(6.519, 6.107, 1116.3595117455784, 925.6445737503763)]}
{1000: [(-0.7310599999999997, 0.643119999999999, 1068.294887300626, 37.80427622442167),
(-0.8105999999999997, 0.6437299218749977, 325.69398272322496, 66.36584947739863),
(-0.8073999999999999, 0.548, 394.71778475125257, 954.1547514240993),
(-0.7257699218749997, 0.5511799999999984, 1155.1696726117643, 900.6018015747674)],
800: [(-0.7087599999999997, 0.6409199999999983, 1056.3942317785522, 65.17578392519127),
(-0.8374999999999998, 0.6427399999999998, 354.2555559762018, 79.45657055167973),
(-0.8393599999999997, 0.4836299999999992, 378.0568670203493, 955.3448169763066),
(-0.6977599999999998, 0.487619999999999, 1159.9299348205936, 906.5521293358044)],
600: [(-0.6560399999999997, 0.6448999999999997, 1112.3273127322987, 61.60558726856914),
(-0.8914799999999998, 0.6495299218750006, 324.5039171710175, 67.55591502960601),
(-0.8760799999999997, 0.3893999999999978, 407.80850582553353, 930.3534403799518),
(-0.6621199999999997, 0.39789999999999964, 1128.988230463202, 873.2302938739978)],
400: [(-0.6044999999999998, 0.6441200000000008, 1074.2452150616627, 63.98571837298388),
(-0.9739299218749998, 0.6475599999999995, 310.2231305445289, 73.50624279064286),
(-0.9546199999999997, 0.22334999999999855, 398.28798140787467, 926.7832437233297),
(-0.5859199999999999, 0.23333999999999833, 1144.4590826418978, 880.3706871872422)],
200: [(-0.4556199999999997, 0.6560399999999991, 1119.4677060455429, 44.9446695376659),
(-1.0542399999999998, 0.6175399999999991, 381.6270636769714, 108.01814380465672),
(-1.0568399999999998, -0.05702000000000044, 413.7588335865705, 932.7335714843665),
(-0.47519999999999984, -0.03876000000000022, 1136.1286237764461, 881.5607527394494)],
1: [(-0.3154599999999996, 0.6150199999999987, 1112.3273127322987, 78.26650499947237),
(-1.1583899218749996, 0.5868999999999996, 425.65948910864427, 129.43932374438944),
(-1.2067399218749997, -0.3514000000000015, 400.6681125122893, 905.3620637835969),
(-0.3347399999999998, -0.36506000000000133, 1136.1286237764461, 880.3706871872422)]}
obj.update_pix2pos(measure)

View File

@@ -95,54 +95,56 @@ class Marker(pg.ROI):
if m==0:
p.drawEllipse(0, 0, 100, 100)
p.drawRect(0, 0, 100, 100)
p.drawRect(0, 0, 5, 5)
p.setPen(pg.mkPen(width=3, color=[200, 100, 100]))
p.drawLine(pg.Point(50, 0), pg.Point(50, 100))
p.drawLine(pg.Point( 0,50), pg.Point(100, 50))
tr=p.transform()
tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33())
p.setTransform(tr)
ofx,ofy=Marker.txtTrf(p)
f=p.font()
f.setPixelSize(10)
p.setFont(f)
p.drawText(24, -80, 'beam marker')
p.drawText(ofx+24, ofy+20, 'beam marker')
ctr=tuple(self.pos()+self.size()/2)
sz=tuple(self.size())
p.drawText(5, -55, '{:.1f}x{:.1f}'.format(*sz))
p.drawText(ofx+5, ofy+45, '{:.1f}x{:.1f}'.format(*sz))
#p.drawText(5, -35, '{:.1f}'.format(ctr[0]))
p.drawText(5, -45,42,30,Qt.AlignRight, '{:.1f}'.format(ctr[0]))
p.drawText(55, -35, '{:.1f}'.format(ctr[1]))
p.drawText(ofx+5, ofy+55,42,30,Qt.AlignRight, '{:.1f}'.format(ctr[0]))
p.drawText(ofx+55, ofy+65, '{:.1f}'.format(ctr[1]))
elif m==1:
p.drawEllipse(20,20,60,60)
p.drawRect(0, 0, 5, 5)
p.drawRect(0, 0, 100, 100)
p.setPen(pg.mkPen(width=2, color=[10, 255, 0]))
p.drawLine(pg.Point(50, 0), pg.Point( 50,100))
p.drawLine(pg.Point( 0,50), pg.Point(100, 50))
tr=p.transform()
tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33())
p.setTransform(tr)
ofx,ofy=Marker.txtTrf(p)
f=p.font();
f.setPixelSize(10)
p.setFont(f)
#p.drawText(ofx+0, ofy+0, 'FFF')
#p.drawText(ofx+100, ofy+100, 'GGG')
px=tuple(self.pos()+self.size()/2)
p.drawText(5, -90, 'optical')
p.drawText(55,-90, 'center')
#p.drawText(5, -10, '{:.1f}/{:.1f}'.format(*px))
p.drawText(5, -10, '{:.1f}'.format(px[0]))
p.drawText(55, -10, '{:.1f}'.format(px[1]))
#p.drawText(0, 0, 'Thierry')
p.drawText(ofx+18, ofy+10, 'optical center')
p.drawText(ofx+5, ofy+80,42,30,Qt.AlignRight, '{:.1f}'.format(px[0]))
p.drawText(ofx+55,ofy+90, '{:.1f}'.format(px[1]))
@staticmethod
def txtTrf(p):
tr=p.transform()
assert (p.transform()==p.worldTransform())
m11, m12, m13, m21, m22, m23, m31, m32, m33=tr.m11(), tr.m12(), tr.m13(), tr.m21(), tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33()
ofx=ofy=0
if m11<0:
m11=-m11; m12=-m12; ofx-=100
if m22<0:
m22=-m22; m21=-m21; ofy=-100
tr.setMatrix(m11, m12, m13, m21, m22, m23, m31, m32, m33)
p.setTransform(tr)
return ofx,ofy
# w, h = self.getState()["size"]
# v1, v2 = -(h * 0.8) / 2, (h * 0.8) / 2
# h1, h2 = -(w * 0.8) / 2, (w * 0.8) / 2
# p.setRenderHint(QtGui.QPainter.Antialiasing)
# p.setPen(pg.mkPen(width=3, color=[200, 100, 100]))
# p.drawLine(pg.Point(0, v1), pg.Point(0, v2))
# p.drawLine(pg.Point(h1, 0), pg.Point(h2, 0))
# p.setPen(self.currentPen)
# #p.setPen(pg.mkPen(width=3, color=[200, 200, 100]))
# p.drawRect(-w / 2, -h / 2, w, h)
# # p.drawText(-w, -h, '{:.0f}x{:.0f}'.format(*self._size))
class Fiducial(pg.ROI):
def __init__(self, pos, size, z:float, **kargs):
@@ -602,7 +604,8 @@ if __name__=='__main__':
obj_info(tr)
#tr.setMatrix(tr.m11(),tr.m12(),tr.m13()+100,tr.m21(),tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33())
#tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),tr.m22(),tr.m23(),tr.m31(),tr.m32()+20,tr.m33())
tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),-tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33())
#tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),-tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33())
tr.setMatrix(-tr.m11(),tr.m12(),tr.m13(),tr.m21(),-tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33())
obj_info(tr)
o.setTransform(tr)
elif m&Qt.AltModifier:
@@ -645,26 +648,37 @@ if __name__=='__main__':
vb.addItem(viImg)
# Custom ROI for selecting an image region
#viRoi=pg.ROI([20, -50], [60, 40])
viRoi=TxtROI([20, -50], [60, 40])
#viRoi=TxtROI([20, -50], [60, 40])
#viRoi.addScaleHandle([1, 1], [0, 0])
#viRoi.addScaleHandle([.7, .5], [0, 0])
vb.addItem(viRoi)
#vb.addItem(viRoi)
viUsrRoi=Marker([50, 120], [30, 20],mode=0)
vb.addItem(viUsrRoi)
obj=Marker([250, 220], [30, 20],mode=1)
vb.addItem(obj)
#obj=Marker([250, 220], [30, 20],mode=1)
#vb.addItem(obj)
vi=Grid( (120,-100), (200,150), (30,20),2)
tr=QtGui.QTransform() # prepare ImageItem transformation:
tr.setMatrix(1, -.1, 0,
.2, 1, 0,
10, 10, 1)
vi.setTransform(tr) # assign transform
#vi=Grid( (50,10), (200,150), (6,4))
vb.addItem(vi) #vi= visual item
grp=pg.ItemGroup()
vb.addItem(grp)
tr.setMatrix(-1, -.1, 0,
.2, -1, 0,
10, 10, 1)
grp.setTransform(tr) # assign transform
obj=Marker([20, 40], [30, 20],mode=1)
grp.addItem(obj)
obj=Marker([20, 40], [30, 20],mode=1)
vb.addItem(obj)
fidScl=.5
fiducial=np.array(((18, 7), (25, 16), (70, 20)))
path=gen_swissmx_points(ofs=(10, 5), width=200)

View File

@@ -394,14 +394,29 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
tr=QtGui.QTransform() # prepare ImageItem transformation:
opt_ctr=app._geometry._opt_ctr
#--- image group ---
# uses image transformation
# contains image and opticalcenter
self._goImgGrp=grp=pg.ItemGroup()
self.vb.addItem(grp)
trf=cfg.value(AppCfg.GEO_CAM_TRF)
# be aware: setTransform is transposed!
# Qt uses: p'=(p.T*A.T).T , but I am used: p'=A*p, with p=[x,y,1].T
tr.setMatrix(trf[0,0],trf[1,0],trf[2,0], #(-1, 0, 0,
trf[0,1],trf[1,1],trf[2,1], # 0,-1, 0,
trf[0,2],trf[1,2],trf[2,2]) # 0, 0, 1)
grp.setTransform(tr) # assign transform
#--- image ---
self._goImg=img=pg.ImageItem()
tr.setMatrix(-1, 0, 0,
0,-1, 0,
0, 0, 1)
# opt_ctr[0], opt_ctr[1], 1)
img.setTransform(tr) # assign transform
vb.addItem(img)
grp.addItem(img)
#--- opctical center ----
oc_sz=np.array((50,50))
#self._goOptCtr=obj=UsrGO.Marker(-opt_ctr+oc_sz/2, oc_sz,mode=1)
self._goOptCtr=obj=UsrGO.Marker(opt_ctr-oc_sz/2, oc_sz,mode=1)
obj.sigRegionChangeFinished.connect(self.cb_marker_moved)
grp.addItem(obj)
#--- grid ---
try:
@@ -412,16 +427,10 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
self._goGrid=grid=pg.GridItem() # green grid and labels
grid.opts['pen']=QPen(QColor(0, 255, 0))
grid.opts['textPen']=QPen(QColor(0, 255, 0))
tr.reset()
#tr.reset()
#grid.setTransform(tr) # assign transform
vb.addItem(grid)
#--- opctical center ----
oc_sz=np.array((50,50))
self._goOptCtr=obj=UsrGO.Marker(-opt_ctr-oc_sz/2, oc_sz,mode=1)
obj.sigRegionChangeFinished.connect(self.cb_marker_moved)
#obj.setTransform(tr) # assign transform
vb.addItem(obj)
#--- beam marker ---
bm_sz=np.array((50, 40)) # it is immidiatly repositioned in cb_zoom_changed
@@ -658,9 +667,9 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
cam=app._camera
cfg=app._cfg
param=cam.get_param()
try:
paramSv=cfg.value(AppCfg.GEO_CAM_PARAM)
except AttributeError as e:
paramSv=cfg.value(AppCfg.GEO_CAM_PARAM)
if paramSv is None:
cfg.setValue(AppCfg.GEO_CAM_PARAM, param)
else:
for k,v in param.items():