From 8199fe4c7f17ab6a4e6bd5a6ee7d1013beddcb8d Mon Sep 17 00:00:00 2001
From: Xaver Roos <xaver.roos@gmail.com>
Date: Mon, 28 Mar 2022 15:30:20 +0200
Subject: [PATCH] [distance_calibration] new python file containing crop and
 mark_checkerboard

---
 README.md                      |   2 +-
 etrack/distance_calibration.py | 185 +++++++++++++++++++++++++++++++++
 etrack/image_marker.py         |  42 ++++++--
 3 files changed, 217 insertions(+), 12 deletions(-)
 create mode 100644 etrack/distance_calibration.py

diff --git a/README.md b/README.md
index efed3c4..8e4dcec 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ If  you leave away the ```--user``` the package will be installed system-wide.
 
 ## TrackingResults
 
-Is a class that wraps around the *.h5 files written by DeppLabCut
+Is a class that wraps around the *.h5 files written by DeepLabCut
 
 ## ImageMarker
 
diff --git a/etrack/distance_calibration.py b/etrack/distance_calibration.py
new file mode 100644
index 0000000..c859b9e
--- /dev/null
+++ b/etrack/distance_calibration.py
@@ -0,0 +1,185 @@
+from cv2 import calibrationMatrixValues
+import matplotlib.pyplot as plt 
+import numpy as np
+import cv2
+import os
+import sys
+from IPython import embed
+
+
+class DistanceCalibration:
+
+    def __init__(self, file_name, x_0=95, y_0=185, cam_dist=1.36, width=1.35, height=0.805, width_pixel=1975, height_pixel=1375, checkerboard_width=0.24, checkerboard_height=0.18, 
+    checkerboard_width_pixel=500, checkerboard_height_pixel=350, rectangle_width=0.024, rectangle_height=0.0225, rectangle_width_pixel=100, rectangle_height_pixel=90, 
+    rectangle_count_width=9, rectangle_count_height=7) -> None:
+        # 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.
+            heigth (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): Heigth 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._x_0 = x_0
+        self._y_0 = y_0
+        self._width_pix = width_pixel
+        self._height_pix = height_pixel
+        self._cam_dist = cam_dist
+        self._width = width
+        self._height = height
+        self._cb_width = checkerboard_width
+        self._cb_height = checkerboard_height
+        self._cb_width_pix = checkerboard_width_pixel
+        self._cb_height_pix = checkerboard_height_pixel
+        self._rect_width = rectangle_width
+        self._rect_height = rectangle_height
+        self._x_factor = self.width / self.width_pix   # m/pix
+        self._y_factor = self.height / self.height_pix # m/pix
+
+        # properties
+    @property
+    def x_0(self):
+        return self._x_0
+
+    @property
+    def y_0(self):
+        return self._y_0
+
+    @property
+    def cam_dist(self):
+        return self._cam_dist
+    
+    @property
+    def width(self):
+        return self._width
+
+    @property
+    def height(self):
+        return self._height
+    
+    @property
+    def width_pix(self):
+        return self._width_pix
+
+    @property
+    def height_pix(self):
+        return self._height_pix
+    
+    @property
+    def x_factor(self):
+        return self._x_factor
+
+    @property
+    def y_factor(self):
+        return self._y_factor
+
+
+    def crop_movie():
+        if not os.path.exists(filename):
+            raise IOError("file %s does not exist!" % filename)
+        video = cv2.VideoCapture()
+        video.open(filename)
+        frame_counter = 0
+        success = True
+        frame = None
+        while success and frame_counter <= frame_number:    # iterating until frame_counter == frame_number --> success (True)
+            print("Reading frame: %i" % frame_counter, end="\r")
+            success, frame = video.read()
+            frame_counter += 1
+        if success:
+           self._fig.gca().imshow(frame)    # plot wanted frame of video
+        else:
+           print("Could not read frame number %i either failed to open movie or beyond maximum frame number!" % frame_number)
+           return []
+        plt.ion()   # turn on interactive mode
+        plt.show(block=False)   # block=False allows to continue interact in terminal while the figure is open
+        
+        self._task_index = -1
+        if len(self._tasks) > 0:
+            self._next_task()
+        
+        while not self._tasks_done:
+            plt.pause(0.250)
+            if self._interrupt:
+                return []
+
+        self._fig.gca().set_title("All set and done!\n Window will close in 2s")
+        self._fig.canvas.draw()
+        plt.pause(2.0)
+        plt.close()
+        return [t.marker_positions for t in self._tasks]
+
+
+    def mark_checkerboard(self, filename, frame_number=10):
+        if not os.path.exists(filename):
+            raise IOError("file %s does not exist!" % filename)
+        video = cv2.VideoCapture()
+        video.open(filename)
+        frame_counter = 0
+        success = True
+        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)
+            print("Reading frame: %i" % frame_counter, end="\r")
+            success, frame = video.read()
+            frame_counter += 1
+        width_mean = np.mean(frame,axis=1)
+        crop_width_mean = width_mean[x_0:width_pix]
+        
+        height_mean = np.mean(frame,axis=0)
+        crop_height_mean = height_mean[y_0:height_pix]
+# HELLO, here you at
+
+        embed()
+        quit()
+        if success:
+           self._fig.gca().imshow(frame)    # plot wanted frame of video
+        else:
+           print("Could not read frame number %i either failed to open movie or beyond maximum frame number!" % frame_number)
+           return []
+        plt.ion()   # turn on interactive mode
+        plt.show(block=False)   # block=False allows to continue interact in terminal while the figure is open
+        
+        self._task_index = -1
+        if len(self._tasks) > 0:
+            self._next_task()
+        
+        while not self._tasks_done:
+            plt.pause(0.250)
+            if self._interrupt:
+                return []
+
+        self._fig.gca().set_title("All set and done!\n Window will close in 2s")
+        self._fig.canvas.draw()
+        plt.pause(2.0)
+        plt.close()
+        return [t.marker_positions for t in self._tasks]    
+        
+
+if __name__ == "__main__":    
+    vid2 = "/home/efish/etrack/videos/2022.03.28_3.mp4"
+    calibration_task = DistanceCalibration(vid2)
+    dc = DistanceCalibration(calibration_task)
+    dc.mark_checkerboard(vid2, 10)
+
+    # print(sys.argv[0])
+    # print (sys.argv[1])
+    # vid1 = sys.argv[1]
+    
+    embed()
\ No newline at end of file
diff --git a/etrack/image_marker.py b/etrack/image_marker.py
index 8ad7bad..82ca605 100644
--- a/etrack/image_marker.py
+++ b/etrack/image_marker.py
@@ -1,4 +1,6 @@
+from cv2 import calibrationMatrixValues
 import matplotlib.pyplot as plt 
+import numpy as np
 import cv2
 import os
 import sys
@@ -19,6 +21,19 @@ class ImageMarker:
         self._fig.canvas.mpl_connect('key_press_event', self._key_press_event)
     
     def mark_movie(self, filename, frame_number=0):
+        """ Interactive GUI to mark the corners of the tank. A specific frame of the video can be chosen. Returns marker positions.
+
+        Args:
+            filename: Videofile
+            frame_number (int, optional): Number of a frame in the videofile. Defaults to 0.
+
+        Raises:
+            IOError: File does not exist.
+
+        Returns:
+            marker_positions: Marker positions of tank corners.
+        """
+        
         if not os.path.exists(filename):
             raise IOError("file %s does not exist!" % filename)
         video = cv2.VideoCapture()
@@ -26,17 +41,17 @@ class ImageMarker:
         frame_counter = 0
         success = True
         frame = None
-        while success and frame_counter <= frame_number:
+        while success and frame_counter <= frame_number:    # iterating until frame_counter == frame_number --> success (True)
             print("Reading frame: %i" % frame_counter, end="\r")
             success, frame = video.read()
             frame_counter += 1
         if success:
-           self._fig.gca().imshow(frame)
+           self._fig.gca().imshow(frame)    # plot wanted frame of video
         else:
            print("Could not read frame number %i either failed to open movie or beyond maximum frame number!" % frame_number)
            return []
-        plt.ion()
-        plt.show(block=False)
+        plt.ion()   # turn on interactive mode
+        plt.show(block=False)   # block=False allows to continue interact in terminal while the figure is open
         
         self._task_index = -1
         if len(self._tasks) > 0:
@@ -50,6 +65,7 @@ class ImageMarker:
         self._fig.gca().set_title("All set and done!\n Window will close in 2s")
         self._fig.canvas.draw()
         plt.pause(2.0)
+        plt.close()
         return [t.marker_positions for t in self._tasks]
 
     def _key_press_event(self, event):
@@ -141,11 +157,15 @@ class MarkerTask():
 if __name__ == "__main__":
     tank_task = MarkerTask("tank limits", ["bottom left corner", "top left corner", "top right corner", "bottom right corner"], "Mark tank corners")
     feeder_task = MarkerTask("Feeder positions", list(map(str, range(1, 2))), "Mark feeder positions")
-    tasks = [tank_task, feeder_task]
+    tasks = [tank_task] # feeder_task]
     im = ImageMarker(tasks)
-    # vid1 = "2020.12.11_lepto48DLC_resnet50_boldnessDec11shuffle1_200000_labeled.mp4"
-    print(sys.argv[0])
-    print (sys.argv[1])
-    vid1 = sys.argv[1]
-    marker_positions = im.mark_movie(vid1, 10)
-    print(marker_positions)
\ No newline at end of file
+
+    vid1 = "/home/efish/efish_tracking/efish_tracking3-Xaver-2022-03-21/videos/2022.01.12_3DLC_resnet50_efish_tracking3Mar21shuffle1_300000_labeled.mp4"
+    marker_positions = im.mark_movie(vid1, 100)
+    print(marker_positions)
+    
+    # print(sys.argv[0])
+    # print (sys.argv[1])
+    # vid1 = sys.argv[1]
+    
+    embed()
\ No newline at end of file