Skip to content

Commit

Permalink
added final calibration gui for the extended zolof calibration and ma…
Browse files Browse the repository at this point in the history
…tched it with the workflow and params file.
  • Loading branch information
ronshnapp committed Feb 10, 2024
1 parent e048407 commit 67cfe04
Show file tree
Hide file tree
Showing 4 changed files with 288 additions and 43 deletions.
4 changes: 2 additions & 2 deletions example/params_file.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
- calibration:
3D_model: Tsai
camera_name: cam3
camera_name: cam1
resolution: 1280, 1024
calibration_image: ./Calibration/cal3.tif
calibration_image: ./Calibration/cal1.tif
target_file: ./Calibration/target_file

- analyze_calibration_error:
Expand Down
66 changes: 25 additions & 41 deletions example/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ def initial_calibration(self):


elif model_name == 'extendedZolof':
...
from myptv.extendedZolof.gui_intial_cal import initial_cal_gui
image = imread(cal_image)
gui = initial_cal_gui(cam_name, cal_image, target_file)


else:
Expand Down Expand Up @@ -301,7 +303,28 @@ def final_calibration(self):


elif model_name == 'extendedZolof':
...
from myptv.extendedZolof.camera import camera_extendedZolof
from myptv.extendedZolof.calibrate import calibrate_extendedZolof
from myptv.extendedZolof.gui_final_cal import cal_gui

try:
cam = camera_extendedZolof(cam_name, cal_points_fname = blob_file)
except:
msg = 'Calibration point file (%s) is not right!'%blob_file
msg2 = 'check that the file exists and that it has no errors.'
raise ValueError(msg+msg2)

cam.load('.')
print('camera data loaded successfully.')
cal = calibrate_extendedZolof(cam,
cam.image_points,
cam.lab_points)
print('Starting calibration gui')
gui = cal_gui(calibrate_obj=cal)
#cal.calibrate()
err = cal.mean_squared_err()
print('Calibration finished. The calibration error is: %.3e'%err)
#cam.save('.')


else:
Expand Down Expand Up @@ -578,45 +601,6 @@ def calibration_with_particles(self):
print('starting calibration GIU using calibration with particles\n')
gui = cal_gui(cal, cal_image)


# print('\n', 'ready to calibrate')
# print('initial error: %.3f pixels'%(cal.mean_squared_err()))
# print('')

# user = True
# print('Starting calibration sequence:')
# while user != '9':
# print("enter '1' for external parameters calibration")
# print("enter '2' for internal correction ('fine') calibration")
# print("enter '3' to show current camera external parameters")
# print("enter '4' to plot the calibration points' projection")
# print("enter '8' to save the results")
# print("enter '9' to quit")
# user = input('')

# if user == '1':
# print('\n', 'Iterating to minimize external parameters')
# cal.searchCalibration(maxiter=2000)
# err = cal.mean_squared_err()
# print('\n','calibration error: %.3f pixels'%(err),'\n')

# if user == '2':
# print('\n', 'Iterating to minimize correction terms')
# cal.fineCalibration()
# err = cal.mean_squared_err()
# print('\n','calibration error:', err,'\n')

# if user == '3':
# print('\n', cam, '\n')

# if user == '4':
# fig, ax = subplots()
# cal.plot_proj(ax=ax)
# show()
# if user == '8':
# print('\n', 'Saving results')
# cam.save('.')



def do_segmentation(self):
Expand Down
36 changes: 36 additions & 0 deletions myptv/extendedZolof/calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,42 @@ def mean_squared_err(self):



def plot_err_distribution(self, ax = None):
import matplotlib.pyplot as plt
from numpy import sum as npsum

if ax == None:
fig, ax = plt.subplots()

imc = array(self.x_list)
z_lst = array([self.cam.projection(x) for x in self.X_list])
err = npsum((imc-z_lst)**2, axis=1)**0.5

h = ax.hist( err, bins='auto')
ax.set_xlabel('Camera projection err [px]')
ax.set_ylabel('Counts')




def plot_proj(self, ax = None):
import matplotlib.pyplot as plt

if ax == None:
fig, ax = plt.subplots()

imc = array(self.x_list)
ax.plot(imc[:,0], imc[:,1], 'ob')
for i in range(imc.shape[0]):
ax.text(imc[i,0], imc[i,1], '%d'%i, color = 'b')

z_lst = array([self.cam.projection(x) for x in self.X_list])
ax.plot( z_lst[:,0], z_lst[:,1], 'xr' )
for i in range(z_lst.shape[0]):
ax.text(z_lst[i,0], z_lst[i,1], '%d'%i, color = 'r')

ax.set_aspect('equal')




225 changes: 225 additions & 0 deletions myptv/extendedZolof/gui_final_cal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# -*- coding: utf-8 -*-
"""
Created on April 23, 2022
@author: Ron
A gui for the final calibration of a Tsai model camera.
"""


#from PIL import Image, ImageTk
from tkinter import Label, LabelFrame, Entry, Tk, Button, Checkbutton, IntVar
from matplotlib.pyplot import subplots, show, imread


class cal_gui(object):
'''
This is a Tkinter based graphical user interface that can be used to mark
points on a static image, give their lab space coordinates, and then save
the data as a text file in the format used by the calibration processes.
'''


def __init__(self, calibrate_obj=None, cal_image=None):
'''
input:
calibrate_obj - An instance of the calibrate class, ready to perform
calibration.
'''
self.calibrate_obj = calibrate_obj
self.cal_image = cal_image

# set the window
self.root = Tk()
self.root.geometry('370x350')
#self.root.resizable(0,0)
self.root.resizable(height = None, width = None)
self.root.title('MyPTV: Extended Zolof calibration GUI')


# =============================
# BUTTONS:

# buttons frame
button_label = LabelFrame(self.root, padx=10, pady=3, width=100)
button_label.grid(row=0, column=0, padx=(10), pady=3, sticky='nsew')


# Buttons frame1
button_frame1 = Label(button_label)
button_frame1.grid(row=0, column=0, columnspan=1, sticky='nsw', padx=2,
pady=3)



# external params calibration button
calibrate_button = Button(button_frame1, text='Calibrate',
command = self.calibrate,
padx=2, pady=4, width=20)
calibrate_button.grid(row=0, column=0, padx=10, pady=2, sticky='ew')


# plot calibration
plot_button = Button(button_frame1, text='Plot calibration',
command = self.plot_calibration,
padx=2, pady=4, width=20)
plot_button.grid(row=1, column=0, padx=10, pady=2, sticky='ew')

# plot error historam
plot_button = Button(button_frame1, text='Plot error hist.',
command = self.plot_err_hist,
padx=2, pady=4, width=20)
plot_button.grid(row=2, column=0, padx=10, pady=2, sticky='ew')


# save points button
save_button = Button(button_frame1, text='Save',
command = self.Save, padx=10, pady=4, width=15)
save_button.grid(row=5, column=0, padx=10, pady=30, sticky='ew')


# quit button
quit_button = Button(button_frame1, text='Quit',
command = self.Quit, padx=10, pady=4, width=15)
quit_button.grid(row=5, column=1, padx=10, pady=30, sticky='ew')







# =============================
# CALIBRATOR STATUS:


status_label = LabelFrame(self.root, padx=10, pady=4, width=30)
status_label.grid(row=1, column=0, padx=(10), pady=4, sticky='nsew')

self.status = Label(status_label, text='Status:', padx=2, pady=2)
self.status.grid(row=0, column=0, rowspan=1, sticky='nw', padx=2, pady=2)
self.status_show = Label(status_label, text='wating for action', padx=2, pady=2,
width=30, anchor='w', fg='green')
self.status_show.grid(row=0, column=1, rowspan=1, sticky='nw', padx=2, pady=2)



self.camera = Label(status_label, text='Camera:', padx=2, pady=2)
self.camera.grid(row=1, column=0, rowspan=1, sticky='nw', padx=2, pady=2)

cam = 'camera name'
if self.calibrate_obj is not None:
cam = self.calibrate_obj.cam.name

self.camera_show = Label(status_label, text=cam, padx=2, pady=2,
width=30, anchor='w')
self.camera_show.grid(row=1, column=1, rowspan=1, sticky='nw', padx=2, pady=2)




# =============================
# CAMERA STATUS:



dashboard = LabelFrame(self.root, padx=10, pady=10, width=100)
dashboard.grid(row=2, column=0, padx=(10), pady=10, sticky='nsew')


# err_Dashboard frame - where the error is shown
err_dashboard = LabelFrame(dashboard)
err_dashboard.grid(row=2, column=1, columnspan=1, sticky='sw', padx=2,
pady=10)


self.error = Label(err_dashboard, text='Error:', padx=2, pady=2)
self.error.grid(row=1, column=0, rowspan=1, sticky='nw', padx=2, pady=2)
self.error_input = Label(err_dashboard, text='0.0', padx=2, pady=2,
width=14, bg='white')
self.error_input.grid(row=1, column=1, rowspan=1, sticky='nw', padx=2, pady=2)



#if self.calibrate_obj is not None:
# self.update_cal_stats()




# ==============================
# RUN

# configure hte frames and run main loop
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
button_label.rowconfigure(0, weight=1)
button_label.columnconfigure(0, weight=1)

self.root.mainloop()



def calibrate(self):
'''Does the searchCalibration, i.e. external calibration'''
print('\n','Iterating to minimize external parameters...','\n')
self.status_show.configure(fg='red',
text='minimizing external parameters...')
self.root.update()
self.calibrate_obj.calibrate()
err = self.calibrate_obj.mean_squared_err()
print('\n','calibration error: %.3f pixels'%(err),'\n')
self.error_input.config(text = '%.3e'%err)
self.status_show.configure(fg='green', text='done! waiting for action')




def plot_calibration(self):
'''Plots the calibration using plot_proj function'''
self.status_show.configure(fg='red', text='plotting calibration...')
self.root.update()
fig, ax = subplots()
if self.cal_image is not None:
img = imread(self.cal_image)
ax.imshow(img, cmap='gray')
self.calibrate_obj.plot_proj(ax=ax)
show()
self.status_show.configure(fg='green', text='done! waiting for action')


def plot_err_hist(self):
'''Plots the calibration error histogram'''
self.status_show.configure(fg='red', text='plotting calibration...')
self.root.update()
fig, ax = subplots()
self.calibrate_obj.plot_err_distribution(ax=ax)
show()
self.status_show.configure(fg='green', text='done! waiting for action')


def Save(self):
'''save the calibrated camera'''
self.status_show.configure(fg='red', text='saving results...')
self.root.update()
self.calibrate_obj.cam.save('.')
self.status_show.configure(fg='green', text='done! waiting for action')


def Quit(self):
'''quit the app'''
self.status_show.configure(fg='red', text='bye!')
self.root.update()
self.root.destroy()




if __name__ == '__main__':
gui = cal_gui()



0 comments on commit 67cfe04

Please sign in to comment.