Files
SwissMX/toolbox/fiducialDetection.py

232 lines
6.8 KiB
Python

# -*- coding: utf-8 -*-
"""
Demonstrate a simple data-slicing task: given 3D data (displayed at top), select
a 2D plane and interpolate data along that plane to generate a slice image
(displayed at bottom).
https://www.hindawi.com/journals/js/2021/5643054/
https://www.hindawi.com/journals/mpe/2021/8243072/
"""
import logging
import numpy as np
_log=logging.getLogger(__name__)
import numpy as np
import cv2 as cv
import PIL.Image
from scipy import ndimage,signal
import glob, os
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
pg.setConfigOptions(imageAxisOrder='row-major')
def set_fiducial(pic):
# fiducial test
f=np.array(((0, 0, 0, 0, 0),
(0, 1, 1, 1, 0),
(0, 1, 0, 0, 0),
(0, 1, 1, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 0, 0, 0),), pic.dtype)
pic[0:6, 0:5]=f*pic.max()
def wtestimages():
#fn=os.path.expanduser('~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/fiducial/image{idx:03d}.png')
fn=os.path.expanduser('../scratch/fiducial/image{idx:03d}.png')
img=np.kron(np.array([[1, 0] * 5, [0, 1] * 5] * 6,dtype=np.uint8), np.ones((100, 100),dtype=np.uint8)*255)
set_fiducial(img)
pil_img=PIL.Image.fromarray(img)
pil_img.save(fn.format(idx=2))
img=np.ndarray((1000,1200),dtype=np.uint8)
img[:]=255
#img=np.zeros((1200,1000),dtype=np.uint8)
fid=np.array([[0, 1] * 2, [1, 0] * 2] * 2,dtype=np.uint8)[:3,:3]
fid=np.kron(fid, np.ones((210, 210),dtype=np.uint8)*255)
img[100:100+fid.shape[0],200:200+fid.shape[1]]=fid
set_fiducial(img)
pil_img=PIL.Image.fromarray(img)
pil_img.save(fn.format(idx=3))
img=np.ndarray((1200,1000))
#wtestimages()
class fiducial(QtGui.QMainWindow):
def __init__(self, parent = None):
super(fiducial, self).__init__(parent)
self.resize(800, 1500)
self.setWindowTitle('pyqtgraph example: DataSlicing')
cw=QtGui.QWidget()
self.setCentralWidget(cw)
l=QtGui.QGridLayout()
cw.setLayout(l)
#self._imgLst=imgLst=sorted(glob.glob("../scratch/autofocus1/image*.png"))
self._imgLst=imgLst=sorted(glob.glob("../scratch/fiducial/*.png"))
self._metrics=mtr=np.ndarray(shape=(len(imgLst), 5))
mtr[:]=0
self._sldImgIdx=sld1=QtGui.QSlider(QtCore.Qt.Horizontal)
sld1.setMinimum(0)
sld1.setMaximum(len(imgLst)-1)
sld1.setValue(0)
sld1.setTickPosition(QtGui.QSlider.TicksBelow)
sld1.setTickInterval(1)
sld1.valueChanged.connect(self.cb_sld_change)
self._sldTplSz=sld2=QtGui.QSlider(QtCore.Qt.Horizontal)
sld2.setMinimum(0)
sld2.setMaximum(300)
sld2.setValue(90)
sld2.valueChanged.connect(self.cb_sld_change)
self._sldTplBrd=sld3=QtGui.QSlider(QtCore.Qt.Horizontal)
sld3.setMinimum(3)
sld3.setMaximum(50)
sld3.setValue(20)
sld3.valueChanged.connect(self.cb_sld_change)
self._imv1=imv1=pg.ImageView()
self._imv2=imv2=pg.ImageView()
#spl=QtGui.QSplitter(QtCore.Qt.Horizontal)
self._pw=pw=pg.PlotWidget(name='Plot1') ## giving the plots names allows us to link
self._plt=plt=[]
for c in ('rgbcy'):
plt.append(pw.plot(pen=c))
pw.resize(100,100)
pw.setMaximumSize(2000,200)
l.addWidget(sld1, 0, 0)
l.addWidget(sld2, 1, 0)
l.addWidget(sld3, 2, 0)
l.addWidget(imv1, 3, 0)
l.addWidget(imv2, 4, 0)
l.addWidget(pw, 5, 0)
## Display the data
self.cb_sld_change(0,True)
mtr[1:,:]=mtr[0,:]
self._imv1.setHistogramRange(0, 100)
self._imv1.setLevels(0, 40)
#self._imv2.setHistogramRange(0, 100)
#self._imv2.setLevels(0, 40)
self._imv2.setHistogramRange(0, 1)
self._imv2.setLevels(0, 1)
def cb_sld_change(self,val,auto=False):
i=self._sldImgIdx.value()
_log.debug(f'{i}')
fn= self._imgLst[i]
img=PIL.Image.open(fn)
img=np.asarray(img)
#pil_img=PIL.Image.fromarray(img)
#pil_img.save('../scratch/fiducial/image002.png')
#fn='/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/fiducial/zoom0400.png'
#pil_img=PIL.Image.open(fn+'_')
#img=np.asarray(pil_img)
#img=np.array(img,dtype=np.uint8)
#pil_img=PIL.Image.fromarray(img)
#pil_img.save(fn)
#img16=np.array(img,np.int16)
#fft=np.log(np.abs(np.fft.fft2(img)))
#fft=np.fft.fftshift(fft)
fid=np.array([[0, 1]*2, [1, 0]*2]*2, dtype=np.uint8)[:3, :3]
fid=np.kron(fid, np.ones((100, 100), dtype=np.uint8)*255)
#res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED )
#fid=np.ones((250,250),dtype=np.uint8)*255
#fid[20:230,20:230]=0
#sz=( 84, 84); brd=( 7, 7) # zoom 001
#sz=(128, 128); brd=( 9, 9) # zoom 200
#sz=(200, 200); brd=(13, 13) # zoom 400
v=self._sldTplSz.value(); sz=(v,v)
v=self._sldTplBrd.value(); brd=(v,v)
fid=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255
fid[brd[1]:sz[1]+brd[1],brd[0]:sz[0]+brd[0]]=0
mask=np.ones((sz[1]+2*brd[1],sz[0]+2*brd[0]),dtype=np.uint8)*255
mask[2*brd[1]:sz[1],2*brd[0]:sz[0]]=0
#https://docs.opencv.org/4.5.2/d4/dc6/tutorial_py_template_matching.html
#res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED )
res = cv.matchTemplate(img,fid,cv.TM_CCORR_NORMED,mask=mask)
corr_u8=np.array(res*255,np.uint8)
h,w=img.shape
fh2,fw2=fid.shape
fw2//=2
fh2//=2
mtr=np.ndarray((5,2),np.uint16)
corr=np.ndarray((5,),np.float32)
for i in range(5):
p=np.unravel_index(res.argmax(), res.shape)
corr[i]=res[p]
mtr[i,:]=p
y0=max(p[0]-fh2,0)
y1=min(p[0]+fh2,h)
x0=max(p[1]-fw2,0)
x1=min(p[1]+fw2,w)
res[y0:y1,x0:x1]*=.5
res[p[0],p[1]]=0
corr_u8=np.array(res*255,np.uint8)
ctr=mtr.mean(0,dtype=np.int32)+(fw2,fh2)
try:
img=img*1
img[ctr[0]-5:ctr[0]+5,ctr[1]-5:ctr[1]+5]=255
img[ctr[0],:]=0
img[:,ctr[1]]=0
except IndexError as e:
pass
self._imv1.setImage(img,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
self._imv2.setImage(res,autoRange=auto,autoLevels=auto,autoHistogramRange=auto)
pos=mtr.mean(0)[::-1]+(fw2,fh2)
print(fid)
print(mask)
print(corr)
print(mtr)
print(f'TplSz:{sz} TplBrd:{brd}')
_log.debug(f'position: {pos} correlation:{corr.mean()}')
#mtr=self._metrics
#mtr[i, 0]=img.std()
#mtr[i, 1]=sb.sum()
#mtr[i, 2]=sb.std()
#mtr[i, 3]=sbLut.sum()#sb.std()
#mtr[i, 4]=sbLut.std()#img2.sum()
#mx=mtr.max(0)
#mn=mtr.min(0)
#mtr=(mtr-mn)/(mx-mn)
#_log.debug(f'{i} {mtr[i,:]}')
#for i in range(mtr.shape[1]):
# self._plt[i].setData(mtr[:,i])
## Start Qt event loop unless running in interactive mode.
if __name__=='__main__':
import sys
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
app=QtGui.QApplication([])
fd=fiducial()
fd.show()
if (sys.flags.interactive!=1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()