Skip to content

Commit

Permalink
Merge pull request #34 from ThijsIllimited/D-DIC-public
Browse files Browse the repository at this point in the history
Directional-DIC implementation
  • Loading branch information
ThijsIllimited authored Jul 23, 2024
2 parents 4d35282 + 00f6829 commit 7bd1948
Show file tree
Hide file tree
Showing 4 changed files with 1,026 additions and 2 deletions.
259 changes: 259 additions & 0 deletions Showcas_LK_1D.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"sys.path.insert(0, os.path.realpath('__file__'))\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import pickle\n",
"import pyidi"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load the video"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"filename = 'data/data_synthetic.cih'\n",
"video = pyidi.pyIDI(filename)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Video info can easily be accessed"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"video.info"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt\n",
"import matplotlib.animation as animation\n",
"\n",
"def play_video(frame_range = None, interval=30, points = None, ij_counter = (0.65, 0.05)):\n",
" \n",
" \"\"\"\n",
" Plays the video from the given video object.\n",
" Args:\n",
" frame_range (range object): The range of frames to play.\n",
" interval (int): The interval between frames in milliseconds.\n",
" points (ndarray): Optional tracked points to plot on the video.\n",
" ij_counter (tuple): The position of the frame counter.\n",
" \"\"\"\n",
" if frame_range is None:\n",
" frame_range = range(0, video.info['Total Frame'])\n",
" fig, ax = plt.subplots()\n",
" im = ax.imshow(video.mraw[frame_range[0]], cmap='gray')\n",
" text = ax.text(ij_counter[0], ij_counter[1], '', transform=ax.transAxes, color='black', ha='right', va='bottom')\n",
"\n",
" if points is not None:\n",
" pts = ax.plot(points[:,0,1], points[:,0,0], 'r.')\n",
"\n",
" def update(i):\n",
" im.set_data(video.mraw[i])\n",
" text.set_text(f'Frame {i}')\n",
" if points is not None:\n",
" pts[0].set_data(points[:,i,1], points[:,i,0])\n",
" return im, text\n",
"\n",
" ani = animation.FuncAnimation(fig, update, frames=frame_range, interval=interval)\n",
" plt.show()\n",
" return ani\n",
"\n",
"ani = play_video(range(1, video.info['Total Frame']))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will first use the `Lucas Kanade` method as a reference"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt\n",
"tol = 1e-8\n",
"roi_size = (5,5)\n",
"video = pyidi.pyIDI(filename)\n",
"video.set_method('lk')\n",
"video.method.configure(reference_image = (0,100), resume_analysis = False, tol=tol, roi_size=roi_size)\n",
"reference_image = video.method._set_reference_image(video, video.method.reference_image)\n",
"Gi, Gj = np.gradient(reference_image)\n",
"G = np.sqrt(Gi**2 + Gj**2)\n",
"highest_points = np.argpartition(G.flatten(), -10)[-10:]\n",
"arguments = np.unravel_index(highest_points, G.shape)\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.scatter(arguments[1], arguments[0])\n",
"ax.imshow(reference_image, cmap='gray')\n",
"plt.show()\n",
"points2d = np.array(arguments).T\n",
"video.set_points(points2d)\n",
"video.show_points()\n",
"displacementes_2d = video.get_displacements(processes=1, autosave=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we will first use the `Directional - Lucas Kanade` method"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt\n",
"video = pyidi.pyIDI(filename)\n",
"video.set_method('lk_1D')\n",
"'''\n",
" Here we define the direction of the motion\n",
" Note the coordinates are in the form (i,j), not (x,y), in correspondence with the numpy array indexing. (i,j) = (-y,x)\n",
" Note that in the example the norm of dij is not 1! This will automatically be corrected. \n",
"'''\n",
"dij = (0.5, 0.5) \n",
"video.method.configure(reference_image = (0,100), dij=dij, resume_analysis = False, tol=tol,roi_size=roi_size)\n",
"reference_image = video.method._set_reference_image(video, video.method.reference_image)\n",
"Gi, Gj = np.gradient(reference_image)\n",
"G = np.sqrt(Gi**2 + Gj**2)\n",
"highest_points = np.argpartition(G.flatten(), -10)[-10:]\n",
"arguments = np.unravel_index(highest_points, G.shape)\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.scatter(arguments[1], arguments[0])\n",
"ax.imshow(reference_image, cmap='gray')\n",
"plt.show()\n",
"points1d = np.array(arguments).T\n",
"video.set_points(points1d)\n",
"video.show_points()\n",
"video.method.dij"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"displacements = video.get_displacements(processes=1, autosave=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An existing analysis can also be loaded without computation and setting the arguments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"t_vec = np.arange(0, len(displacements[0])) * video.info['Record Rate(fps)']\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.set_xlabel('Time (s)')\n",
"ax.set_ylabel('Displacement (pixels)')\n",
"for point in displacements:\n",
" # ax.plot(t_vec, point[:,0],'b:')\n",
" # ax.plot(t_vec, point[:,1],'b--')\n",
" ax.plot(t_vec, point[:,0]*dij[0] + point[:,1]*dij[1],'b', label=f'1D, d = {dij}')\n",
"for point in displacementes_2d:\n",
" ax.plot(t_vec, point[:,0]*dij[0] + point[:,1]*dij[1], 'r', label=f'2D, d = {dij}')\n",
"ax.plot(t_vec, displacementes_2d[0, :,0], 'r:', label = '2D - x', alpha=0.5)\n",
"ax.plot(t_vec, displacementes_2d[0, :,1], 'r--', label = '2D - y', alpha=0.5)\n",
"# ax.plot(t_vec, np.arctan2(displacementes_2d[0, :,1], displacementes_2d[0, :,0]), 'r--', label = 'direction', alpha=0.5)\n",
"handles, labels = ax.get_legend_handles_labels()\n",
"by_label = dict(zip(labels, handles))\n",
"ax.legend(by_label.values(), by_label.keys())\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib qt\n",
"td2d = displacementes_2d + points2d.reshape(len(points2d),1,2)\n",
"td1d = displacements + points1d.reshape(len(points1d),1,2)\n",
"ani = play_video(range(1,video.reader.N), points=td1d)"
]
}
],
"metadata": {
"hide_input": false,
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.5"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
3 changes: 2 additions & 1 deletion pyidi/methods/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
from ._gradient_based_optical_flow import GradientBasedOpticalFlow
from ._lucas_kanade_scipy import LucasKanadeSc
from ._lucas_kanade import LucasKanade
from ._lucas_kanade_scipy2 import LucasKanadeSc2
from ._lucas_kanade_scipy2 import LucasKanadeSc2
from ._directional_lucas_kanade import LucasKanade_1D
Loading

0 comments on commit 7bd1948

Please sign in to comment.