widzenie_komputerowe_zadania/wko-02.ipynb

1326 lines
2.3 MiB
Plaintext
Raw Permalink Normal View History

2021-11-24 11:50:36 +01:00
{
"cells": [
{
"cell_type": "markdown",
"id": "b9359682",
"metadata": {},
"source": [
"![Logo 1](img/aitech-logotyp-1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Widzenie komputerowe </h1>\n",
"<h2> 02. <i>Operacje binarne na obrazach</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": "fc75aedb",
"metadata": {},
"source": [
"# Progowanie\n",
"\n",
"Podczas pracy z obrazami często potrzebne jest operowanie na obrazach, które przyjmują tylko dwie skrajne wartości. Po operacji tzw. progowania (ang. *thresholding*) na obrazie będziemy mieli piksele czarne o wartości 0 lub białe o wartości 255 (lub 1, w zależności od tego na jakim typie danych i w jakiej dziedzinie operujemy).\n",
"\n",
"Na początku załadujmy niezbędne biblioteki."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "cabd0fa4",
"metadata": {},
"outputs": [],
"source": [
"import cv2 as cv\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"id": "22fcf0c4",
"metadata": {},
"source": [
"Podczas tych zajęć skupimy się na ręcznym progowaniu. Jeśli dla obrazu w skali odcieni szarości chcielibyśmy w naszym kodzie uzyskać obraz binarny, to moglibyśmy hipotetycznie wybrać jedną z trzech opcji:\n",
"\n",
"1. przejść w pętli po wszystkich pikselach, sprawdzić czy wartość danego piksela jest mniejsza od wybranej wartości progowej i na tej podstawie ustawić nowy piksel jako czarny lub biały,\n",
"2. użyć biblioteki *NumPy* (i przy pomocy wektoryzacji stworzyć macierz binarną),\n",
"3. użyć biblioteki *OpenCV*.\n",
"\n",
"W tym miejscu nie będziemy co prawda robili eksperymentu, jednak co do zasady mając do wyboru gotowe zoptymalizowane biblioteki, zdecydowanie *nie* powinniśmy implementować algorytmów od podstaw (no chyba że podczas zajęć uczymy się mechaniki danych algorytmów; na produkcji raczej będziemy preferowali gotowe rozwiązania). Różnica w wydajności między naiwną ręczną implementacją a użyciem gotowej biblioteki może być, lekko licząc, kilkudziesięciokrotna.\n",
"\n",
"Wykorzystajmy na początek funkcję [`cv2.threshold()`](https://docs.opencv.org/4.5.3/d7/d1b/group__imgproc__misc.html#gae8a4a146d1ca78c626a53577199e9c57) do zwykłego progowania z progiem ustalonym na 100:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "52e17cff",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"img = cv.imread(\"img/lena.png\", cv.IMREAD_GRAYSCALE)\n",
"_, img_bin = cv.threshold(img, 100, 255, cv.THRESH_BINARY)\n",
"\n",
"plt.figure(figsize=[10,10])\n",
"plt.subplot(121) \n",
"plt.imshow(img, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(122)\n",
"plt.imshow(img_bin, cmap='gray')\n",
"plt.title(\"Binary\");"
]
},
{
"cell_type": "markdown",
"id": "5f672c11",
"metadata": {},
"source": [
"Istnieją również [inne metody ręcznego progowania](https://docs.opencv.org/4.5.3/d7/d1b/group__imgproc__misc.html#gaa9e58d2860d4afa658ef70a9b1115576), które np. przycinają wartości do progu (w dokumentacji znajdują się wzory i przykładowe wykresy opisujące poszczególne typy operacji). Poniżej możemy zobaczyć wynik dla tych operacji:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "78627f66",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x720 with 12 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"_, img_bin = cv.threshold(img, 100, 255, cv.THRESH_BINARY)\n",
"_, img_bin_inv = cv.threshold(img, 100, 255, cv.THRESH_BINARY_INV)\n",
"_, img_trunc = cv.threshold(img, 100, 255, cv.THRESH_TRUNC)\n",
"_, img_to_zero = cv.threshold(img, 100, 255, cv.THRESH_TOZERO)\n",
"_, img_to_zero_inv = cv.threshold(img, 100, 255, cv.THRESH_TOZERO_INV)\n",
"\n",
"images = (img, img_bin, img_bin_inv, img_trunc, img_to_zero, img_to_zero_inv)\n",
"titles = (\"Grayscale\", \"Binary\", \"Binary Inverse\", \"Truncate\", \"To Zero\", \"To Zero Inverse\")\n",
"\n",
"plt.figure(figsize=[15,10])\n",
"\n",
"for i, (image, title) in enumerate(zip(images, titles)):\n",
" plt.subplot(231+i)\n",
" plt.imshow(image, cmap='gray')\n",
" plt.title(title)\n",
" plt.colorbar()"
]
},
{
"cell_type": "markdown",
"id": "b12656fa",
"metadata": {},
"source": [
"Spójrzmy na słupki z zakresami wartości. Możemy zauważyć, że dla poszczególnych obrazów wartości minimalne i maksymalne biblioteka Matplotlib automatycznie przeskalowała do skrajnych wartości dla bieli i czerni. Aby na etapie wyświetlania usunąć to przekłamanie, musimy nieco zmienić funkcję `matplotlib.pyplot.imshow()` podając prawdziwe zakresy wartości:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "9150b23e",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x720 with 12 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=[15,10])\n",
"\n",
"for i, (image, title) in enumerate(zip(images, titles)):\n",
" plt.subplot(231+i)\n",
" plt.imshow(image, cmap='gray', vmin=0, vmax=255)\n",
" plt.title(title)\n",
" plt.colorbar()"
]
},
{
"cell_type": "markdown",
"id": "be117462",
"metadata": {},
"source": [
"## Operacje morfologiczne\n",
"\n",
"Morfologia matematyczna jest narzędziem, które pozwala m.in. na uzupełnianie ubytków w uszkodzonych/zniekształconych obrazach lub wyciszanie (a czasem i usuwanie) prostych kształtów. Na początku omówimy proste operacje typu erozja i dylacja, a następnie ich złożenie. Dodajmy, że operacje te działają zasadniczo na wszystkich typach obrazów (nie tylko binarnych)."
]
},
{
"cell_type": "markdown",
"id": "26f1d8b2",
"metadata": {},
"source": [
"### Element strukturyzujący, erozja i dylacja\n",
"\n",
"Na początku będziemy potrzebowali tzw. element strukturyzujący. Jest to binarna maska (mała macierz), najczęściej o nieparzystym wymiarze i zawierająca jakiś prosty, regularny kształt. Kształt ten może być dowolny, jednak w praktyce wykorzystywanych jest [kilka standardowych](https://docs.opencv.org/4.5.3/d4/d86/group__imgproc__filter.html#gac2db39b56866583a95a5680313c314ad). Do łatwego uzyskania elementu użyjemy funkcji [`cv.getStructuringElement()`](https://docs.opencv.org/4.5.3/d4/d86/group__imgproc__filter.html#gac342a1bb6eabf6f55c803b09268e36dc)."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f7e590fb",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"kernel_ellipse = cv.getStructuringElement(cv.MORPH_ELLIPSE, (7, 7))\n",
"plt.imshow(kernel_ellipse, cmap='gray');"
]
},
{
"cell_type": "markdown",
"id": "f4d750a9",
"metadata": {},
"source": [
"No, powiedzmy, że jest to elipsa ;) Tutaj użyliśmy dość dużego elementu o wymariach 7 na 7, jednak w praktyce może być on mniejszy.\n",
"\n",
"W jaki sposób możemy wykorzystać taki element strukturyzujący? Element strutkruryzujący jest maską binarną, którą możemy *przyłożyć* dla każdego piksela jakiegoś obrazu (najczęściej przykłada się go centralnie do piksela). Białe piksele maski mówią nam które sąsiadujące piksele powinniśmy wziąć w danym momencie pod uwagę. Mając wartości tych pikseli, możemy policzyć ich wartość minimalną (erozja) lub maksymalną (dylacja) i ustawić w nowym obrazie na współrzędznych danego piksela. Wykorzystuje się tutaj odpowiednio funkcje [`cv.erode()`](https://docs.opencv.org/4.5.3/d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb) i [`cv.dilate()`](https://docs.opencv.org/4.5.3/d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c). Poniżej możemy zobaczyć działanie na klasycznym przykładzie z monetami:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0beff1e3",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x576 with 4 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"coins = cv.imread(\"img/coins.png\", cv.IMREAD_GRAYSCALE)\n",
"_, coins_bin = cv.threshold(coins, 125, 255, cv.THRESH_BINARY)\n",
"\n",
"coins_eroded = cv.erode(coins_bin, kernel_ellipse, iterations=1)\n",
"coins_dilated = cv.dilate(coins_bin, kernel_ellipse, iterations=1)\n",
"\n",
"plt.figure(figsize=[10,8])\n",
"plt.subplot(221)\n",
"plt.imshow(coins, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(222)\n",
"plt.imshow(coins_bin, cmap='gray')\n",
"plt.title(\"Binary\")\n",
"plt.subplot(223)\n",
"plt.imshow(coins_eroded, cmap='gray')\n",
"plt.title(\"Eroded\")\n",
"plt.subplot(224)\n",
"plt.imshow(coins_dilated, cmap='gray')\n",
"plt.title(\"Dilated\");"
]
},
{
"cell_type": "markdown",
"id": "7d198b64",
"metadata": {},
"source": [
"Możemy zauważyć, że zastosowanie erozji spowodowało wypełnienie w większym lub mniejszym stopniu dziur w zbinaryzowanych monetach. Z kolei dylacja spowodowała prawie zaniknięcie obrazu. Użyliśmy tutaj jednej iteracji, jednak możliwe jest kilkukrotne wykonanie erozji lub dylacji.\n",
"\n",
"Poniżej możemy zobaczyć, że erozja i dylacja są w pewien sposób komplementarne:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "7a162cc0",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x576 with 4 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"coins = cv.imread(\"img/coins.png\", cv.IMREAD_GRAYSCALE)\n",
"_, coins_bin = cv.threshold(coins, 125, 255, cv.THRESH_BINARY_INV)\n",
"\n",
"coins_eroded = cv.erode(coins_bin, kernel_ellipse, iterations=1)\n",
"coins_dilated = cv.dilate(coins_bin, kernel_ellipse, iterations=1)\n",
"\n",
"plt.figure(figsize=[10,8])\n",
"plt.subplot(221)\n",
"plt.imshow(coins, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(222)\n",
"plt.imshow(coins_bin, cmap='gray')\n",
"plt.title(\"Binary\")\n",
"plt.subplot(223)\n",
"plt.imshow(coins_eroded, cmap='gray')\n",
"plt.title(\"Eroded\")\n",
"plt.subplot(224)\n",
"plt.imshow(coins_dilated, cmap='gray')\n",
"plt.title(\"Dilated\");"
]
},
{
"cell_type": "markdown",
"id": "f5a050d4",
"metadata": {},
"source": [
"Element strukturyzujący w kształcie elipsy całkiem dobrze zadziałał w przypadku usunięcia dziur w owalnych kształtach. Z drugiej strony musimy być świadomi, że inne, arbitralne kształty mogą być przydatne w specjalnych zastosowaniach (np. pionowe lub ukośne linie/kreski)."
]
},
{
"cell_type": "markdown",
"id": "df8b1531",
"metadata": {},
"source": [
"### Otwarcie i zamknięcie\n",
"\n",
"Złożenie operacji dylacji i erozji może posłużyć np. do uzupełnienia przerw między kształtami lub wyciszenia drobnych szumów. Tzw. *otwarcie* dotyczy erozji, po której następuje dylacja, co w konsekwencji usuwa białe plamy i przerwy. Z kolei tzw. *zamknięcie* to dylacja, po której następuje erozja, i taka operacja usuwa czarne plamy i przerwy. Jeśli interesuje nas wypełnienie przerw, to takie złożenia operacji nie będą powodowały *rozrastania* obiektów. Użyjemy tutaj funkcji [`cv.morphologyEx()`](https://docs.opencv.org/4.5.3/d4/d86/group__imgproc__filter.html#ga67493776e3ad1a3df63883829375201f)."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "4a661d2c",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAADYCAYAAAApgK2eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAACHdElEQVR4nO2dd1hU19r27zVD78UCikqUoxwlkShRohzLZywkMdZEjSXxjSaaWI/GyKsxRo8ajbG+RmMS67FgDxw1amKNKIoKFsSGICqKIArSZ+b+/gDmMDJDExjA9buu+wLWbs/es+fm2WuvIkhCIpFIJBKJRPLiKIwdgEQikUgkEklNQSZWEolEIpFIJOWETKwkEolEIpFIygmZWEkkEolEIpGUEzKxkkgkEolEIiknZGIlkUgkEolEUk7IxEpS7gghVgkhvjZ2HBKJRGJMhBBXhBCdjB2HpHIRchwrSVkQQsQAqAtADSAHQAiAUSTjjBmXRCKRPI8Q4mMAkwA0AZACYDeAAJJPjBiWpIYia6wkL0JPkjYAXAE8BLC8Ig8mhDCpyP1LJJKahxBiEoD5AL4EYA/AF0AjAIeEEGbGjE1SM5GJleSFIZkJYAeA5gAghFgnhPhX3u+dhBB3hRCThBAJQoh4IcTw/G2FEO8IIS4IIVKEEHFCiJkFlrkLISiE+EQIcQfAYSHEXiHE2ILHF0JcFEL0roRTlUgk1QghhB2AbwGMJfk7yRySMQA+QG5yNUQIMVMIsUMIESiESBVCnBdCtCywj3pCiJ1CiEdCiNtCiHEFls0UQmwTQmzI2/aKEMKnwPIYIcRbJVy3VZ4XpgohtufF86+Kv0qS8kYmVpIXRghhBWAAgNMGVnFB7pNifQCfAFghhHDMW5YGYBgABwDvABitJ0nqCODvALoDWA9gSIFjt8zb775yOBWJRFKzaAfAAsCugoUknwHYD6BrXlEvANsBOAHYDGCPEMJUCKEAEAwgArk+0wXABCFE9wK7ew/AVuR6WBCA/ysiHr3r5tWc7QawLi+GLQD6lP50JVUBmVhJXoQ9QognyG2z0BXA9wbWywEwK+9pcR+AZwCaAQDJoyQvkdSQvIhcQ+n43PYzSaaRzADwG4C/CSH+lrdsKIBAktnlemYSiaQmUAtAIkmVnmXxecsB4BzJHSRzACxCbjLmC+ANALVJziKZTTIawM8ABhbYz18k95FUA9gIoCUMY2hdXwAmAJbl+eQuAGfKdMYSoyMTK8mL0JukAwBzAGMAHBNCuOhZL+k5Y0sHYAMAQoi2QogjedXsTwGMwn/NLh9tg3iSWQC2IbcKXwFgEHINSiKRSJ4nEUAtA+0zXfOWA7oeowFwF0A95L4urCeEeJIvAP+L3I47+Two8Hs6AIsi2oMaWrcegHvU7U0mOwJVU2RiJXlhSKrznrDUAPxKuflm5FaJNyBpD2AVAPH8IZ77ez2Awcitlk8near0UUskkpeAUwCyAPQtWCiEsAbgD+DPvKIGBZYpALgBuI/c5OY2SYcCsiX5djnHGQ+gvhCioPc1MLSypGojEyvJCyNy6QXAEcDVUm5uC+AxyUwhRBsAHxa3QV4ipQHwA2RtlUQiMQDJp8htvL5cCNEjr92UO3LbU93Ff/2jtRCib17t0QTkJmOnkfs6LkUI8ZUQwlIIoRRCeAkh3ijnUE8h98F0jBDCJM9P25TzMSSVhEysJC9CsBDiGXLbWM0B8BHJK6Xcx+cAZgkhUgHMQO5rvpKwAcCrAP5dyuNJJJKXCJILkPv6biFyvSoUuTVRXfKaFgC5bTcHAEhGbrvNvnltndQAegLwBnAbua8Of0FuZ5zyjDEbubVqnwB4gtwOOv9BboInqWbIAUIl1RIhxDAAn5Is7atHiUQi0ZI3xIsHySHFrVuZCCFCAawiudbYsUhKh6yxklQ78oZ3+BzAamPHIpFIJOWBEKKjEMIl71XgRwBeA/C7seOSlJ4KS6zy3mdfE0LcFEJMrajjSF4u8saPeYTckd43GzkcSQ1F+pfECDRD7nhZT5E7/U5/kvHGDUlSFirkVaAQQgngOnLHNroL4CyAQSQjy/1gEolEUo5I/5JIJC9CRdVYtQFwk2R0XqO8rcgd2VYikUiqOtK/JBJJmamoxKo+dAc3u5tXJpFIJFUd6V8SiaTMGBod9kV5foBH4LlBHoUQnwL4NO/P1hUUh0Qiqbokkqxt7CD0UKx/AdLDJJKXHZL6vKLCEqu70B01Nn8U24IBrUZery4hhBzzQSJ5+Yg1dgAGKNa/AOlhEolEPxX1KvAscifKfSVv1u6ByJ22RCKRSKo60r8kEkmZqZAaK5IqIcQYAAcAKAGsKcOI3BJJlcTT0xPx8fFQKpXo378/fH194eDgAFNTU+zbtw8RERFISUkBANy+fRtpaWlGjlhSGqR/SV4mvL298eTJE8TExBg7lBpDlRh5XVajS6oyZmZmaN++Pd59912kpKRg9+7dSE9Px48//oiuXbvi4cOHsLa2xoMHD2BtbQ1XV1c8ffoUJBEUFIR58+aBJK5du2bsU6lqnCPpY+wgygPpYZLqhBACzs7OWL58udbXfv75Z/zrX/+CSqUydnjVBkNtrGRiJZEYwNTUFD169EC/fv3Qt29f2NraIjAwEI0bN4a9vT2aNm2qXffZs2cYMWIEXnnlFbz33nt45ZVXsHnzZpiZmaFbt24wNzfHkCFDYGlpiWPHjiE7O9uIZ1ZlkImVRFKJ2NraYtCgQRgxYkQhD3v48CH+/ve/Izk52YgRVi8MJVYgaXQht8eNlFSVkEKhYM+ePXn06FE+ffqUkyZN4h9//EFDZGdn88KFCxw9ejR79+5NHx8fBgUF8eLFi6xVqxb79+/PxMREHjx4kKdPn+b27dvp4+Nj9POsAgoztvdID5N6mTRz5kxqNBq9HvbFF19QoVAYPcbqJEN+UFG9AiWSakmDBg3w+eefo2vXrggJCYFarcaYMWNQp04dZGRkQKlUwszMTGcbjUaD0NBQzJgxA//85z8RFhaGFStWYPr06XBzc8POnTtx4cIFuLi44OrVq/Dy8sL//M//wN3dHbt374ZarTbS2UokkpeJ6OhoZGZmwtLSUqdco9EgOjoaGo3GSJHVLOQkzBIJcqvIBwwYgK1bt0KlUmHy5MlwdnZGx44d8ejRI6xfvx4BAQHYs2dPoW3Nzc0xePBg2NjYoG7dugCAw4cP48cff8SDBw9AErdu3cLJkyeRmZmJkJAQfPnll7C0tISzs3Mln6lEInkZsLa2LlS2adMmBAcHFyo3NzdHu3btKiOslwKZWEleaoQQaNq0KXbv3o3Fixfjr7/+QkpKCn799Vd8+OGHUCqV8PHxgYmJCc6dO4e4uDikp6cX2s/FixfxxRdfYPDgwTA1NUVOTg527dqFBw8e6Kw3YsQI2NnZ4e9//zs2btyIhISEyjpViUTyEmBmZoYJEyYgODgYo0ePhqmpqXaZWq3Gnj178OzZs0LbtWvXrlBNlqSMGLttgmyfIGUsOTs7c/ny5bx+/TovXbrE4cOH8/vvv6dKpSJJqtVqnj17liSZmZnJTZs2cdCgQTxy5EihNgoZGRmcOHEip06dSg8PD73HMzEx4S+//MJ3332XJiYmRj//KiDZxkpKqhxlZmbG7777TuthmZmZDAgI4BdffMHatWsTAN3c3PR6WEJCAh0dHY1+DtVJBv3A2IYkTUnKGOrVqxfPnDlDkpw7dy6trKx0DCmf/Iae9+/f5zvvvMOMjAy9jT/J3EQsJyeHiYmJ3LVrl442b95MPz8/3r9/n0OGDCEA2tnZ0dra2ujXwoiSiZWUVDnJzMyM8+bN0+thGo2Gx48fp7u7O69du1bIwx4+fMjvvvuOpqamRj+P6iRDfiCHW5C8dPTq1Qvr16+Hvb09MjIy0LlzZ7zxxhtYsmQJlEql3m2ys7ORmJiIevXqAQCSk5MRHh6Oy5cvIyio8KDcDRo0wNChQ1G7dm14eXkBAK5evYoffvgB77zzDn744QdERkbijTfewPXr11/WwfnkcAsSSRlo1KgRYmN1Z4QaM2ZMsR524cIFvPHGG1AoFDo
"text/plain": [
"<Figure size 720x720 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"coins_opened = cv.morphologyEx(coins_bin, cv.MORPH_OPEN, kernel_ellipse, iterations=1)\n",
"\n",
"plt.figure(figsize=[10,10])\n",
"\n",
"plt.subplot(121)\n",
"plt.imshow(coins_bin, cmap='gray')\n",
"plt.title(\"Binary\")\n",
"plt.subplot(122)\n",
"plt.imshow(coins_opened, cmap='gray')\n",
"plt.title(\"Opening\");"
]
},
{
"cell_type": "markdown",
"id": "b711e6d5",
"metadata": {},
"source": [
"### Zadanie 1\n",
"\n",
"Wczytaj obraz `text_no_ocr.png`, który zawiera fragment starych notatek (z przedmiotu \"E-gospodarka\" dra Michała Rena) posiadających zabezpieczenie przed dalszym przetwarzaniem. Spróbuj usunąć niechciane kształty (wynik nie musi być dokładny - może uzyskasz lepszy efekt?)."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "99a8de1b",
"metadata": {},
"outputs": [
{
"ename": "TypeError",
"evalue": "Image data of dtype object cannot be converted to float",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-9-26090b1d03bb>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msubplot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m121\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mplt\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mimshow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtext_no_ocr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcmap\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'gray'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m~\\anaconda3\\lib\\site-packages\\matplotlib\\pyplot.py\u001b[0m in \u001b[0;36mimshow\u001b[1;34m(X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, filternorm, filterrad, resample, url, data, **kwargs)\u001b[0m\n\u001b[0;32m 2722\u001b[0m \u001b[0mfilternorm\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfilterrad\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m4.0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mresample\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2723\u001b[0m data=None, **kwargs):\n\u001b[1;32m-> 2724\u001b[1;33m __ret = gca().imshow(\n\u001b[0m\u001b[0;32m 2725\u001b[0m \u001b[0mX\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcmap\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mcmap\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnorm\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mnorm\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maspect\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0maspect\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2726\u001b[0m \u001b[0minterpolation\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0minterpolation\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0malpha\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0malpha\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvmin\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mvmin\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\anaconda3\\lib\\site-packages\\matplotlib\\__init__.py\u001b[0m in \u001b[0;36minner\u001b[1;34m(ax, data, *args, **kwargs)\u001b[0m\n\u001b[0;32m 1445\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0minner\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0max\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1446\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mdata\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 1447\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0max\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0mmap\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msanitize_sequence\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0margs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1448\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1449\u001b[0m \u001b[0mbound\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnew_sig\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbind\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0max\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m*\u001b[0m\u001b[0margs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\anaconda3\\lib\\site-packages\\matplotlib\\axes\\_axes.py\u001b[0m in \u001b[0;36mimshow\u001b[1;34m(self, X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, filternorm, filterrad, resample, url, **kwargs)\u001b[0m\n\u001b[0;32m 5521\u001b[0m resample=resample, **kwargs)\n\u001b[0;32m 5522\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 5523\u001b[1;33m \u001b[0mim\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_data\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5524\u001b[0m \u001b[0mim\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mset_alpha\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0malpha\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5525\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mim\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_clip_path\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32m~\\anaconda3\\lib\\site-packages\\matplotlib\\image.py\u001b[0m in \u001b[0;36mset_data\u001b[1;34m(self, A)\u001b[0m\n\u001b[0;32m 700\u001b[0m if (self._A.dtype != np.uint8 and\n\u001b[0;32m 701\u001b[0m not np.can_cast(self._A.dtype, float, \"same_kind\")):\n\u001b[1;32m--> 702\u001b[1;33m raise TypeError(\"Image data of dtype {} cannot be converted to \"\n\u001b[0m\u001b[0;32m 703\u001b[0m \"float\".format(self._A.dtype))\n\u001b[0;32m 704\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: Image data of dtype object cannot be converted to float"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"text_no_ocr = cv.imread(\"text_no_ocr.png\", cv.IMREAD_GRAYSCALE)\n",
"plt.figure(figsize=[10,10])\n",
"plt.subplot(121) \n",
"\n",
"plt.imshow(text_no_ocr, cmap='gray')\n"
]
},
{
"cell_type": "markdown",
"id": "03000213",
"metadata": {},
"source": [
"![Przykładowy wynik](img/text_no_ocr_sample_result.png)"
]
},
{
"cell_type": "markdown",
"id": "b3d03d84",
"metadata": {},
"source": [
"## Analiza połączonych komponentów\n",
"\n",
"Jeśli na naszym obrazie binarnym posiadamy zwarte grupy obiektów, to możemy im nadać etykiety i je policzyć. Na poniższym zdjęciu możemy policzyć litery napisu:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "e7aa03c0",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"bologna = cv.imread(\"img/bologna.png\", cv.IMREAD_GRAYSCALE)\n",
"_, bologna_bin = cv.threshold(bologna, 127, 255, cv.THRESH_BINARY)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"\n",
"plt.imshow(bologna_bin, cmap='gray');"
]
},
{
"cell_type": "markdown",
"id": "d6fb8e32",
"metadata": {},
"source": [
"Do nadania etykiet użyjemy funkcji [`cv.connectedComponents()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#gaedef8c7340499ca391d459122e51bef5):"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "ac906ff2",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"_, bologna_labels = cv.connectedComponents(bologna_bin)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"\n",
"plt.imshow(bologna_labels, cmap='gray')\n",
"plt.colorbar();"
]
},
{
"cell_type": "markdown",
"id": "7a6f7ac1",
"metadata": {},
"source": [
"Zauważmy, że wynikowy obraz ma 8 etykiet, gdzie 0 oznacza tło, a kolejne siedem są przypisane do poszczególnych liter. Możemy wyświetlić poszczególne fragmenty obrazu dotyczące danej etykiety:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "e26b2b00",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 864x504 with 8 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"bologna_n = bologna_labels.max()\n",
"\n",
"plt.figure(figsize=[12,7])\n",
"\n",
"for i in range(bologna_n+1):\n",
" plt.subplot(331+i)\n",
" plt.imshow(bologna_labels==i, cmap='gray')\n",
" plt.title(f\"Label: {i}\")"
]
},
{
"cell_type": "markdown",
"id": "6a682adc",
"metadata": {},
"source": [
"Do wygodnego wyświetlenia pokolorowanych etykiet możemy użyć map kolorów. Pracując z biblioteką Matplotlib możemy wyświetlić taki obraz wprost i użyć ew. odpowiedniej [mapy kolorów](https://matplotlib.org/stable/tutorials/colors/colormaps.html), np.:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d4f999b0",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1224x360 with 6 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=[17,5])\n",
"\n",
"plt.subplot(131)\n",
"plt.imshow(bologna_labels)\n",
"plt.title(\"Default\")\n",
"plt.colorbar()\n",
"plt.subplot(132)\n",
"plt.imshow(bologna_labels, cmap='gray')\n",
"plt.colorbar()\n",
"plt.title(\"Gray\")\n",
"plt.subplot(133)\n",
"plt.imshow(bologna_labels, cmap='inferno')\n",
"plt.colorbar()\n",
"plt.title(\"Inferno\");"
]
},
{
"cell_type": "markdown",
"id": "0e66a5e9",
"metadata": {},
"source": [
"Biblioteka OpenCV również posiada obsługę map kolorów, co może być pomocne gdybyśmy chcieli np. wyeksportować obraz. Na początku możemy przekonwertować obraz do przedziału `[0; 255]` (znajdujemy minimalną i maksymalną wartość przy pomocy [`cv.minMaxLoc()`](https://docs.opencv.org/4.5.3/d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707)), a następnie używamy funkcji [`cv.applyColorMap()`](https://docs.opencv.org/4.5.3/d3/d50/group__imgproc__colormap.html#gadf478a5e5ff49d8aa24e726ea6f65d15) podając wybraną [mapę](https://docs.opencv.org/4.5.3/d3/d50/group__imgproc__colormap.html#ga9a805d8262bcbe273f16be9ea2055a65) i otrzymując obraz BGR, np.:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "549f4e6c",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"val_min, val_max, _, _ = cv.minMaxLoc(bologna_labels)\n",
"bologna_labels_norm = 255 * (bologna_labels - val_min)/(val_max - val_min)\n",
"bologna_labels_norm = np.uint8(bologna_labels_norm)\n",
"\n",
"bologna_labels_turbo = cv.applyColorMap(bologna_labels_norm, cv.COLORMAP_TURBO)\n",
"plt.imshow(bologna_labels_turbo[:,:,::-1])\n",
"plt.title(\"Turbo\");"
]
},
{
"cell_type": "markdown",
"id": "d57ad348",
"metadata": {},
"source": [
"## Kontury"
]
},
{
"cell_type": "markdown",
"id": "1bb5892e",
"metadata": {},
"source": [
"W widzeniu komputerowym bardzo często chcemy nie tylko znaleźć pewne obiekty, ale również zaznaczyć ich obrys (kontury). Poniżej znajduje się kilka przykładów - będziemy co prawda działali na obrazie w skali odcieni szarości, aczkolwiek w pewnych zastosowaniach lepsze efekty dałaby praca na obrazie czarno-białym."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "66990cfa",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes = cv.imread(\"img/shapes.png\", cv.IMREAD_COLOR)\n",
"shapes_gray = cv.cvtColor(shapes, cv.COLOR_BGR2GRAY)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"\n",
"plt.subplot(121)\n",
"plt.imshow(shapes[:,:,::-1])\n",
"plt.title(\"Original\")\n",
"plt.subplot(122)\n",
"plt.imshow(shapes_gray, cmap='gray')\n",
"plt.title(\"Grayscale\");"
]
},
{
"cell_type": "markdown",
"id": "9757e0fd",
"metadata": {},
"source": [
"Przy pomocy [`cv.findContours()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#gadf1ad6a0b82947fa1fe3c3d497f260e0) uzyskujemy kontury obiektów oraz opcjonalną macierz opisującą ich hierarchię. Drugi parametr funkcji opisuje [sposób wyznaczania konturów](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga819779b9857cc2f8601e6526a3a5bc71), a trzeci [algorytm aproksymacji konturów](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga4303f45752694956374734a03c54d5ff)."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "16fe17f5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No. of contours: 11\n"
]
}
],
"source": [
"shapes_contours, _ = cv.findContours(shapes_gray, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)\n",
"print(f\"No. of contours: {len(shapes_contours)}\")"
]
},
{
"cell_type": "markdown",
"id": "48dbe624",
"metadata": {},
"source": [
"Przy pomocy [`cv.drawContours()`](https://docs.opencv.org/4.5.3/d6/d6e/group__imgproc__draw.html#ga746c0625f1781f1ffc9056259103edbc) możemy nanieść kontury na obraz. Zauważmy, że mamy tutaj oznaczone zewnętrzne i wewnętrzne kontury:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "772ef0bc",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_contours = shapes.copy()\n",
"\n",
"cv.drawContours(shapes_with_contours, shapes_contours, -1, (255,255,0), 2)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_contours[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "ff1ddbfc",
"metadata": {},
"source": [
"Możemy również ograniczyć się tylko do zewnętrznych konturów (parametr `cv.RETR_EXTERNAL`):"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "b937986e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No. of contours: 9\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_contours, _ = cv.findContours(shapes_gray, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n",
"print(f\"No. of contours: {len(shapes_contours)}\")\n",
"shapes_with_contours = shapes.copy()\n",
"\n",
"cv.drawContours(shapes_with_contours, shapes_contours, -1, (255,255,0), 2)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_contours[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "bb3ec6bb",
"metadata": {},
"source": [
"Poniżej mamy zaznaczony obrys konturu wybranego obiektu:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "49ca327f",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAWsAAAEyCAYAAAA8x/FHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAA+r0lEQVR4nO3dd3wc133v/c9vtqN3ohAgAZKiSJGURFFdtmR1W12JHJdcO7ESJbYVx891nms5zk2cmziPfW/i3MRdcmzLcSxFLopsucgqVrM6JYpVpFhAEgSIQrTtZeY8f+yShCiARNuK35svvLCY3Z35cbD47uyZM+eIMQallFKFzcp3AUoppU5Nw1oppYqAhrVSShUBDWullCoCGtZKKVUENKyVUqoIZC2sReRaEdkpIrtF5K5sbUcppRYCyUY/axFxAbuAq4Ae4GXg/caY7fO+MaWUWgCydWR9HrDbGLPXGJMA7gduytK2lFKq5LmztN424OCEn3uA8yc+QETuAO7I/HhOlupQSqliMmSMaZzsjmyFtUyy7C3tLcaYu4G7AUREr3lXSinYP9Ud2WoG6QHaJ/y8GOjN0raUUqrkZSusXwZWiEiniHiB9wE/zdK2lFKq5GWlGcQYkxKRO4FHABfwbWPMtmxsSymlFoKsdN2bcRHaZq2UUgAbjTEbJrtDr2BUSqkioGGtlFJFQMNaKaWKgIa1UiprPB43FZUBPB5Xvkspetm6KEYptYCICFW1PvwVKYykji1vavXS1FbF4YNjDB2OHn+88RINuhgfiU62OjWJkg7r+spK6ioqAEikUgyMjRFNJPJclVKlo66xnMrGOC6vTftyi6pGwZlwf1lVBI8vQl0nREPHl1tGGB0QDuwCJyWMD/gZG9bgPpmSC2u/18sZgQCVwSBtiQR14TAAccehz7YJ+nzsLyuje3SUQui2qFQxamz1U9uaoHVZkpoWBxGDryyCa4pE8ZWlv46LU14P9R3g2DB8KMXQIRdj/V4GDsaxbWfyFS1gJdXPut3n4wIROlIpvKkUbo43yhsgBTiWxbhlsdvl4tfx+HxsVqkFo7LGQ8cqi6alSWpbHbx+sFwgk40GNE3GgJMCOyVEg8KhnR62PZcgEct/NuXBlP2sS+bIutmyeJfj0JZM4uHtI0kJ4AFwHBoch0AqRYXHwxM+H6Oh0NvWp5Q6zuUSlq+pYdHKERo7wBtIB/RcQvooEXB5wOUxePwGbyCOvwpGDzawY+PQ3DdQIkoirOsti2vcbloTiUmD+kQClAOrk0lsY3gYsLNepVLFyeWG9ZdV0nHmCL7y9LL5COnJiIC/AjrXQbRzCG+ll63PJrBtThi3c+Ep+q57ZW437y4rozWRwMupg/ooIf2f77Jt3uHz4baKflcoNe98ATj7KhcdZ43jr5i/o+mTObqNQCV0nZ3gvOssFrWVY7myvOECV/QJtaamhvZQCO8snitAhTGcZgztZWWnfLxSC0lZNay9DDpW2yecHMwNESirgqXrHM66OkFbVxkud9FH1qwV/f98VSQyq6A+ygJqEwkWx+O4XdpxXymAilpYfSF0rAJ/efaPpk/GsqCuNcnqS5K0LPFjWQvzCLuow7qxspLKSGTO6/ECnYEA9YHA3ItSqshV1MLK84X21Rxr+sg3ywV1bQmWnpnAX57vavKjqMN6zaJF1MzDeiygmvRJR6UWskCFxenneulYbQjk+Yj6RJYLGpekWHa2C7cn39XkXlGHdYXLNW//ASuVwkqlTv1ApUqU22OxfG0lHWuSBCpACjAdAhXQdXaKVRtqCuqNJBeKuuueM489OIwIZqH99ouEz+ViXVMTHTU1Od92OJFg0+HDHM5cCVvKPD6HxmVjBdP0MRmxoLwalp8/St+eSoYGgvkuKWeKOqxDxmCYfne9qRgg5fFg29rbutBYIlxeU8N9fX1U9fXlfPtJ4LuBAJ8JBBiOlu7YFZYFay6soq5lvGCD+igRCFTB6ZckeO4hwbEXRgfsAvygM32vdHcTnIdXVgrojscZSibnXpSaV5YIy+vqqCb9ppzrLy/QHghQW+Inn8uqXFQ1j89bFz3HhngEYuG3fiXjYOZp2I/GJXGWrKian5UVgaI+sg7HYnRXVrImGGS2ne4MELEsDiWThLTNWi1Qp2/wU9c696Yex4ZEVBgb8HBod5Jk4q1HvZW1bpo7hYq6JB7f7JtbRNLt162rQ/Tu8xCPl/6BVlGHNcBGoN2yqHNm93ZtAz0iHNIrGNUCVddYTm17GK9/9uswJn3kPNLrofdN4UiPi+HBJM4JLYu+gND3prBoiZ+WFQkqG5zZb1egsd3Q2uVn3w4N64LXGwyysayMyyIRZtqbxwBBl4s3ysoYCi6cExVKTdS+ylDXPPvnGwPRcaF7s5e9r6cIjRns1OTjxsejSQ7vh+HDbg6+aVh9gZ+WFTG8s2hlEgFvmUN5femeS5io6A8nbWBLKsXrVVXM5L3VAGERNtbXs6uETxwpdSqe8giuWfZbNiY9qUD35gDbn08ydsTGTp36U24inmK4z/Da40l6dwZIzPJP0OWC+jaori394SKKPqwBgokET8ZiPB0IMCzC0QG6TjxHfHRZDOgBnmxu5sWhIRLaVq0WqLYltTR1zC0G+ve52Px0lHh05k2R4XGbTU/GGDlsMZuh9cWC+haLxraibyQ4pZL5H4YTCZ4FBmtrWRMO05ZMUgXI0VeACHFg0BgG6+r49cgIiTx0BVOqkDQuSVFZP/uub9Eg7H25Ejs1Out1xELCgS3l1CwKzrg3igjgSuC4S3+6vpIJ66N2joywE2hvaGBtIIBneBiJRnGqqxksK2PL0BCh4eF8l6lUQbAlfa5mNr0yHAcG9gboPzQ6txpsh8MHwizp99K4NDHjWkTSY26LMKuj82JRcmF91MGhIQ5OXDAykv5SSs2L8Cgc2OrBmLmf84mFLPp2u6hqYsYDNXn9sKjdT+9OCAdjc66lUJVEm7VSKveCw3D40Pi8rCsRTzHYGyU+i0E0LRfUNvqprintC5c0rJVaoPwBL5V1FqVwiYGIQawSbgNBw1qpBatxUQ2NrZ6CHF1PvZ3+mpRaoLw+N26PFPzATSpNw1qpBaqvZ5jRocScBlaa15zXN42T0rBWaoGKhGMMHHSY7cjAda3QdXrdvNQSKPOwZEUFZdUzf64xYKfALvHhQTSslVKz4i+DtjPCeLxzn2i6vMbQ2BnHM4vZr+0kHD4QZvhIaU8QoWGt1AImc4yAurY47Svm1mXO7RHalnuoqJvdoXEyASODKRIlPkzqnH5TItItIltEZJOIvJJZVicij4rIm5nvtfNTqlJqvoldPafA9vhh2TlRGtt8s9u+QNsyL4tXx3HP4qga0m84MuMxN4vPfBxZv8sYc5YxZkPm57uAx40xK4DHMz8rpQpQf7dDNGjmdJl2bZvNmncYFnXMfGDqpavKWHWxQ2X97M5yGgeiQRexsTkMxl0kstEMchNwb+b2vcDNWdiGUmoeDPSOM3Bg9kktAm4PNHYmWPPOFF1r/fh8pz7KragKsOZiL6suiVPbksQ1y4Ev7BT07knR31Pa7dUw97FBDPBrETHAN40xdwOLjDF9AMaYPhFpmmuRSqnscByDiTSBGZh117mjgd20NEX1IpuO1R4Oba9h3xtBUsm3djWpqgmwdLWb5pURahbZuD3M+qIcY9IBlIxbb9tOKZprWF9sjOnNBPKjIvLGdJ8oIncAd8xx+0qpOdr2YohFq6BiDmeXREBc4C83tK5MUN+eoGUVpE4451deHaW2JR3uR583F6EjFqMHK4HRua2oCMwprI0xvZnvAyLyIHAe0C8iLZmj6hZgYIrn3g3cDZA5MldK5UFwPMLhPV661ifmPE7I0fD1l0P7qrnXNhVj0pPz9u4WDu0fzd6GCsisfzUiUi4ilUdvA1cDW4GfAh/OPOzDwENzLVIplV0HtgQIDRdXT96xQRjYU5HvMnJmLkfWi4AHJf1W6gZ+YIz5lYi8DDwgIrcDB4Db5l6mUiqbDveM0bMtwGkXRY81URQyOwl9uwL07h/Ldyk5M+uwNsbsBc6cZPkR4Iq
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_contours = shapes.copy()\n",
"\n",
"cv.drawContours(shapes_with_contours, [shapes_contours[5]], -1, (255,255,0), 2)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_contours[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "1b665cc1",
"metadata": {},
"source": [
"Poniżej możemy zobaczyć jak przy pomocy tzw. [momentów](https://en.wikipedia.org/wiki/Image_moment) są wyliczane środki ciężkości poszczególnych konturów. Każdy kontur jest również opisany żółtą etykietą liczbową, ale w związku z tym, że czasem mamy kontur zewnętrzny i wewnętrzny blisko siebie, to niektóre etykiety nakładają się na siebie. Dodatkowo, tym razem kontury wykryjemy z informacją o drzewiastej hierarchii (parametr `cv.RETR_TREE`, za chwilę opiszemy co tam się znajduje)."
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "a4b88578",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_contours, shapes_hierarchy = cv.findContours(shapes_gray, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)\n",
"shapes_with_contours = shapes.copy()\n",
"\n",
"cv.drawContours(shapes_with_contours, shapes_contours, -1, (255,255,0), 2)\n",
"\n",
"for idx, contour in enumerate(shapes_contours):\n",
" M = cv.moments(contour)\n",
" x = int(round(M[\"m10\"]/M[\"m00\"]))\n",
" y = int(round(M[\"m01\"]/M[\"m00\"]))\n",
" \n",
" cv.circle(shapes_with_contours, (x,y), 5, (255,255,255), -1)\n",
" cv.putText(shapes_with_contours, str(idx), (x+10, y+10), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 200, 255), 2)\n",
" \n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_contours[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "9d0b0e26",
"metadata": {},
"source": [
"W zmiennej `shapes_hierarchy` mamy macierz opisującą hierarchię konturów. Dla każdego wiersza (konturu) kolejne kolumny opisują odpowiednio: indeks następnego konturu, indeks poprzedniego konturu, indeks pierwszego dziecka oraz indeks rodzica (wartość ujemna oznacza, że dane pole nie ma zastosowania)."
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "af88fd07",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[[ 1 -1 -1 -1]\n",
" [ 2 0 -1 -1]\n",
" [ 3 1 -1 -1]\n",
" [ 5 2 4 -1]\n",
" [-1 -1 -1 3]\n",
" [ 6 3 -1 -1]\n",
" [ 7 5 -1 -1]\n",
" [ 8 6 -1 -1]\n",
" [ 9 7 -1 -1]\n",
" [-1 8 10 -1]\n",
" [-1 -1 -1 9]]]\n"
]
}
],
"source": [
"print(shapes_hierarchy)"
]
},
{
"cell_type": "markdown",
"id": "4532e4ef",
"metadata": {},
"source": [
"Przy pomocy [`cv.contourArea()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga2c759ed9f497d4a618048a2f56dc97f1) i [`cv.arcLength()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga8d26483c636be6b35c3ec6335798a47c) możemy policzyć odpowiednio pole powierzchni i obwód kształtu:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "1486063c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Contour id 0: area = 1063.0, perimeter = 161.4\n",
"Contour id 1: area = 8017.5, perimeter = 390.0\n",
"Contour id 2: area = 375.0, perimeter = 133.0\n",
"Contour id 3: area = 1750.0, perimeter = 170.0\n",
"Contour id 4: area = 556.0, perimeter = 95.7\n",
"Contour id 5: area = 2917.0, perimeter = 244.7\n",
"Contour id 6: area = 729.5, perimeter = 185.6\n",
"Contour id 7: area = 1922.0, perimeter = 175.7\n",
"Contour id 8: area = 380.5, perimeter = 73.4\n",
"Contour id 9: area = 2596.5, perimeter = 191.6\n",
"Contour id 10: area = 407.0, perimeter = 75.6\n"
]
}
],
"source": [
"for idx, contour in enumerate(shapes_contours):\n",
" area = cv.contourArea(contour)\n",
" perimeter = round(cv.arcLength(contour, True), 1)\n",
" print(f\"Contour id {idx: >2}: area = {area: >6}, perimeter = {perimeter: >5}\")"
]
},
{
"cell_type": "markdown",
"id": "0068e697",
"metadata": {},
"source": [
"Dla znalezionych kształtów często chcemy wyznaczyć ramkę ograniczającą i możemy to zrobić na kilka sposobów. Poniżej przy pomocy [`cv.boundingRect()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga103fcbda2f540f3ef1c042d6a9b35ac7) i [`cv.rectangle()`](https://docs.opencv.org/4.5.3/d6/d6e/group__imgproc__draw.html#ga07d2f74cadcf8e305e810ce8eed13bc9) nanosimy prostokąty:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "8004a7ad",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_bb = shapes_with_contours.copy()\n",
"for contour in shapes_contours:\n",
" x,y,w,h = cv.boundingRect(contour)\n",
" cv.rectangle(shapes_with_bb, (x,y), (x+w,y+h), (255,0,255), 2)\n",
" \n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_bb[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "41314b68",
"metadata": {},
"source": [
"Czasami wygodniej jest umieścić minimalny obrys prostokąta, co możemy uzyskać przy pomocy [`cv.minAreaRect()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga3d476a3417130ae5154aea421ca7ead9) i [`cv.boxPoints()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#gaf78d467e024b4d7936cf9397185d2f5c):"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "35ad082f",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_bb = shapes_with_contours.copy()\n",
"for contour in shapes_contours:\n",
" rect = cv.minAreaRect(contour)\n",
" box_points = np.int0(cv.boxPoints(rect))\n",
" cv.drawContours(shapes_with_bb, [box_points], -1, (255,0,255), 2)\n",
" \n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_bb[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "ca930b9f",
"metadata": {},
"source": [
"Poniżej mamy przykład z okręgiem przy pomocy [`cv.minEnclosingCircle()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#ga8ce13c24081bbc7151e9326f412190f1):"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "459140d5",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_bb = shapes_with_contours.copy()\n",
"for contour in shapes_contours:\n",
" (x,y), radius = cv.minEnclosingCircle(contour)\n",
" cv.circle(shapes_with_bb, (int(x),int(y)), int(round(radius)), (255,0,255), 2)\n",
" \n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_bb[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "6c4e88d2",
"metadata": {},
"source": [
"Możemy również umieścić elipsy przy pomocy [`cv.fitEllipse()`](https://docs.opencv.org/4.5.3/d3/dc0/group__imgproc__shape.html#gaf259efaad93098103d6c27b9e4900ffa), ale w tym przypadku kontur musi składać się z co najmniej 5 punktów:"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "4a46cbcd",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"shapes_with_bb = shapes_with_contours.copy()\n",
"for contour in shapes_contours:\n",
" if len(contour) < 5:\n",
" continue\n",
" ellipse = cv.fitEllipse(contour)\n",
" cv.ellipse(shapes_with_bb, ellipse, (255,0,255), 2)\n",
" \n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_bb[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "e925fb4d",
"metadata": {},
"source": [
"## Wykrywanie obszarów/plam\n",
"\n",
"Do wykrywania obszarów/plam (ang. *blobs*) posiadających wspólne cechy (np. rozmiar, kształt, wartości pikseli) możemy użyć [`cv.SimpleBlobDetector_create()`](https://docs.opencv.org/4.5.3/d0/d7a/classcv_1_1SimpleBlobDetector.html#a1d7a06c8b8749207a978e42cd8d0cdf6), a następnie używamy metody `detect()`. W poniższym przykładzie użyjemy domyślnych wartości detektora."
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "cad48f62",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"blobs_gray = cv.imread(\"img/blobs.png\", cv.IMREAD_GRAYSCALE)\n",
" \n",
"blob_detector = cv.SimpleBlobDetector_create()\n",
"\n",
"keypoints = blob_detector.detect(blobs_gray)\n",
"\n",
"blobs_color = cv.cvtColor(blobs_gray, cv.COLOR_GRAY2BGR)\n",
" \n",
"for kp in keypoints:\n",
" x, y = kp.pt\n",
" x = int(round(x))\n",
" y = int(round(y))\n",
"\n",
" radius = int(round(kp.size/2))\n",
"\n",
" cv.circle(blobs_color, (x,y), radius, (0,0,255), 3)\n",
"\n",
"plt.figure(figsize=[15,5])\n",
"plt.subplot(121)\n",
"plt.imshow(blobs_gray, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(122)\n",
"plt.imshow(blobs_color[:,:,::-1])\n",
"plt.title(\"Blobs\");"
]
},
{
"cell_type": "markdown",
"id": "b5639883",
"metadata": {},
"source": [
"Parametry ustawia się poprzez atrybuty obiektu zwracanego przez [`cv.SimpleBlobDetector_Params()`](https://docs.opencv.org/4.5.3/d8/da7/structcv_1_1SimpleBlobDetector_1_1Params.html). Po ustawieniu parametrów obiekt z parametrami przekazuje się jako argument `cv.SimpleBlobDetector_create()`.\n",
"\n",
"Detektor działa następująco:\n",
"\n",
"1. Obraz źródłowy jest przekształcany do obrazów binarnych poprzez progowanie z wartościami odcięcia od `minThreshold` do `maxThreshold` z krokiem `thresholdStep`.\n",
"2. Dla każdego obrazu binarnego znajdowane są połączone komponenty przy pomocy `cv.findContours()` oraz obliczane są współrzędne ich środków.\n",
"3. Środki z kilku obrazów binarnych są grupowane na podstawie ich współrzędnych. Te, które znajdują się blisko siebie, odpowiadają jednej plamie/obszarowi (kontroluje się to poprzez parametr `minDistBetweenBlobs`).\n",
"4. Na podstawie wyznaczonych wcześniej grup obliczane są końcowe współrzędne środków plam/obszarów oraz ich promienie, tak by zwrócić je jako lokalizacje i rozmiary punktów kluczowych.\n",
"\n",
"Detektor dokonuje kilku filtracji zwracanych plam/obszarów. Poszczególne filtry ustawia się poprzez parametry `filterBy*` nadając im wartość `True` lub `False`. Można filtrować według:\n",
"\n",
"1. koloru (`filterByColor = True`), tj. następuje porównanie intensywności środka plamy/obszaru z obrazu binarnego do wartości ustawionej w `blobColor`; jeśli są różne, to plama/obszar jest odfiltrowana; wartość `blobColor = 0` wyodrębnia czarne plamy/obszary, a `blobColor = 255` jasne,\n",
"2. powierzchni (`filterByArea = True`), tj. plamy/obszary mają mieć powierzchnię między `minArea` a `maxArea`; np. ustawienie `minArea = 100` spowoduje odfiltrowanie plam/obszarów, których powierzchnia stanowi mniej niż 100 pikseli,\n",
"3. okrągłości (`filterByCircularity = True`), tj. miara okrągłości plamy/obszaru `4 * pi * pole powierzchni / obwód^2` ma być między `minCircularity` a `maxCircularity`; np. regularny sześciokąt ma większą okrągłość niż kwadrat; np. okrąg ma miarę `1.0`, a kwadrat ok. `0.785`,\n",
"4. inercji (`filterByInertia = True`), tj. jej wartość ma się znaleźć między `minInertiaRatio` a `maxInertiaRatio`; miara ta określa jak bardzo wydłużony jest dany kształt, np. dla okręgu wartość ta wynosi 1, dla elipsy mieści się w przedziale od 0 do 1, a dla linii wynosi 0; aby odfiltrować po inercji można ustawić `0 ≤ minInertiaRatio ≤ 1` oraz `maxInertiaRatio ≤ 1`,\n",
"5. wypukłości (`filterByConvexity = True`), tj. `pole powierzchni / pole powierzchni otoczki wypukłej` ma być między `minConvexity` a `maxConvexity`; aby odfiltrować po wypukłości można ustawić `0 ≤ minConvexity ≤ 1` oraz `maxConvexity ≤ 1`.\n",
"\n",
"Domyślne wartości parametrów są dostrojone do ekstrakcji ciemnych, okrągłych plam.\n",
"\n",
"Poniżej znajduje się przykład skonfigurowania parametrów pod kątem progu i minimalnego pola powierzchni:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "1fb61f3c",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"params = cv.SimpleBlobDetector_Params()\n",
"params.minThreshold = 200\n",
"params.maxThreshold = 255\n",
"params.filterByArea = True\n",
"params.minArea = 2000\n",
"\n",
"blob_detector = cv.SimpleBlobDetector_create(params)\n",
"\n",
"keypoints = blob_detector.detect(blobs_gray)\n",
"\n",
"blobs_color = cv.cvtColor(blobs_gray, cv.COLOR_GRAY2BGR)\n",
" \n",
"for kp in keypoints:\n",
" x, y = kp.pt\n",
" x = int(round(x))\n",
" y = int(round(y))\n",
"\n",
" radius = int(round(kp.size/2))\n",
"\n",
" cv.circle(blobs_color, (x,y), radius, (0,0,255), 3)\n",
"\n",
"plt.figure(figsize=[15,5])\n",
"plt.subplot(121)\n",
"plt.imshow(blobs_gray, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(122)\n",
"plt.imshow(blobs_color[:,:,::-1])\n",
"plt.title(\"Blobs\");"
]
},
{
"cell_type": "markdown",
"id": "af69ebc8",
"metadata": {},
"source": [
"### Zadanie 2\n",
"\n",
"Spróbuj wykryć i oznaczyć monety z pliku `img/coins.png`. Przykładowy wynik znajduje się poniżej (użyto schematu kolorów *inferno*, kolejność wykrytych monet nie jest istotna)."
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "94d29296",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"params = cv.SimpleBlobDetector_Params()\n",
"params.minThreshold = 100\n",
"params.maxThreshold = 255\n",
"params.filterByArea = True\n",
"params.minArea = 500\n",
"params.minConvexity = 0.36\n",
"params.maxArea = 50000\n",
"\n",
"blobs_gray = cv.imread(\"img/coins.png\", cv.IMREAD_GRAYSCALE)\n",
"\n",
"blob_detector = cv.SimpleBlobDetector_create(params)\n",
"\n",
"keypoints = blob_detector.detect(blobs_gray)\n",
"\n",
"blobs_color = cv.cvtColor(blobs_gray, cv.COLOR_GRAY2BGR)\n",
"image_empty = np.zeros((358, 538, 3), dtype='uint8')\n",
"for kp in keypoints:\n",
" x, y = kp.pt\n",
" x = int(round(x))\n",
" y = int(round(y))\n",
"\n",
" radius = int(round(kp.size/2))\n",
"\n",
" cv.circle(image_empty, (x,y), radius, (255,255,255), -1)\n",
"\n",
"image_empty = cv.cvtColor(image_empty, cv.COLOR_BGR2GRAY)\n",
"_, image_empty = cv.connectedComponents(image_empty)\n",
"\n",
"\n",
"\n",
"plt.figure(figsize=[15,5])\n",
"plt.subplot(121)\n",
"plt.imshow(blobs_gray, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(122)\n",
"plt.imshow(image_empty , cmap='inferno')\n",
"plt.title(\"Blobs\");"
]
},
{
"cell_type": "markdown",
"id": "b826a305",
"metadata": {},
"source": [
"![Wykryte monety](img/coins_detected.png)"
]
}
],
"metadata": {
"author": "Andrzej Wójtowicz",
"email": "andre@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3",
"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.8"
},
"subtitle": "02. Operacje binarne na obrazach [laboratoria]",
"title": "Widzenie komputerowe",
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}