widzenie-komputerowe-MP/wko-07.ipynb

989 lines
2.3 MiB
Plaintext
Raw Permalink Normal View History

2023-01-23 12:24:42 +01:00
{
"cells": [
{
"cell_type": "markdown",
"id": "73e26798",
"metadata": {},
"source": [
"![Logo 1](img/aitech-logotyp-1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Widzenie komputerowe </h1>\n",
"<h2> 07. <i>Analiza wideo: przepływ optyczny, śledzenie obiektów</i> [laboratoria]</h2> \n",
"<h3>Andrzej Wójtowicz (2021)</h3>\n",
"</div>\n",
"\n",
"![Logo 2](img/aitech-logotyp-2.jpg)"
]
},
{
"cell_type": "markdown",
"id": "f124f5cd",
"metadata": {},
"source": [
"W poniższych materiałach zobaczymy w jaki sposób możemy przy pomocy przepływu optycznego dokonać stabilizacji obrazu oraz w jaki sposób śledzić obiekty znajdujące się na filmie.\n",
"\n",
"Na początku załadujmy niezbędne biblioteki."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "ed69629c",
"metadata": {},
"outputs": [],
"source": [
"import cv2 as cv\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"import IPython.display"
]
},
{
"cell_type": "markdown",
"id": "f9ef8d67",
"metadata": {},
"source": [
"# Przepływ optyczny\n",
"\n",
"Naszym celem będzie znalezienie na poniższym filmie punktów kluczowych, które pozwolą nam w jakiś sposób sprawdzić jak przemieszcza się rowerzystka:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "1629fc29",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<video src=\"vid/bike.mp4\" controls width=\"800\" >\n",
" Your browser does not support the <code>video</code> element.\n",
" </video>"
],
"text/plain": [
"<IPython.core.display.Video object>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"IPython.display.Video(\"vid/bike.mp4\", width=800)"
]
},
{
"cell_type": "markdown",
"id": "aa176c9a",
"metadata": {},
"source": [
"Załadujmy film:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2463bd1d",
"metadata": {},
"outputs": [],
"source": [
"bike = cv.VideoCapture(\"vid/bike.mp4\")"
]
},
{
"cell_type": "markdown",
"id": "dde041a3",
"metadata": {},
"source": [
"Przy pomocy algorytmu Shi-Tomasi (rozwinięcie metody Harrisa) możemy znaleźć narożniki, które dobrze nadają się do śledzenia. W OpenCV algorytm jest zaimplementowany w funkcji [`cv.goodFeaturesToTrack()`](https://docs.opencv.org/4.5.3/dd/d1a/group__imgproc__feature.html#ga1d6bb77486c8f92d79c8793ad995d541):"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "36492aa6",
"metadata": {},
"outputs": [],
"source": [
"corners_num = 100\n",
"corners_colors = np.random.randint(0, 255, (corners_num, 3))\n",
"\n",
"_, frame_1 = bike.read()\n",
"frame_1_gray = cv.cvtColor(frame_1, cv.COLOR_BGR2GRAY)\n",
"keypoints_1 = cv.goodFeaturesToTrack(\n",
" frame_1_gray, mask=None, maxCorners=corners_num,\n",
" qualityLevel=0.3, minDistance=7, blockSize=7)\n",
"\n",
"mask = np.zeros_like(frame_1)\n",
"count = 0"
]
},
{
"cell_type": "markdown",
"id": "028dded7",
"metadata": {},
"source": [
"Aby sprawdzić w jaki sposób punkty przemieszczają się pomiędzy kolejnymi klatkami filmu, wykorzystamy algorytm LucasaKanade, który jest zaimplementowany w funkcji [`cv.calcOpticalFlowPyrLK()`](https://docs.opencv.org/4.5.3/dc/d6b/group__video__track.html#ga473e4b886d0bcc6b65831eb88ed93323):"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "14b62820",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAbUAAAD/CAYAAAB2HkhjAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9+bNly3XfiX0ycw9nPufOU81z1ZvwBgwEIYAgKYIUKYpSSGqprQgruh0dbod/d//uv6Aj7B+ssNVhSVa03d2W1N0kRYokQIAE3og3V72a687zmc+eM9M/7HPuPXeoeg8kBRFwLaDePefsvXPamWv45lorhbWW5/ScntNzek7P6eeB5H/qBjyn5/ScntNzek5/VfRcqD2n5/ScntNz+rmh50LtOT2n5/ScntPPDT0Xas/pOT2n5/Scfm7ouVB7Ts/pOT2n5/RzQ8+F2nN6Ts/pOT2nnxv6qQs1IcSvCyHuCiEeCCH+m592/c/pOT2n5/Scfn5J/DTj1IQQCrgH/E1gDXgH+MfW2ts/tUY8p+f0nJ7Tc/q5pZ+2pfYV4IG19pG1NgH+e+Dv/JTb8Jye03N6Ts/p55R+2kJtCVgd+742/O05Pafn9Jye03P6S5Pzn7oBx0kI8V8B/xVAoVR+/fyVG8AXgUjFF7zvJyA7KnfsB/Hse460wFoQxx/4SzfoC956rF4xenb0+3hZp3VKjH20YMEYi8UipcRaizEGIQVKirw+Cxabq0oWBIIsy0iSGCEExUIRKwTGGCwWRzkYrTHW4DjuM7tnsQhE/leIw6G1h9ee9uTT+/lXS6c1/+js+em15bDO0+mptdu/2lUksAw6HXqdJhKDsQZrTV6PAGvzCsXws0FRqjaYmJk9tb2W4zP4i6x78RNzh899Ozafdcd+/NxnP/+Ow7ue+fPTOnS4KIY3WLAGjMZiMMaQZRoBKCkwo3UMxEmM4ygybRBC4rkuVmvSNCXTCdZahJQIcl4glcJ1Xay1OEqhHBdjQWeGOIpRSoE1DPpdtE7ydgAWQbFSIzaGQqFMvT6ByTQCi85SojBEG4PRGRiD4yi00QghEUIw6HeJo2DPWjtz2jD9tIXaOnB27PuZ4W8HZK39Z8A/A7jxyhv2//H7b2GtHb2eU0nAaFX8pRekYGzK2fFvdkwwjLeX4eTO79PGkGmDFAJhBEpIUKcIw79Ai4zRfKGlaQUgiaIYay3FYgHIJ64dCtmje6kCa0DIkSAz+W8MBZDNaDWbVCs1/FIpf9akbG1vYWzKZKNO2asQhAmZ0Fih6Xb6zE7PEUUBb775Q+anpplfOEN9cgohJe1um7mZOba3tqnXa/h+gSTVOJ4z1usxZWHYXmstQg2FGjDoD/B9H9d1jw6BHZ8x46zwPx4d14FOmS55u8TwxuOKx7GyvhgDPKiZ49vjlmNVjM1ncWRKmkMdxpws5/Nqzv+dLtJ9A7/7r/87fvyn/ys1T5OZhCxLiKKQzBq0GVaoTV5CcYZrX/91/sF/8b8H10MO2ymHxRtx2HYDiIMOmtMbKIZ9FoIv7D9gj/GB024ZCmOLGI7x4dt65nOG/D084yZr7alttXYkySxCyGNzHCBn+haLsAZ0TNzf49GdD7n78ft4rqE+0aAXBhSUolzy6fUDsjjD2pjW/hau61AtlBDCok1Ms9mk3ekTJwmu65FpkNpQr9fR2qBQuIUCsuwzf+YKM4tn8VSVB589ROuM+ck6P37nu2ytf0Y66GCtIUEhps/w2q/8Br/2t/4Bnd0ucS+g19phbfUxWaKZnV9kfmYeEotC0e41ibM+Lprf/5//Be+/9b3lp43fT1uovQNcFUJcJBdm/wj4z7/Ig583WUb0VyHUjnw5xvyfVsNoEhpjaLValIolPOUhHPKVKE+2/4sbcV+8V+PNFULQbrdxXQchDAKBdJwTXEvrjGAQUqlW8jYZg7ECbSy9fhtHCcLBgFKxjM4SpIQ4HdBqbbH+5BEz0zNcv/EimbYkOuGDj95lbnYWT2Vobem29rFJwrVrt3LtTUDYH9B1O5SLJRzHI45TOv0uk5MTSKlygSDG26iRcrhorcUYi8k01toDgXaSEQy/jzGdsdH5vJH8HNPr5PPiOGsXx++zI92LcbH1tLYIxBHJaIcM/KStfQxNOPj5WAfGp+/B52OM8dg9Qgisefb8G6pJpwyXRShFpVKjXm9QIKA/SJBS5u/YHLW1/EIBWSrRaEx8scUxfK9i7L/jLTrtvqfRkVX+Rc06AWKkbJ0GgJxWjDjtyrP7enCnOPryxIn5ld8tLNgsZvvRXT569wckSZMs6VBwy3Q6HZJI0w8HbGcBwhjiMCAYdFhcmqPeqBIOEuIsYXtvgySKCAYBWRqTOS6VSh3flZhkgO97oKHoeSDLuKJK0BfEIubFl15hfXWZ9fVHKCmYnJwidgX9QZ80NWRRwLnZWTbufsq9Tz9iZ2uNWr1KuTHFuUsXiOKMleYqJa+EspLOoEnRcQgHPeI4feZ4/VSFmrU2E0L8H4E/ABTwz621n37ec+ILcn/L0U3Ccd3tNKF4mvWXa9uH2uyJ9fEMjS/LMtI0pd/rogQIzyJEAWHEUGEUCCkQclxe2lP6N76qxljXsUk83o788+E1ARQKHpOTDdrtJr7v4ToOJdfF2KMsQEpJajLWN9eoFD1810FYyfbeDlonCK0ZDCIqFZ9eP8X3HOIkoLW3STzo0sGys7GO9Fy0Tei0tvBsSFlmbG7tQhowPXWefr+HiiMc5SCMRScJlXoNg0Yqi84ieu0WvlekUq5ghl1K0oTtrW2mpqbwCz69bo9KuUSn02ViYgLI38lIAR4ZQ3aIUZ42ez5vStmnWVHPhEiPaeCncrSxsT9ghCcn2mnFHGe2I8juZB3PoLEyDrt4bIxGzNOO5uhpZR61I5/K1C1cunKZj38ksdqQ6ZQ4jjDa4DoOSRyjhEQqied7aAnFYgFHOWRj5Y7mwol6hi9cjOsgw7V2vK3HOn2SRtbqFwBWxE+ADJ0QmEfa88WeHe+3OHIFxtWcEU+xxuIrF2kE3W7C/MJlhPC4ev0FyoUSyWCP5cefsLX2mErR4cziDF7RYX1jg0EvpFypMOgnZFrgeHUKJcFkY5KZ6Sn6rT2kK2kHEao0QWn2Mo3GGZRbY3p6lkrZIxp0SKM+aysPSMIWc9MT2EqBh/cfILTBiSIevP0jXNdnZ2sFScrj5QDrFfnoXYckjHGEy6Vr15mbXcCmGa0oQScRAv3MMfup76lZa38P+L3/GGWPCwdrj2pm4tj1sRufPq+EPSYmnk2tdotWu8Ug6AIZoeMzNTmLJF+0IBBK5JCKkDkTPt6mccjzmKYtDqBDOG01WGAwGOAXfHzHBSEo+B62UmZjY51KpYKUCt/3Dxa9tQJjM1xfsf7gEYPWDhXfZ2Zmjq3tbaTQYAzFQpn2bkYYh6yvr1Op1HCkw9zcPFIoHtz/jNffeJVur4tPxsbD23TW7mON5PKFW5CldFt7CNfn8uUrVOs1giCk2d5lZ2eDSqVEEidov4Jbn0Fg0JlGW0MQh3R7HaZnJuh02niOQzgYkIQBanLy0CAaDlsUBGRpiue5+IXiUYPppK7wDPpJ7f6j7/JU0FMcvfOE0BBHZ5wd+3uaBpbvM44/ascvn9YCEPZIeYei9lglR6TvKWMx/shTh0pTrZYpFAvE7T2EtDiOg+MrlOOgTYoUAqNzaC6KYra3NrGZRjnOYfXisCrBMSZvj471MXF7apNPkj0xXl/cljp6z2lDcaS9Y8rX55V8YuSPSG977I78c7735WJkEeM3ePXrr3DhwmVc16PoKzZX7vJo+S5xGuBXykxWKuzv77D6cIUkTokzaPbbWGeKl177ChfOX4YsRdkEnbQZTGzT6rfoOBHf+q1/zOLidRQFsjhFxz363U2CwToOPUqeJegO2N7qUZASX7ikRuM6kt21x7zxxlc5O/Uiu1sb9P0BvSAgjBJMEKNcS293l5LyMbFmb2cPrVPifvzMMftr5yjyV0lfdCJ+vvH/+RMPIUjSmHZ3l0yHDLo7SONSLZWwFlzHRQiF8hysFIBEOKPPp7XmNAtjuOz
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"while True:\n",
" _, frame_2 = bike.read()\n",
" frame_2_gray = cv.cvtColor(frame_2, cv.COLOR_BGR2GRAY)\n",
" count += 1\n",
"\n",
" keypoints_2, status, _ = cv.calcOpticalFlowPyrLK(\n",
" frame_1_gray, frame_2_gray, keypoints_1, None, winSize=(15, 15),\n",
" maxLevel=2, criteria=(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))\n",
"\n",
" keypoints_2_good = keypoints_2[status==1]\n",
" keypoints_1_good = keypoints_1[status==1]\n",
" \n",
" for i, (kp2, kp1) in enumerate(zip(keypoints_2_good, keypoints_1_good)):\n",
" a, b = kp2.ravel()\n",
" a, b = int(a), int(b)\n",
" c, d = kp1.ravel()\n",
" c, d = int(c), int(d)\n",
" cv.line(mask, (a, b), (c, d), corners_colors[i].tolist(), 8, cv.LINE_AA)\n",
" cv.circle(frame_2, (a ,b), 9, corners_colors[i].tolist(), -1)\n",
" \n",
" display_frame = cv.add(frame_2, mask)\n",
" if count % 5 == 0:\n",
" plt.figure(figsize=(7,7))\n",
" plt.imshow(display_frame[:,:,::-1])\n",
" if count > 40:\n",
" break\n",
"\n",
" frame_1_gray = frame_2_gray.copy()\n",
" keypoints_1 = keypoints_2_good.reshape(-1,1,2)\n",
" \n",
"bike.release()"
]
},
{
"cell_type": "markdown",
"id": "d8c01f59",
"metadata": {},
"source": [
"Możemy zauważyć, że część punktów kluczowych została wykryta poza głównym śledzonym obiektem, jednak mimo wszystko jesteśmy w stanie określić główny ruch przemieszczającego się obiektu."
]
},
{
"cell_type": "markdown",
"id": "879a813e",
"metadata": {},
"source": [
"## Stabilizacja obrazu\n",
"\n",
"Spróbujemy wykorzystać przepływ optyczny do stablizacji cyfrowej filmu nakręconego z ręki:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "d8686953",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<video src=\"vid/protest.mp4\" controls width=\"800\" >\n",
" Your browser does not support the <code>video</code> element.\n",
" </video>"
],
"text/plain": [
"<IPython.core.display.Video object>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"IPython.display.Video(\"vid/protest.mp4\", width=800)"
]
},
{
"cell_type": "markdown",
"id": "c3541db4",
"metadata": {},
"source": [
"Załadujmy film oraz przygotujmy film wyjściowy, który będziemy wyświetlać obok oryginalnego, tak aby móc porównać otrzymane wyniki:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "0b18aad1",
"metadata": {},
"outputs": [],
"source": [
"cap = cv.VideoCapture(\"vid/protest.mp4\")\n",
"n_frames = int(cap.get(cv.CAP_PROP_FRAME_COUNT))\n",
"width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH)) \n",
"height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))\n",
"fps = cap.get(cv.CAP_PROP_FPS)\n",
"\n",
"out = cv.VideoWriter('vid/gen-protest.avi', cv.VideoWriter_fourcc(*'MJPG'), fps, (width*2, height))"
]
},
{
"cell_type": "markdown",
"id": "27355bd0",
"metadata": {},
"source": [
"Pomiędzy poszczególnymi klatkami filmu znajdujemy punkty kluczowe i śledzimy w jaki sposób się one przemieściły. Na tej podstawie przy pomocy [`cv.estimateAffinePartial2D()`](https://docs.opencv.org/4.5.3/d9/d0c/group__calib3d.html#gad767faff73e9cbd8b9d92b955b50062d) możemy oszacować transformacje (translację oraz obrót), które nastapiły między następującymi po sobie klatkami:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "c00b1e9d",
"metadata": {},
"outputs": [],
"source": [
"_, prev = cap.read()\n",
"prev_gray = cv.cvtColor(prev, cv.COLOR_BGR2GRAY)\n",
"\n",
"transforms = np.zeros((n_frames-1, 3), np.float32)\n",
"\n",
"for i in range(n_frames-2):\n",
" prev_pts = cv.goodFeaturesToTrack(prev_gray, maxCorners=200,\n",
" qualityLevel=0.01, minDistance=30, blockSize=3)\n",
" \n",
" success, curr = cap.read() \n",
" if not success: \n",
" break\n",
" curr_gray = cv.cvtColor(curr, cv.COLOR_BGR2GRAY) \n",
" \n",
" curr_pts, status, _ = cv.calcOpticalFlowPyrLK(prev_gray, curr_gray, prev_pts, None)\n",
" \n",
" idx = np.where(status==1)[0]\n",
" prev_pts = prev_pts[idx]\n",
" curr_pts = curr_pts[idx]\n",
" \n",
" mat, _ = cv.estimateAffinePartial2D(prev_pts, curr_pts)\n",
" # traslation\n",
" dx = mat[0,2]\n",
" dy = mat[1,2]\n",
" # rotation angle\n",
" da = np.arctan2(mat[1,0], mat[0,0])\n",
" \n",
" transforms[i] = [dx,dy,da]\n",
" \n",
" prev_gray = curr_gray"
]
},
{
"cell_type": "markdown",
"id": "ba9fce7d",
"metadata": {},
"source": [
"Przygotujemy też kilka funkcji pomocniczych. Posiadając serię transformacji wygładzimy ich poszczególne komponenty przy pomocy średniej kroczącej."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "0fd89a26",
"metadata": {},
"outputs": [],
"source": [
"def moving_average(values, radius): \n",
" window_size = 2 * radius + 1 \n",
" mask = np.ones(window_size)/window_size \n",
"\n",
" values_padded = np.lib.pad(values, (radius, radius), 'edge') \n",
" values_smoothed = np.convolve(values_padded, mask, mode='same') \n",
" \n",
" return values_smoothed[radius:-radius] # remove padding\n",
"\n",
"def smooth(trajectory, radius=50): \n",
" smoothed_trajectory = np.copy(trajectory) \n",
" for i in range(smoothed_trajectory.shape[1]):\n",
" smoothed_trajectory[:,i] = moving_average(trajectory[:,i], radius)\n",
"\n",
" return smoothed_trajectory"
]
},
{
"cell_type": "markdown",
"id": "9f4d1df0",
"metadata": {},
"source": [
"Możemy teraz policzyć jakie mieliśmy transformacje względem początku filmu, wygładzić je poprzez średnią kroczącą, a następnie nanieść wynikowe różnice na poszczególne transformacje:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "efb52c4d",
"metadata": {},
"outputs": [],
"source": [
"trajectory = np.cumsum(transforms, axis=0)\n",
"smoothed_trajectory = smooth(trajectory) \n",
"\n",
"difference = smoothed_trajectory - trajectory\n",
"transforms_smooth = transforms + difference"
]
},
{
"cell_type": "markdown",
"id": "0ef3b313",
"metadata": {},
"source": [
"Ostatecznie na podstawie wygładzonych transformacji dostosowujemy poszczególne klatki filmu. Dodatkowo poprzez ustabilizowanie obrazu mogą pojawić się czarne obramowania na wynikowym obrazie, zatem poprzez niewielkie powiększenie obrazu zniwelujemy ten efekt:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "b8d4528b",
"metadata": {},
"outputs": [],
"source": [
"cap.set(cv.CAP_PROP_POS_FRAMES, 0) # back to first frame\n",
"\n",
"for i in range(n_frames-2):\n",
" success, frame = cap.read() \n",
" if not success:\n",
" break\n",
"\n",
" dx = transforms_smooth[i,0]\n",
" dy = transforms_smooth[i,1]\n",
" da = transforms_smooth[i,2]\n",
"\n",
" mat = np.zeros((2,3), np.float32)\n",
" mat[0,0] = np.cos(da)\n",
" mat[0,1] = -np.sin(da)\n",
" mat[1,0] = np.sin(da)\n",
" mat[1,1] = np.cos(da)\n",
" mat[0,2] = dx\n",
" mat[1,2] = dy\n",
"\n",
" frame_stabilized = cv.warpAffine(frame, mat, (width, height))\n",
" \n",
" mat = cv.getRotationMatrix2D((width/2, height/2), 0, 1.1)\n",
" frame_stabilized = cv.warpAffine(frame_stabilized, mat, (width, height))\n",
"\n",
" frame_out = cv.hconcat([frame, frame_stabilized]) # frame by frame\n",
" \n",
" out.write(frame_out)\n",
" \n",
"out.release()"
]
},
{
"cell_type": "markdown",
"id": "c204ec3a",
"metadata": {},
"source": [
"Na potrzeby wyświetlenie wynikowego filmu w przeglądarce, użyjemy kodeka H264:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "4b58bce1",
"metadata": {},
"outputs": [],
"source": [
"!ffmpeg -y -hide_banner -loglevel warning -nostats -i vid/gen-protest.avi -vcodec libx264 vid/gen-protest.mp4"
]
},
{
"cell_type": "markdown",
"id": "fce1d5cd",
"metadata": {},
"source": [
"Wynikowy film:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "041e29a5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<video src=\"vid/gen-protest.mp4\" controls width=\"800\" >\n",
" Your browser does not support the <code>video</code> element.\n",
" </video>"
],
"text/plain": [
"<IPython.core.display.Video object>"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"IPython.display.Video(\"vid/gen-protest.mp4\", width=800)"
]
},
{
"cell_type": "markdown",
"id": "5fd935d2",
"metadata": {},
"source": [
"# Śledzenie obiektów"
]
},
{
"cell_type": "markdown",
"id": "dbeb1ae1",
"metadata": {},
"source": [
"Załóżmy, że chcemy na poniższym filmie śledzić przemieszczanie się piłkarek:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7a31e78d",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<video src=\"vid/football.mp4\" controls width=\"800\" >\n",
" Your browser does not support the <code>video</code> element.\n",
" </video>"
],
"text/plain": [
"<IPython.core.display.Video object>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"IPython.display.Video(\"vid/football.mp4\", width=800)"
]
},
{
"cell_type": "markdown",
"id": "2fc45895",
"metadata": {},
"source": [
"Biblioteka OpenCV posiada [kilka algorytmów](https://docs.opencv.org/4.5.3/dc/d6b/group__tracking__legacy.html) pozwalających na śledzenie obiektów. Poniżej użyjemy algorytmu [*Multiple Instance Learning*](https://docs.opencv.org/4.5.3/d9/dbc/classcv_1_1legacy_1_1TrackerMIL.html):"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "e28d152e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n",
"Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n",
"To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n",
"\u001b[33mWARNING: Skipping opencv-python as it is not installed.\u001b[0m\u001b[33m\n",
"\u001b[0mWARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.\n",
"Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.\n",
"To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.\n",
"Found existing installation: opencv-contrib-python 4.5.5.62\n",
"Uninstalling opencv-contrib-python-4.5.5.62:\n",
" Would remove:\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/cv2/*\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python-4.5.5.62.dist-info/*\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libQt5Core-39545cc7.so.5.15.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libQt5Gui-ba0a2070.so.5.15.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libQt5Test-c38a5234.so.5.15.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libQt5Widgets-e69d94fb.so.5.15.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libQt5XcbQpa-ca221f44.so.5.15.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libX11-xcb-69166bdf.so.1.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libXau-00ec42fe.so.6.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libavcodec-64ac49e1.so.58.91.100\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libavformat-4b79e479.so.58.45.100\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libavutil-805734e8.so.56.51.100\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libbz2-a273e504.so.1.0.6\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libcrypto-018b8c17.so.1.1\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libfreetype-c0e61f0c.so.6.14.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libgfortran-91cc3cb1.so.3.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libopenblas-r0-f650aae0.3.3.so\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libpng15-ce838cd1.so.15.13.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libquadmath-96973f99.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libssl-6082116c.so.1.1\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libswresample-83ce3247.so.3.7.100\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libswscale-7e960168.so.5.7.100\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libvpx-392cd848.so.6.4.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-icccm-413c9f41.so.4.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-image-e82a276d.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-keysyms-21015570.so.1.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-randr-a96a5a87.so.0.1.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-render-637b984a.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-render-util-43ce00f5.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-shape-25c2b258.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-shm-7a199f70.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-sync-89374f40.so.1.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-util-4d666913.so.1.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-xfixes-9be3ba6f.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-xinerama-ae147f87.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxcb-xkb-9ba31ab3.so.1.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxkbcommon-71ae2972.so.0.0.0\n",
" /home/mikolaj/.local/lib/python3.8/site-packages/opencv_contrib_python.libs/libxkbcommon-x11-c65ed502.so.0.0.0\n",
"Proceed (Y/n)? "
]
}
],
"source": [
"!pip3 uninstall opencv-python\n",
"!pip3 uninstall opencv-contrib-python\n",
"!pip3 uninstall opencv-contrib-python-headless\n",
"!pip3 install opencv-contrib-python==4.5.5.62"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a35e3ad7",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import cv2 as cv\n",
"video = cv.VideoCapture(\"vid/football.mp4\")\n",
"_, frame = video.read()\n",
"\n",
"bbox = (45, 350, 120, 270)\n",
"\n",
"tracker = cv.legacy.TrackerMIL_create()\n",
"tracker.init(frame, bbox)\n",
"\n",
"pt_1 = (int(bbox[0]), int(bbox[1]))\n",
"pt_2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
"cv.rectangle(frame, pt_1, pt_2, (0, 0, 255), 4, cv.LINE_8)\n",
"\n",
"\n",
"plt.figure(figsize=(7,7))\n",
"plt.imshow(frame[:,:,::-1]);"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8ebf3f6b",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "934dde10",
"metadata": {},
"source": [
"Możemy sprawdzić wyniki pomiędzy poszczególnymi klatkami, jednak tutaj na potrzeby prezentacji dodajmy odstęp co 10 klatek aby można było zauwazyć ruch. Dodatkowo możemy sprawdzić względną prędkość działania algorytmu:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7650ee1",
"metadata": {},
"outputs": [],
"source": [
"count = 50\n",
"\n",
"while count > 0:\n",
"\n",
" ok, frame = video.read()\n",
" if not ok:\n",
" break\n",
"\n",
" timer = cv.getTickCount()\n",
" \n",
" ok, bbox = tracker.update(frame)\n",
" \n",
" fps = cv.getTickFrequency() / (cv.getTickCount() - timer);\n",
"\n",
" if ok:\n",
" pt_1 = (int(bbox[0]), int(bbox[1]))\n",
" pt_2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
" cv.rectangle(frame, pt_1, pt_2, (0,0,255), 4, cv.LINE_8)\n",
" else :\n",
" cv.putText(frame, \"Tracking failure\", (20, 180), \n",
" cv.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), cv.LINE_AA)\n",
"\n",
" cv.putText(frame, \"FPS : \" + str(int(fps)), (20,50), \n",
" cv.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), cv.LINE_AA)\n",
"\n",
" if count % 10 == 0:\n",
" plt.figure(figsize=(7,7))\n",
" plt.imshow(frame[:,:,::-1])\n",
" count -= 1\n",
"\n",
"video.release()"
]
},
{
"cell_type": "markdown",
"id": "bf17ff66",
"metadata": {},
"source": [
"Istnieje też możliwość jednoczesnego śledzenia kilku obiektów:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d2e56fa9",
"metadata": {},
"outputs": [],
"source": [
"video = cv.VideoCapture(\"vid/football.mp4\")\n",
"_, frame = video.read()\n",
"\n",
"bboxes = [(45, 350, 120, 270), (755, 350, 120, 270)]\n",
"colors = [(0, 0, 255), (0, 255, 0)]\n",
"\n",
"multi_tracker = cv.legacy.MultiTracker_create()\n",
"\n",
"for bbox in bboxes:\n",
" multi_tracker.add(cv.legacy.TrackerMIL_create(), frame, bbox)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9f989b8a",
"metadata": {},
"outputs": [],
"source": [
"count = 50\n",
"\n",
"while count > 0:\n",
"\n",
" ok, frame = video.read()\n",
" if not ok:\n",
" break\n",
"\n",
" timer = cv.getTickCount()\n",
" \n",
" _, boxes = multi_tracker.update(frame)\n",
" \n",
" for i, bbox in enumerate(boxes):\n",
" pt_1 = (int(bbox[0]), int(bbox[1]))\n",
" pt_2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
" cv.rectangle(frame, pt_1, pt_2, colors[i], 4, cv.LINE_8)\n",
"\n",
" if count % 10 == 0:\n",
" plt.figure(figsize=(7,7))\n",
" plt.imshow(frame[:,:,::-1])\n",
" count -= 1\n",
"\n",
"video.release()"
]
},
{
"cell_type": "markdown",
"id": "b1d84a3a",
"metadata": {},
"source": [
"# Zadanie 1\n",
"\n",
"Dla filmu `vid/football.mp4` porównaj jakość śledzenia dla dostępnych algorytmów. Wyniki zapisz na jednym filmie.\n",
"\n",
"![Porówanie algorytmów śledzenia obiektów](img/football-multi.png)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "47227975",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import cv2 as cv\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"import IPython.display\n",
"\n",
"video = cv.VideoCapture(\"vid/football.mp4\")\n",
"_, frame = video.read()\n",
"\n",
"trackers = []\n",
"bbox = (45, 350, 120, 270)\n",
"\n",
"tracker_mil = cv.legacy.TrackerMIL_create()\n",
"tracker_mil.init(frame, bbox)\n",
"trackers.append((tracker_mil, 'MIL'))\n",
"\n",
"tracker_b = cv.legacy.TrackerBoosting_create()\n",
"tracker_b.init(frame, bbox)\n",
"trackers.append((tracker_b, 'BOOSTING'))\n",
"\n",
"tracker_kcf = cv.legacy.TrackerKCF_create()\n",
"tracker_kcf.init(frame, bbox)\n",
"trackers.append((tracker_kcf, 'KCF'))\n",
"\n",
"tracker_tld = cv.legacy.TrackerTLD_create()\n",
"tracker_tld.init(frame, bbox)\n",
"trackers.append((tracker_tld, 'TLD'))\n",
"\n",
"tracker_mf = cv.legacy.TrackerMedianFlow_create()\n",
"tracker_mf.init(frame, bbox)\n",
"trackers.append((tracker_mf, 'MEDIANFLOW'))\n",
"\n",
"tracker_m = cv.legacy.TrackerMOSSE_create()\n",
"tracker_m.init(frame, bbox)\n",
"trackers.append((tracker_m, 'MOOSE'))\n",
"\n",
"tracker_csrt = cv.legacy.TrackerCSRT_create()\n",
"tracker_csrt.init(frame, bbox)\n",
"trackers.append((tracker_csrt, 'CSRT'))\n",
"\n",
"\n",
"\n",
"pt_1 = (int(bbox[0]), int(bbox[1]))\n",
"pt_2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
"cv.rectangle(frame, pt_1, pt_2, (0, 0, 255), 4, cv.LINE_8)\n",
"\n",
"plt.figure(figsize=(7,7))\n",
"plt.imshow(frame[:,:,::-1]);"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "5acf46f0",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABGIAAAEeCAYAAADB67OCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9d7yt2XnXCX5XeMOOJ958b91bSSpVSaVoyZKFjZADDrjB2Bg3wW0GBppuwDDQDDM9PZ+G7qEHZoZhMEy3YYAeGDBgbANOgGxLsi1bsXKuujmcfM6Ob1ph/lg7nXTrliQsVXk/Vefuvd+41nqf9Vvr/a0nCO89c5nLXOYyl7nMZS5zmctc5jKXucxlLnP5Ty/ya12AucxlLnOZy1zmMpe5zGUuc5nLXOYyl98uMidi5jKXucxlLnOZy1zmMpe5zGUuc5nLXH6LZE7EzGUuc5nLXOYyl7nMZS5zmctc5jKXufwWyZyImctc5jKXucxlLnOZy1zmMpe5zGUuc/ktkjkRM5e5zGUuc5nLXOYyl7nMZS5zmctc5vJbJHMiZi5zmctc5jKXucxlLnOZy1zmMpe5zOW3SPTddv7VH/pWX0rFtUGOEBqLpzSOE7HiVKrw3pM5z81hQR9Jo1EjiuooLVCRwDqHtR6ExHlwHpLGAklzkUa9RZLG9Pt9Hn3oAR568GFUFLG7tcbpkyc5dfo02XBIb3ebX/73v8jjF89w5eZNzi2vsL63zaVzZ7h5+w6nV1foDXssrq5Qr9d52+MfZmHlLABeSBACIcSkTuPvHjn97j3jNN5CCAQgBGitcM6FbUJirePLTfY9vr73nnARD7h99z7uvNdLMS4O1HG87cCVRtcRWGun5cHjPHh3/H1n739ceQ5u+0rTos8+j3u97lHPc/Y86wy9Xpder8e5sxdQSn3F5Tx473s57l6PHZetKHI+9/lPcfLkCk899QSvvfIcZVlRGUteVFjr+Ml/9al7u+ibVP7kD37QG6EoYs3F3pAf+dVX2Is1//DDF9lNQAHf//wGH7yyw6cfP8Pb7vRY6eR8+vEzfMszd+hFin/2kfvYkTGbmQSpSCJYbnmWtMBZST8v+L7P3+BDr22SuKleVEpye2WBk3s9aqUBINOK2+0G//FdD/Hy6QU+/sJNPnjlNiv9IXkUcW15kU997GOc+S/+BCJSWByf+fVPc2plhXe+63G8gJ2NNc6vrnL2/CW6nV2ywQ6/+O9+mg8/9jDOVSy2mqhOj/v/+c9Sf/pFnvnWj3DnY9+Is5YHT5zlsZ//NPEvfAK5u4d78H6KH/0z2N/3n4FSwGGdFEIgpURKuU8PnfM4G/qMxyMFIEfYyWHshHvv35NzvMc5s+/86TU84EP5EMhR2Y67n/UO5z3jTWNcO3ht59y+c/dh2hj3/Cwmj/dMLjT7cWy9vffh9t5jrSPPh8RxQl4MiCKF94I4qiOlvCc8v5t47+8JP4wxFGXG5cuXObF6klOnTt8z7oxlFk8hqAQCBAI/Gk8Ojq3eey6cf+i3FRb98U+/zKWdPgJwwHYj5gv3LfELj50hWkj5tqfXeP9La6x2czqNmCcuLPEf33mSXRnTXsv4oZfv8PbtLpF1rK02+NS77+M3T9U5v57xbU/e5uFOn0ZZsV1LuXL+JMvDIfff3kbN9gkBV1cWScuKZy+exeqI9125xS+/5zE+8cAlmrUF/sJLr7B05QpP/tk/w6+u3eLbfumTvPvyFZKtLbpnTtP9ge+n+JN/ik6ZHcKi+1+9zoM//hOkGzuTnuaBzqkVdK1G4+rN0AWkxJ87S/V7vpvqz/xp1FNPE/+tv4N8/gXIMvzF+zB/8Acwf+pPIJaXv3wscg75kz+F+lt/G3/pEuZ//jH8wsJ0f5ah/ur/iPyFX8T+hR/F/tE/PMeiORa9JeW4udE/+Mgl+trx7a9u8fHXdnjpVJt//5FLfOzZ9UN49EuPneB3vbDFR17eIDXTlwErBc9fWuUff/ACezJhdxiRlZLF3PDfPP08j2/toGbK0os0N9pNHtrtEo90vpfEXD25yr//wLsZ1mp82xee5JEbd1jMMoqlJbbe/Tj/9O0Pod/97jc0N/LeU1nH9Rdf5Tt/7tOc+MLTqNG8zbVb5P/ln6T8c/8V0c/+POnf+3Hkteu40ycxP/LDVH/kD0GjPin3fG40x6M3Il9tPLorEWO8RTrL/alCCIH1Hh9LpPDgLFJJTGVRSY3Hzq8QpxJjHCuLLeqNGAR46zBWUlSGWi1BSkVWVFRmmzwT4Axr155lb+s6jeYiQkhW2k2csYgRQ+C8xeNAeJSWeBweh8NivQGhcF4EckUp/LiqM1UeN8REMSd94IiHPyJKvPcTBQGQQuJ4Y8qy7wG72fMEjB7auGxfiRwkLu5FKT0znNDMdQ4SL0d9/08pB+95VD1mjznYKY4qp5gBsHEdf6vq80blYP2LsiSOEpwVlEVJWRgqYygri3MEsvMtLgkRQ2PIfcF7Lt/hwe0eAFdeS/m5957h4nqX3/3cGqlxfO9nr5MYi/TwfZ+5Qj03eODBjZwrSwn1ZoSxZdB/pZBaUeWeB4aCb7yyTez2t2dkHRc3dvdtqxnLAztdfuTXn2KzmXJubzCBm3pZ8sjaBg/+m3/H5z70O9h5/J0IBFGcBP0bDXQOjxcCjyX8Ai8E1nmeevYFPnb2HI/+o59k4ZmXEcD9v/wbbH70G6gEnPhHP0H6s7+EGGPTM89R+3N/kcF99+G+4f1HYspY5621k4lH2AHei9Hg7HEShJ9uFwiElLPD8KHrwtFk5GTfQYg9ULbXw6rZ/Uoo8A7vHd6PsX3/oDeeaNz9mjBGQT/7ejnCnH31fb0u5gECvmitsc6glCLPK+I4RsrDz+Mgbt3LOHC3dprFSq0ViAQp5T21xeEbjSslkFKAODCx8AIhD5fljU5o3oxyEIvGJAwEE+MTg5Lf/cI6p7KKYaL5yEsbE9PjxUHJ73xxnVZu+NcXT/Kjn3uNk3k5Of/cRp/v+5UXWXn3RT763E0aeTXZdyLLWX3lOrBvagOA8vDg1l447vnLeAGJsXzvb36R5xt1nOxw/pOfRBnDAz/9M9y/t8uFJ5+aXGfhzhrtH/t77FpD54/98H4seuZ53vuJz1Pb2Nl3TwEsrm/v3+Yc4sZN4r/3v6B/5ZPIa9dhmE3uI167TPR/+RuIGzcp/vb/HavUG8ci51B/58dQf/1vIPp9/DPPIv74H8N//GOjFweP+gf/EPVjfw9hDPwvfx/7B74fn6ahDHMsmmPRW0iOmht54NH1Rc70cn7vM2tEzrM4LFnJKt51fecQHp3fGXB+N9tHwgAo53n79W3ue/clOnUB0mKt5V2bW7x7a+eQS0WrMjy6vbd/W1Hyzhu3ubi1Q6U1y70pXqa7u5z75Kf4kSee4Ocefts9z40+/N7HSZOYRGve3c859YWnw/viSGS3R/JTP4Nvt6j/9/8jlAFj5e4u8V/5b2F7h/Kv/KVxx5vPjQ5dE+Z4dNyNxpX66uHRXYkYpB9ZSoQLS6HAe6QQRFLiCEyQFIIsH2CsxDqLa2qqvKQ0Fc5YpNSUlUP6BK0E9TQhbqVURhKrJrVaDDpGiIJhL2f71itIb4jjBO+qqeYLkFpgnMVYO+qsHjFiKJWOiePaRC8mg/+hhzhSsJlNYobhFKOGdc5NGFIpJdY7vHs9rTumKaVECKZspAgllH5K9BxHIBy3b1KbeyIrjjwRDrXW0ecfJD5ej6B5I+TScceN63XUC+Xsfe52jbE45zDG4GwAqa+23CsbOz52LPfSTo16gw+8/5sQCPIsJ4k0L7zwPM6VGFuRJPFXVPY3g3SFoGcrjHEkAzPR1m+8tscvPnKSD722RzKaRNQrOzmvkU9XGpa8xApBuykQUtPtFOSlo0DQ0DXiaogaAXOpJJ1ahBAS6WFhkKO8xwrYrSckxtEsKhJjOb83AEJP6tZrRNZSK0qi4ZCl559l+/F3AoIkipFSIaxj6ZlnWP3SF9Ef+xb8uXM44fHeYX1g1UWUcPLnPjUhYQDaDpaaTfJXXuPMf/j0hISB0aLDYIC4dg33/vceYuP
"text/plain": [
"<Figure size 1440x360 with 8 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"count = 50\n",
"rows, cols = 2, 4\n",
"ok, frame = video.read()\n",
"plt.figure(figsize=(20,5));\n",
"plt.subplot(rows, cols, 1);\n",
"plt.imshow(frame[:,:,::-1]);\n",
"plt.axis('off');\n",
"cnt = 2\n",
"for t in trackers:\n",
" video = cv.VideoCapture(\"vid/football.mp4\")\n",
" count = 50\n",
" while count > 0:\n",
" ok, frame = video.read()\n",
" if not ok:\n",
" break\n",
"\n",
" timer = cv.getTickCount()\n",
"\n",
" ok, bbox = t[0].update(frame)\n",
"\n",
" fps = cv.getTickFrequency() / (cv.getTickCount() - timer);\n",
"\n",
" if ok:\n",
" pt_1 = (int(bbox[0]), int(bbox[1]))\n",
" pt_2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3]))\n",
" cv.rectangle(frame, pt_1, pt_2, (0,0,255), 4, cv.LINE_8)\n",
" else :\n",
" cv.putText(frame, \"Tracking failure\", (20, 180), \n",
" cv.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), cv.LINE_AA)\n",
"\n",
" cv.putText(frame, f\"{t[1]} FPS : \" + str(int(fps)), (20,50), \n",
" cv.FONT_HERSHEY_SIMPLEX, 2, (0,0,255), cv.LINE_AA)\n",
"\n",
" if count % 26 == 0:\n",
" plt.subplot(rows, cols, cnt);\n",
" plt.imshow(frame[:,:,::-1]);\n",
" plt.axis('off');\n",
" cnt += 1\n",
" count -= 1\n",
"video.release()"
]
}
],
"metadata": {
"author": "Andrzej Wójtowicz",
"email": "andre@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3.8.12 64-bit",
"language": "python",
"name": "python3"
},
"lang": "pl",
"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.8.12"
},
"subtitle": "07. Analiza wideo [laboratoria]",
"title": "Widzenie komputerowe",
"vscode": {
"interpreter": {
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
}
},
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}