-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b118197
commit 8ef90dc
Showing
93 changed files
with
11,806 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import matplotlib.pyplot as plt | ||
import time | ||
import numpy as np | ||
from PIL import Image | ||
|
||
class graphic_display(): | ||
def __init__(self): | ||
self.um_per_pixel = 0.5 | ||
self.cm_hot = plt.get_cmap('hot') | ||
self.cm_jet = plt.get_cmap('jet') | ||
self.cm_vir = plt.get_cmap('viridis') | ||
self.cm_mag = plt.get_cmap('magma') | ||
# self.cm_grn = plt.get_cmap('Greens') | ||
self.cm_raw = plt.get_cmap('gray') | ||
self.fps_counter = np.array([time.time(),time.time(),time.time()]) | ||
self.img_rs = None | ||
self.img_norm = None | ||
self.img_gamma = None | ||
self.img_p = None | ||
self.img_cm = None | ||
self.img_sb = None | ||
self.img_fin = None | ||
self.win = None | ||
self.cam = None | ||
return | ||
|
||
def update_win(self, win): | ||
self.win = win | ||
|
||
def update_cam(self, cam): | ||
self.cam = cam | ||
|
||
def update_image(self): | ||
print('update image function') | ||
self.img_rs = np.array(Image.fromarray(self.cam.img_raw).resize(size=(958, 638)),dtype = 'float64')/255 | ||
if self.win.zoom_factor > 1: | ||
r1 = self.img_rs.shape[0] | ||
c1 = self.img_rs.shape[1] | ||
r2 = int(np.round(r1/self.win.zoom_factor)) | ||
c2 = int(np.round(c1/self.win.zoom_factor)) | ||
self.img_rs = self.img_rs[int((r1-r2)/2):int((r1-r2)/2)+r2, int((c1-c2)/2):int((c1-c2)/2)+c2] | ||
|
||
# update and process the image for display from the camera | ||
self.update_image_gamma() | ||
self.normalise_img() | ||
self.update_colormap() | ||
self.display_saturated_pixels_purple() ### error | ||
self.burn_scalebar_into_image() | ||
|
||
# gui functions | ||
self.win.repaint_image() ### may zoom in twice for raw image, need double check | ||
self.win.update_hist() | ||
# self.win.image_histogram.update_histogram() # method in histogram_canvas class | ||
self.win.status_text_update_image() | ||
|
||
# fps counter | ||
self.fps_counter = np.append(self.fps_counter,time.time()) | ||
self.fps_counter = np.delete(self.fps_counter, 0) | ||
self.win.status_fps_number.setText(str(np.round(1/np.mean(np.diff(self.fps_counter)),5))) | ||
print('current saved value for fps is: ' + str(self.cam.fps) + ' current timer value is: ' + str(self.cam.timer_value)) | ||
return | ||
|
||
def update_image_gamma(self): | ||
|
||
if self.win.gamma == 1: | ||
self.img_gamma = self.img_rs | ||
else: | ||
self.img_gamma = self.img_rs**self.win.gamma | ||
return | ||
|
||
def normalise_img(self): | ||
print('normalise function') | ||
if self.win.cbox_normalise.isChecked(): | ||
imgnormmin = np.min(np.nonzero(self.img_gamma)) | ||
imgnormmax = np.max(self.img_gamma) | ||
self.img_norm = (self.img_gamma-imgnormmin)/(imgnormmax--imgnormmin) | ||
self.img_norm = self.img_norm | ||
else: | ||
self.img_norm = self.img_gamma | ||
return | ||
|
||
def update_colormap(self): | ||
print('update colormap function') | ||
# convert from gray to colormap magma selection | ||
if self.win.combobox_colourmap.currentIndex() == 0: | ||
self.img_cm = self.cm_mag(self.img_norm) | ||
# convert from gray to colormap green selection | ||
elif self.win.combobox_colourmap.currentIndex() == 1: | ||
self.img_cm = np.zeros(np.hstack([np.shape(self.img_norm),4])) | ||
self.img_cm[:,:,1] = self.img_norm | ||
self.img_cm[:,:,3] = 255 | ||
## or use Greens colormap directly | ||
# self.img_cm = self.cm_grn(self.img_norm) | ||
# convert from gray to colormap viridis (3 channel) selection | ||
elif self.win.combobox_colourmap.currentIndex() == 2: | ||
self.img_cm = self.cm_vir(self.img_norm) | ||
# convert from gray to colormap jet selection | ||
elif self.win.combobox_colourmap.currentIndex() == 3: | ||
self.img_cm = self.cm_jet(self.img_norm) | ||
elif self.win.combobox_colourmap.currentIndex() == 4: | ||
# self.img_cm = np.zeros(np.hstack([np.shape(self.img_norm),4])) | ||
# self.img_cm[:,:,0] = self.img_norm | ||
# self.img_cm[:,:,1] = self.img_norm | ||
# self.img_cm[:,:,2] = self.img_norm | ||
# self.img_cm[:,:,3] = 1 | ||
# print(self.img_cm) | ||
# print(self.cam.img_raw) | ||
## or use gray colormap directly | ||
self.img_cm = self.cm_raw(self.img_norm) | ||
return | ||
|
||
def display_saturated_pixels_purple(self): | ||
print('saturated pxls purple function') | ||
# saturated pixels show up purple if check box is selected | ||
# if self.win.combobox_colourmap.currentIndex() != 4: | ||
self.img_p = self.img_cm | ||
if self.win.cbox_saturated.isChecked(): | ||
ind = self.img_norm > 254 | ||
self.img_p[ind,0] = 255 | ||
self.img_p[ind,1] = 0 | ||
self.img_p[ind,2] = 255 | ||
return | ||
|
||
def burn_scalebar_into_image(self): | ||
print('burn scalebar function') | ||
self.img_sb = self.img_p | ||
if self.win.cbox_show_scalebar.isChecked(): | ||
s = self.img_sb.shape | ||
if self.win.combobox_colourmap.currentIndex() == 1: | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 0] = 255 | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 1] = 0 | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 2] = 255 | ||
else: | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 0] = 0 | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 1] = 255 | ||
self.img_sb[int(s[0]*0.95):int(s[0]*0.955), int(s[1]*0.05):int(s[1]*0.05+100/self.um_per_pixel), 2] = 0 | ||
self.img_fin = self.img_sb | ||
self.img_fin = np.array(self.img_fin*255,dtype='uint8') | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import numpy as np | ||
from matplotlib.figure import Figure | ||
import matplotlib as mpl | ||
import matplotlib.pyplot as plt | ||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas | ||
|
||
|
||
class histogram_canvas(FigureCanvas): | ||
|
||
def __init__(self, parent=None): | ||
histo_fig = Figure(dpi=100, constrained_layout=True) | ||
histo_fig.set_facecolor((240/255, 240/255, 240/255)) | ||
self.axes = histo_fig.add_subplot(111) | ||
self.axes.set_facecolor((180/255, 180/255, 180/255)) | ||
super(histogram_canvas, self).__init__(histo_fig) | ||
# define properties for the image histogram | ||
self.number_of_bins = 80 | ||
self.bin_range = int(255/80) | ||
self.x1 = range(0,255,self.bin_range) | ||
self.xtickedges = np.arange(0, 257, 257/self.number_of_bins).tolist() | ||
self.axes.set_xlabel('bit depth') | ||
self.axes.set_ylabel('histo count (log)') | ||
self.xtickbins = np.arange(0, 257, 256/10).tolist() | ||
self.axes.get_xaxis().set_ticks(self.xtickbins) | ||
self.axes.get_xaxis().set_ticklabels(np.hstack([1,['']*(len(self.xtickbins)-2),255])) | ||
self.axes.set(xlim=(-1, 257)) | ||
self.axes.set_yscale('log') | ||
self.axes.get_yaxis().set_ticklabels([]) | ||
self.axes.grid(which='major', color='black', linestyle='-', linewidth=0.1, alpha=0.5) | ||
self.axes.grid(which='minor', color='black', linestyle='-', linewidth=0.05, alpha=0.25) | ||
self.axes.xaxis.labelpad = -10 | ||
self.axes.yaxis.labelpad = -3 | ||
self._plot_ref1 = None | ||
self._plot_ref2 = None | ||
self.win = None | ||
self.graphic_display = None | ||
self.cam = None | ||
return | ||
|
||
def update_win(self, win): | ||
self.win = win | ||
|
||
def update_graph(self, gra): | ||
self.graphic_display = gra | ||
|
||
def update_cam(self, cam): | ||
self.cam = cam | ||
|
||
def update_histogram(self): | ||
print('update histogram function') | ||
# t = time.time() | ||
if self._plot_ref1 is None: | ||
h1 = (self.cam.img_raw.flatten()*(self.number_of_bins/256)) | ||
h1 = np.unique(h1.astype(np.uint8), return_counts=True) | ||
x1 = np.arange(self.number_of_bins) | ||
y1 = np.zeros(self.number_of_bins) | ||
for i in np.unique(h1[0]): | ||
y1[i] = h1[1][np.where(h1[0] == i)] | ||
y2 = np.zeros(self.number_of_bins) | ||
plot_refs1 = self.axes.plot(x1*(256/self.number_of_bins),y1, 'white', linewidth=2, alpha=0.5) | ||
plot_refs2 = self.axes.plot(x1*(256/self.number_of_bins),y2, 'red', linewidth=2, alpha=0.5) | ||
self._plot_ref1 = plot_refs1[0] | ||
self._plot_ref2 = plot_refs2[0] | ||
else: | ||
h1 = (self.cam.img_raw.flatten()*(self.number_of_bins/256)) | ||
h1 = np.unique(h1.astype(np.uint8), return_counts=True) | ||
x1 = np.arange(self.number_of_bins) | ||
y1 = np.zeros(self.number_of_bins) | ||
for i in np.unique(h1[0]): | ||
y1[i] = h1[1][np.where(h1[0] == i)] | ||
self._plot_ref1.set_ydata(y1) | ||
|
||
if self.win.cbox_normalise.isChecked() or self.win.gamma != 1: | ||
h2 = (self.graphic_display.img_norm.flatten()*(self.number_of_bins/256)) | ||
h2 = np.unique(np.asarray(h2, dtype=np.uint8), return_counts=True) | ||
y2 = np.zeros(self.number_of_bins) | ||
for i in np.unique(h2[0]): | ||
y2[i] = h2[1][np.where(h2[0] == i)] | ||
self._plot_ref2.set_ydata(y2) | ||
else: | ||
self._plot_ref2.set_ydata(np.zeros(self.number_of_bins)) | ||
y2 = y1 | ||
self.axes.axis(ymin=1,ymax=2.5*np.amax(np.hstack([y1,y2]),0)) | ||
self.win.image_histogram.draw() | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
from PyQt5.QtCore import * | ||
import time | ||
import sig as s | ||
import traceback | ||
import sys | ||
|
||
class Worker(QRunnable): | ||
''' | ||
Worker thread | ||
:param callback: The function callback to run on this worker thread. Supplied args and | ||
kwargs will be passed through to the runner. | ||
:type callback: function | ||
:param args: Arguments to pass to the callback function | ||
:param kwargs: Keywords to pass to the callback function | ||
''' | ||
|
||
def __init__(self, fn, *args, **kwargs): | ||
super(Worker, self).__init__() | ||
# Store constructor arguments (re-used for processing) | ||
self.fn = fn | ||
self.args = args | ||
self.kwargs = kwargs | ||
self.signals = s.WorkerSignals() | ||
|
||
# Add the callback to our kwargs | ||
self.kwargs['progress_callback'] = self.signals.progress | ||
|
||
@pyqtSlot() | ||
def run(self): | ||
''' | ||
Initialise the runner function with passed args, kwargs. | ||
''' | ||
# Retrieve args/kwargs here; and fire processing using them | ||
try: | ||
result = self.fn(*self.args, **self.kwargs) | ||
except: | ||
traceback.print_exc() | ||
exctype, value = sys.exc_info()[:2] | ||
self.signals.error.emit((exctype, value, traceback.format_exc())) | ||
else: | ||
self.signals.result.emit(result) # Return the result of the processing | ||
finally: | ||
self.signals.finished.emit() # Done |
Oops, something went wrong.