166 lines
5.5 KiB
Python
166 lines
5.5 KiB
Python
import numpy as np
|
|
import cv2
|
|
|
|
|
|
|
|
|
|
def drawTemperature(img, point, T, color = (0,0,0)):
|
|
d1, d2 = 2, 5
|
|
dsize = 1
|
|
font = cv2.FONT_HERSHEY_PLAIN
|
|
(x, y) = point
|
|
t = '%.2fC' % T
|
|
cv2.line(img,(x+d1, y),(x+d2,y),color, dsize)
|
|
cv2.line(img,(x-d1, y),(x-d2,y),color, dsize)
|
|
cv2.line(img,(x, y+d1),(x,y+d2),color, dsize)
|
|
cv2.line(img,(x, y-d1),(x,y-d2),color, dsize)
|
|
|
|
text_size = cv2.getTextSize(t, font, 1, dsize)[0]
|
|
tx, ty = x+d1, y+d1+text_size[1]
|
|
if tx + text_size[0] > img.shape[1]: tx = x-d1-text_size[0]
|
|
if ty > img.shape[0]: ty = y-d1
|
|
|
|
cv2.putText(img, t, (tx,ty), font, 1, color, dsize, cv2.LINE_8)
|
|
|
|
def autoExposure(update, exposure, frame):
|
|
# Sketchy auto-exposure
|
|
lmin, lmax = frame.min(), frame.max()
|
|
T_min, T_max, T_margin = exposure['T_min'], exposure['T_max'], exposure['T_margin']
|
|
if exposure['auto_type'] == 'center':
|
|
T_cent = int((T_min+T_max)/2)
|
|
d = int(max(T_cent-lmin, lmax-T_cent, 0) + T_margin)
|
|
if lmin < T_min or T_max < lmax or (T_min + 2 * T_margin < lmin and T_max - 2 * T_margin > lmax):
|
|
# print('d:',d, 'lmin:', lmin, 'lmax:', lmax)
|
|
update = True
|
|
T_min, T_max = T_cent - d, T_cent + d
|
|
# print('T_min:', T_min, 'T_cent:', T_cent, 'T_max:', T_max)
|
|
if exposure['auto_type'] == 'ends':
|
|
if T_min > lmin: update, T_min = True, lmin-T_margin
|
|
if T_min + 2 * T_margin < lmin: update, T_min = True, lmin-T_margin
|
|
if T_max < lmax: update, T_max = True, lmax+T_margin
|
|
if T_max - 2 * T_margin > lmax: update, T_max = True, lmax+T_margin
|
|
|
|
exposure['T_min'] = T_min
|
|
exposure['T_max'] = T_max
|
|
return update
|
|
|
|
def correctRoi(roi, shape):
|
|
((x,y),(w,h)) = roi
|
|
# if w == 0 and h == 0:
|
|
# ((x,y),(w,h)) = ((0,0), shape)
|
|
x1,x2 = max(0, min(x,x+w)), max(0, x,x+w)
|
|
y1,y2 = max(0, min(y,y+h)), max(0, y,y+h)
|
|
# if x1 == x2: x2 += 1
|
|
# if y1 == y2: y2 += 1
|
|
return ((x1,y1),(x2,y2))
|
|
|
|
|
|
def inRoi(roi, point, shape):
|
|
result = False
|
|
((x1,y1),(x2,y2)) = correctRoi(roi, shape)
|
|
if x1 < point[0] and point[0] < x2:
|
|
if y1 < point[1] and point[1] < y2:
|
|
result = True
|
|
return result
|
|
|
|
def subdict(d, l):
|
|
return dict((k,d[k]) for k in l if k in d)
|
|
|
|
|
|
class HT301emulator:
|
|
def __init__(self, filename):
|
|
self.load(filename)
|
|
|
|
def save(filename, frame, info, lut, additional_values):
|
|
np.save(filename, np.array([frame, info, lut, additional_values], dtype="object"))
|
|
|
|
def load(self, filename):
|
|
v = np.load(filename, allow_pickle=True)
|
|
self._frame = v[0]
|
|
self._info = v[1]
|
|
self._lut = v[2]
|
|
self._additional_values = v[3]
|
|
print(self._lut)
|
|
|
|
def read(self):
|
|
return True, self._frame
|
|
|
|
def info(self):
|
|
return self._info, self._lut
|
|
|
|
def release(self):
|
|
return
|
|
|
|
def restore_additional_values(self, d):
|
|
for i in self._additional_values:
|
|
d[i] = self._additional_values[i]
|
|
|
|
|
|
|
|
class Annotations:
|
|
def __init__(self, ax, patches):
|
|
self.ax = ax
|
|
self.astyle = dict(s='', xy=(0, 0), xytext=(0, 0), textcoords='offset pixels', arrowprops=dict(facecolor='black', arrowstyle="->"))
|
|
self.anns = {}
|
|
self.roi_patch = ax.add_patch(patches.Rectangle((0, 0), 0, 0, linewidth=1, edgecolor='black', facecolor='none'))
|
|
self.set_roi(((0,0),(0,0)))
|
|
|
|
def set_roi(self, roi):
|
|
self.roi = roi
|
|
((x,y), (w,h)) = roi
|
|
self.roi_patch.xy = (x,y)
|
|
self.roi_patch.set_width(w)
|
|
self.roi_patch.set_height(h)
|
|
self.roi_patch.set_visible(w!=0 and h!=0)
|
|
|
|
def get_ann(self, name, color):
|
|
if name not in self.anns:
|
|
self.anns[name] = self.ax.annotate(**self.astyle, bbox=dict(boxstyle='square', fc=color, alpha=0.3, lw=0))
|
|
return self.anns[name]
|
|
|
|
def update(self, temp_annotations, annotation_frame, draw_temp):
|
|
l = temp_annotations['std'].items() | temp_annotations['user'].items()
|
|
for name, color in l:
|
|
pos = self.get_pos(name, annotation_frame, self.roi)
|
|
self.ann_set_temp(self.get_ann(name, color), pos, annotation_frame, draw_temp)
|
|
|
|
def get(self):
|
|
return list(self.anns.values()) + [self.roi_patch]
|
|
|
|
def remove(self, d):
|
|
for name in d:
|
|
if name in self.anns:
|
|
self.anns[name].remove()
|
|
del self.anns[name]
|
|
d.clear()
|
|
|
|
def ann_set_temp(self, ann, pos, annotation_frame, draw_temp):
|
|
(x,y) = pos
|
|
ann.xy = pos
|
|
value = annotation_frame[pos[1], pos[0]]
|
|
ann.set_text('%.2f$^\circ$C' % value)
|
|
ann.set_visible(draw_temp)
|
|
tx,ty = 20, 15
|
|
if x > annotation_frame.shape[1]-50: tx = -80
|
|
if y < 30: ty = -15
|
|
ann.xyann = (tx, ty)
|
|
|
|
|
|
def get_pos(self, name, annotation_frame, roi):
|
|
((x1,y1),(x2,y2)) = correctRoi(roi, annotation_frame.shape)
|
|
roi_frame = annotation_frame[y1:y2,x1:x2]
|
|
if roi_frame.size <= 0:
|
|
x1,y1 = 0, 0
|
|
roi_frame = annotation_frame
|
|
if name == 'Tmin':
|
|
pos = np.unravel_index(roi_frame.argmin(), roi_frame.shape)
|
|
pos = (pos[1]+x1, pos[0]+y1)
|
|
elif name == 'Tmax':
|
|
pos = np.unravel_index(roi_frame.argmax(), roi_frame.shape)
|
|
pos = (pos[1]+x1, pos[0]+y1)
|
|
elif name == 'Tcenter':
|
|
pos = (annotation_frame.shape[1]//2, annotation_frame.shape[0]//2)
|
|
else:
|
|
pos = name
|
|
return pos
|