[distance_factor_calculation] towards distance factor interpolation

This commit is contained in:
Xaver Roos 2022-04-29 11:51:48 +02:00
parent af9444ab26
commit 08a4abda62
3 changed files with 140 additions and 117 deletions

View File

@ -2,10 +2,22 @@ from turtle import left
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
from IPython import embed from IPython import embed
from etrack import MarkerTask, ImageMarker
def crop_frame(frame, marker_positions):
# load the four marker positions def mark_crop_positions(self):
task = MarkerTask("crop area", ["bottom left corner", "top left corner", "top right corner", "bottom right corner"], "Mark crop area")
im = ImageMarker([task])
marker_positions = im.mark_movie(file_name, frame_number)
print(marker_positions)
np.save('marker_positions', marker_positions)
return marker_positions
def assign_marker_positions(marker_positions):
bottom_left_x = marker_positions[0]['bottom left corner'][0] bottom_left_x = marker_positions[0]['bottom left corner'][0]
bottom_left_y = marker_positions[0]['bottom left corner'][1] bottom_left_y = marker_positions[0]['bottom left corner'][1]
bottom_right_x = marker_positions[0]['bottom right corner'][0] bottom_right_x = marker_positions[0]['bottom right corner'][0]
@ -14,6 +26,21 @@ def crop_frame(frame, marker_positions):
top_left_y = marker_positions[0]['top left corner'][1] top_left_y = marker_positions[0]['top left corner'][1]
top_right_x = marker_positions[0]['top right corner'][0] top_right_x = marker_positions[0]['top right corner'][0]
top_right_y = marker_positions[0]['top right corner'][1] top_right_y = marker_positions[0]['top right corner'][1]
return bottom_left_x, bottom_left_y, bottom_right_x, bottom_right_y, top_left_x, top_left_y, top_right_x, top_right_y
def assign_checkerboard_positions(checkerboard_marker_positions):
checkerboard_top_right = checkerboard_marker_positions[0]['top right corner']
checkerboard_top_left = checkerboard_marker_positions[0]['top left corner']
checkerboard_bottom_right = checkerboard_marker_positions[0]['bottom right corner']
checkerboard_bottom_left = checkerboard_marker_positions[0]['bottom left corner']
return checkerboard_top_right, checkerboard_top_left, checkerboard_bottom_right, checkerboard_bottom_left
def crop_frame(frame, marker_positions):
# load the four marker positions
bottom_left_x, bottom_left_y, bottom_right_x, bottom_right_y, top_left_x, top_left_y, top_right_x, top_right_y = assign_marker_positions(marker_positions)
# define boundaries of frame, taken by average of points on same line but slightly different pixel values # define boundaries of frame, taken by average of points on same line but slightly different pixel values
left_bound = int(np.mean([bottom_left_x, top_left_x])) left_bound = int(np.mean([bottom_left_x, top_left_x]))
@ -22,12 +49,12 @@ def crop_frame(frame, marker_positions):
bottom_bound = int(np.mean([bottom_left_y, bottom_right_y])) bottom_bound = int(np.mean([bottom_left_y, bottom_right_y]))
# crop the frame by boundary values # crop the frame by boundary values
crop_frame = frame[top_bound:bottom_bound, left_bound:right_bound] cropped_frame = frame[top_bound:bottom_bound, left_bound:right_bound]
crop_frame = np.mean(crop_frame, axis=2) # mean over 3rd dimension (RGB/color values) cropped_frame = np.mean(cropped_frame, axis=2) # mean over 3rd dimension (RGB/color values)
# mean over short or long side of the frame corresponding to x or y axis of picture # mean over short or long side of the frame corresponding to x or y axis of picture
frame_width = np.mean(crop_frame,axis=0) frame_width = np.mean(cropped_frame,axis=0)
frame_height = np.mean(crop_frame,axis=1) frame_height = np.mean(cropped_frame,axis=1)
# differences of color values lying next to each other --> derivation # differences of color values lying next to each other --> derivation
diff_width = np.diff(frame_width) diff_width = np.diff(frame_width)
@ -37,7 +64,7 @@ def crop_frame(frame, marker_positions):
x_width = np.arange(0, len(diff_width), 1) x_width = np.arange(0, len(diff_width), 1)
x_height = np.arange(0, len(diff_height), 1) x_height = np.arange(0, len(diff_height), 1)
return crop_frame, frame_width, frame_height, diff_width, diff_height, x_width, x_height return cropped_frame, frame_width, frame_height, diff_width, diff_height, x_width, x_height
def rotation_angle(): def rotation_angle():
pass pass

View File

@ -7,9 +7,10 @@ import numpy as np
import cv2 import cv2
import os import os
import sys import sys
import glob
from IPython import embed from IPython import embed
from etrack import MarkerTask, ImageMarker from calibration_functions import *
from calibration_functions import crop_frame, threshold_crossings, checkerboard_position, filter_data
class DistanceCalibration(): class DistanceCalibration():
@ -17,23 +18,6 @@ class DistanceCalibration():
def __init__(self, file_name, frame_number, x_0=154, y_0=1318, cam_dist=1.36, tank_width=1.35, tank_height=0.805, width_pixel=1900, height_pixel=200, def __init__(self, file_name, frame_number, x_0=154, y_0=1318, cam_dist=1.36, tank_width=1.35, tank_height=0.805, width_pixel=1900, height_pixel=200,
checkerboard_width=0.24, checkerboard_height=0.18, checkerboard_width_pixel=500, checkerboard_height_pixel=350) -> None: checkerboard_width=0.24, checkerboard_height=0.18, checkerboard_width_pixel=500, checkerboard_height_pixel=350) -> None:
super().__init__() super().__init__()
# aktualisieren
"""Calibration of the dimensions of the tank. Conversion of pixel into meter. Width refers to the "x-axis", height to the "y-axis" of the tank.
Args:
file_name (_type_): _description_
x_0 (int, optional): X-value of the "origin" of the tank. Defaults to 0.
y_0 (int, optional): Y-value of the "origin" of the tank. Defaults to 0.
cam_dist (int, optional): Distance of camera lense to tank floor. Defaults to 1.36.
width (int, optional): Width in meter from one lightened corner of the tank to the other. Defaults to 1.35.
height (int, optional): Height in meter from one lightened corner of the tank to the other. Defaults to 1.35.
width_pixel (int, optional): Width in pixel from one lightened corner of the tank to the other. Defaults to 1975.
height_pixel (int, optional): Height in pixel from one lightened corner of the tank to the other. Defaults to 1375.
rectangle_width (float, optional): Width of one black or corresponding white rectangle of the checkerboard. Defaults to 0.024.
rectangle_height (float, optional): Height of one black or corresponding white rectangle of the checkerboard. Defaults to 0.0225.
rectangle_count_width (int, optional): Number of black rectangles over the width of the whole checkerboard. Defaults to 9.
rectangle_count_height (int, optional): Number of black rectangles over the height of the whole checkerboard. Defaults to 7.
"""
self._file_name = file_name self._file_name = file_name
self._x_0 = x_0 self._x_0 = x_0
@ -50,24 +34,18 @@ class DistanceCalibration():
self._x_factor = tank_width / width_pixel # m/pix self._x_factor = tank_width / width_pixel # m/pix
self._y_factor = tank_height / height_pixel # m/pix self._y_factor = tank_height / height_pixel # m/pix
self.distance_calculation self.distance_factor_calculation
self.mark_crop_positions
# if needed include setter: @y_0.setter def y_0(self, value): self._y_0 = value
@property @property
def x_0(self): def x_0(self):
return self._x_0 return self._x_0
@x_0.setter
def x_0(self, value):
self._x_0 = value
@property @property
def y_0(self): def y_0(self):
return self._y_0 return self._y_0
@y_0.setter
def y_0(self, value):
self._y_0 = value
@property @property
def cam_dist(self): def cam_dist(self):
return self._cam_dist return self._cam_dist
@ -76,50 +54,26 @@ class DistanceCalibration():
def width(self): def width(self):
return self._width return self._width
@width.setter
def width(self, value):
self._width = value
@property @property
def height(self): def height(self):
return self._height return self._height
@height.setter
def height(self, value):
self._height = value
@property @property
def width_pix(self): def width_pix(self):
return self._width_pix return self._width_pix
@width_pix.setter
def width_pix(self, value):
self._width_pix = value
@property @property
def height_pix(self): def height_pix(self):
return self._height_pix return self._height_pix
@height_pix.setter
def height_pix(self, value):
self._height_pix_ = value
@property @property
def cb_width(self): def cb_width(self):
return self._cb_width return self._cb_width
@cb_width.setter
def cb_width(self, value):
self._cb_width = value
@property @property
def cb_height(self): def cb_height(self):
return self._cb_height return self._cb_height
@cb_height.setter
def cb_height(self, value):
self._cb_height = value
@property @property
def x_factor(self): def x_factor(self):
return self._x_factor return self._x_factor
@ -142,7 +96,7 @@ class DistanceCalibration():
def detect_checkerboard(self, filename, frame_number, marker_positions): def detect_checkerboard(self, filename, frame_number, marker_positions):
# load frame
if not os.path.exists(filename): if not os.path.exists(filename):
raise IOError("file %s does not exist!" % filename) raise IOError("file %s does not exist!" % filename)
video = cv2.VideoCapture() video = cv2.VideoCapture()
@ -151,25 +105,28 @@ class DistanceCalibration():
success = True success = True
frame = None frame = None
x_0 = self._x_0
y_0 = self._y_0
width_pix = self._width_pix
height_pix = self._height_pix
while success and frame_counter <= frame_number: # iterating until frame_counter == frame_number --> success (True) while success and frame_counter <= frame_number: # iterating until frame_counter == frame_number --> success (True)
print("Reading frame: %i" % frame_counter, end="\r") print("Reading frame: %i" % frame_counter, end="\r")
success, frame = video.read() success, frame = video.read()
frame_counter += 1 frame_counter += 1
marker_positions = np.load('marker_positions.npy', allow_pickle=True) # load saved numpy marker positions file marker_positions = np.load('marker_positions.npy', allow_pickle=True) # load saved numpy marker positions file
bottom_left_marker = marker_positions[0]['bottom left corner']
bottom_right_marker= marker_positions[0]['bottom right corner']
top_left_marker = marker_positions[0]['top left corner']
top_right_marker = marker_positions[0]['top right corner']
# care: y-axis is inverted, top values are low, bottom values are high # care: y-axis is inverted, top values are low, bottom values are high
croped_frame, frame_width, frame_height, diff_width, diff_height, _, _ = crop_frame(frame, marker_positions) # crop frame to given marker positions cropped_frame, frame_width, frame_height, diff_width, diff_height, _, _ = crop_frame(frame, marker_positions) # crop frame to given marker positions
bottom_left_x = 0
bottom_left_y = np.shape(cropped_frame)[0]
bottom_right_x = np.shape(cropped_frame)[1]
bottom_right_y = np.shape(cropped_frame)[0]
top_left_x = 0
top_left_y = 0
top_right_x = np.shape(cropped_frame)[1]
top_right_y = 0
cropped_marker_positions = [{'bottom left corner': (bottom_left_x, bottom_left_y), 'top left corner': (top_left_x, top_left_y),
'top right corner': (top_right_x, top_right_y), 'bottom right corner': (bottom_right_x, bottom_right_y)}]
thresh_fact = 7 # factor by which the min/max is divided to calculate the upper and lower thresholds thresh_fact = 7 # factor by which the min/max is divided to calculate the upper and lower thresholds
@ -188,49 +145,60 @@ class DistanceCalibration():
# position of checkerboard in width # position of checkerboard in width
print('width..') print('width..')
width_position, left_width_position, right_width_position = checkerboard_position(lci_width, uci_width) width_position, left_width_position, right_width_position = checkerboard_position(lci_width, uci_width)
# position of checkerboard in height # position of checkerboard in height
print('height..') print('height..')
height_position, left_height_position, right_height_position = checkerboard_position(lci_height, uci_height) # left height refers to top, right height to bottom height_position, left_height_position, right_height_position = checkerboard_position(lci_height, uci_height) # left height refers to top, right height to bottom
if width_position == 'left' and height_position == 'left':
checkerboard_position_tank = 'top left'
elif width_position == 'left' and height_position == 'right':
checkerboard_position_tank = 'bottom left'
elif width_position == 'right' and height_position == 'right':
checkerboard_position_tank = 'bottom right'
elif width_position == 'right' and height_position == 'left':
checkerboard_position_tank = 'top right'
else:
checkerboard_position_tank = 'middle'
print(checkerboard_position_tank)
# final corner positions of checkerboard # final corner positions of checkerboard
top_left = np.array([left_width_position, left_height_position]) checkerboard_marker_positions = [{'bottom left corner': (left_width_position, right_height_position), 'top left corner': (left_width_position, left_height_position),
top_right = np.array([right_width_position, left_height_position]) 'top right corner': (right_width_position, left_height_position), 'bottom right corner': (right_width_position, right_height_position)}]
bottom_left = np.array([left_width_position, right_height_position])
bottom_right = np.array([right_width_position, right_height_position])
print(top_left, top_right, bottom_left, bottom_right) print(checkerboard_marker_positions)
# fig, ax = plt.subplots() checkerboard_top_right, checkerboard_top_left, checkerboard_bottom_right, checkerboard_bottom_left = assign_checkerboard_positions(checkerboard_marker_positions)
# ax.imshow(croped_frame)
# for p in top_left, top_right, bottom_left, bottom_right: fig, ax = plt.subplots()
# ax.scatter(p[0], p[1]) ax.imshow(cropped_frame)
# plt.show() for p in checkerboard_top_left, checkerboard_top_right, checkerboard_bottom_left, checkerboard_bottom_right:
ax.scatter(p[0], p[1])
ax.scatter(bottom_left_x, bottom_left_y)
ax.scatter(bottom_right_x, bottom_right_y)
ax.scatter(top_left_x, top_left_y)
ax.scatter(top_right_x, top_right_y)
plt.show()
# embed()
# quit()
return top_left, top_right, bottom_left, bottom_right return checkerboard_marker_positions, cropped_marker_positions, checkerboard_position_tank
def distance_calculation(self, top_left, top_right, bottom_left, bottom_right, marker_positions): def distance_factor_calculation(self, checkerboard_marker_positions, marker_positions):
checkerboard_top_right, checkerboard_top_left, checkerboard_bottom_right, checkerboard_bottom_left = assign_checkerboard_positions(checkerboard_marker_positions)
checkerboard_width = 0.24 checkerboard_width = 0.24
checkerboard_height = 0.18 checkerboard_height = 0.18
checkerboard_width_pixel = top_right[0] - top_left[0] checkerboard_width_pixel = checkerboard_top_right[0] - checkerboard_top_left[0]
checkerboard_height_pixel = bottom_right[1] - top_right[1] checkerboard_height_pixel = checkerboard_bottom_right[1] - checkerboard_top_right[1]
x_factor = checkerboard_width / checkerboard_width_pixel x_factor = checkerboard_width / checkerboard_width_pixel
y_factor = checkerboard_height / checkerboard_height_pixel y_factor = checkerboard_height / checkerboard_height_pixel
bottom_left_x = marker_positions[0]['bottom left corner'][0] bottom_left_x, bottom_left_y, bottom_right_x, bottom_right_y, top_left_x, top_left_y, top_right_x, top_right_y = assign_marker_positions(marker_positions)
bottom_left_y = marker_positions[0]['bottom left corner'][1]
bottom_right_x = marker_positions[0]['bottom right corner'][0]
bottom_right_y = marker_positions[0]['bottom right corner'][1]
top_left_x = marker_positions[0]['top left corner'][0]
top_left_y = marker_positions[0]['top left corner'][1]
top_right_x = marker_positions[0]['top right corner'][0]
top_right_y = marker_positions[0]['top right corner'][1]
tank_width_pixel = np.mean([bottom_right_x - bottom_left_x, top_right_x - top_left_x]) tank_width_pixel = np.mean([bottom_right_x - bottom_left_x, top_right_x - top_left_x])
tank_height_pixel = np.mean([bottom_left_y - top_left_y, bottom_right_y - top_right_y]) tank_height_pixel = np.mean([bottom_left_y - top_left_y, bottom_right_y - top_right_y])
@ -240,22 +208,50 @@ class DistanceCalibration():
print(tank_width, tank_height) print(tank_width, tank_height)
embed() return x_factor, y_factor
quit()
def distance_factor_interpolation(x_factors, y_factors):
pass pass
if __name__ == "__main__": if __name__ == "__main__":
file_name = "/home/efish/etrack/videos/2022.03.28_3.mp4"
all_x_factor = []
all_y_factor = []
all_checkerboard_position_tank = []
for file_name in glob.glob("/home/efish/etrack/videos/*"):
# file_name = "/home/efish/etrack/videos/2022.03.28_4.mp4"
frame_number = 10 frame_number = 10
dc = DistanceCalibration(file_name=file_name, frame_number=frame_number) dc = DistanceCalibration(file_name=file_name, frame_number=frame_number)
# marker_positions = dc.mark_crop_positions() dc.mark_crop_positions()
top_left, top_right, bottom_left, bottom_right = dc.detect_checkerboard(file_name, frame_number=frame_number, marker_positions=np.load('marker_positions.npy', allow_pickle=True)) checkerboard_marker_positions, cropped_marker_positions, checkerboard_position_tank = dc.detect_checkerboard(file_name, frame_number=frame_number, marker_positions=np.load('marker_positions.npy', allow_pickle=True))
x_factor, y_factor = dc.distance_factor_calculation(checkerboard_marker_positions, marker_positions=cropped_marker_positions)
all_x_factor.append(x_factor)
all_y_factor.append(y_factor)
all_checkerboard_position_tank.append(checkerboard_position_tank)
x_factors = np.load('x_factors.npy')
y_factors = np.load('y_factors.npy')
all_checkerboard_position_tank = np.load('all_checkerboard_position_tank.npy')
embed()
quit()
dc.distance_calculation(top_left, top_right, bottom_left, bottom_right, marker_positions = np.load('marker_positions.npy', allow_pickle=True)) # next up: distance calculation with angle
# is this needed or are current videos enough?:
# laying checkerboard at position directly above and below / left and right to centered checkerboard near edge of tank
# calculating x and y factor for centered checkerboard, then for the ones at the edge
# --> afterwards interpolate between them to have continuous factors for whole tank
# maybe smaller object in tank to have more accurate factor
# make function to refine checkerboard detection at edges of tank by saying if no lower color values appears near edge --> checkerboard position then == corner of tank?
#
# mark_crop_positions why failing plot at end? # mark_crop_positions why failing plot at end?
# with rectangles of checkerboard? # with rectangles of checkerboard?

View File

@ -65,7 +65,7 @@ class ImageMarker:
self._fig.gca().set_title("All set and done!\n Window will close in 2s") self._fig.gca().set_title("All set and done!\n Window will close in 2s")
self._fig.canvas.draw() self._fig.canvas.draw()
plt.pause(2.0) plt.pause(2.0)
plt.close() plt.close() #self._fig.gca().imshow(frame))
return [t.marker_positions for t in self._tasks] return [t.marker_positions for t in self._tasks]
def _key_press_event(self, event): def _key_press_event(self, event):