wko/wko-02.ipynb

1344 lines
4.3 MiB
Plaintext
Raw Normal View History

2023-01-16 09:35:16 +01:00
{
"cells": [
{
"cell_type": "markdown",
"id": "46f39503",
"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": "c8f8f691",
"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": 39,
"id": "0ddcac8e",
"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": "89072615",
"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": 40,
"id": "6bf564d2",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA0QAAAGiCAYAAADHmwaYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9d5ikVbU9vCrn6hwnBxiSoIQBySgIcpEgOYP+EFAuV/y4CoLoRbkY4CoqhgsKiiiIGZSkEg14JSkKzjBMnp7u6enuyqmr6vujn3V6vadrYICZ7unhXc/TT3dXvWGf8Fbtddbe+3jq9XodLly4cOHChQsXLly4cPEWhHeqDXDhwoULFy5cuHDhwoWLqYJLiFy4cOHChQsXLly4cPGWhUuIXLhw4cKFCxcuXLhw8ZaFS4hcuHDhwoULFy5cuHDxloVLiFy4cOHChQsXLly4cPGWhUuIXLhw4cKFCxcuXLhw8ZaFS4hcuHDhwoULFy5cuHDxloVLiFy4cOHChQsXLly4cPGWhUuIXLhw4cKFCxcuXLhw8ZaFS4hcuHgL4LzzzsPcuXOn2gwXLly4cDEJ8Hg8+MxnPjPVZrhwMW3gEiIX2z2WL1+OSy65BDvuuCOi0Sii0Sh22WUXfOQjH8Hf/va3qTbPhQsXLly4eE3cfvvt8Hg8jp/Ozk4cdthhuP/++6faPBcupjX8U22ACxdbE/fddx9OPfVU+P1+nHnmmdhjjz3g9Xrx0ksv4Wc/+xm++c1vYvny5ZgzZ85Um+rChQsXLly8Jq699lrMmzcP9Xod/f39uP3223H00Ufj3nvvxTHHHAMAKBQK8PtdF8+Fi82F+7S42G6xbNkynHbaaZgzZw5+97vfoaenx/H+F77wBXzjG9+A17tpoTSXyyEWi21tU124cOHChYvNwnvf+17svffe5v8PfvCD6Orqwo9+9CNDiMLh8KTbVa/XUSwWEYlEJv3eLly8Wbghcy62W3zxi19ELpfDbbfdNoEMAYDf78ell16KWbNmARjLs4nH41i2bBmOPvpoJBIJnHnmmQCAJ554AieffDJmz56NUCiEWbNm4bLLLkOhUDDXu+222+DxePDss89OuNd///d/w+fzYe3atQCApUuX4sQTT0R3dzfC4TBmzpyJ0047DalUynHeD37wAyxevBjRaBQtLS04+OCD8dBDD5n3f/nLX+Lf/u3f0Nvbi1AohAULFuCzn/0sqtXqa/ZPrVbDV77yFey6664Ih8Po6urChRdeiOHh4c3oXRcuXLhwsS2gubkZkUjEoQjZOUSf+cxn4PF48PLLL+O8885Dc3MzmpqacP755yOfzzuud9ttt+Fd73oXOjs7EQqFsMsuu+Cb3/zmhPvOnTsXxxxzDB588EHsvffeiEQi+Pa3v41DDjkEe+yxR0NbFy1ahCOPPHLLNNyFiy0IVyFysd3ivvvuw8KFC7Hvvvtu9jmjo6M48sgjceCBB+KGG25ANBoFANxzzz3I5/O4+OKL0dbWhr/85S/42te+hjVr1uCee+4BAJx00kn4yEc+gjvvvBPveMc7HNe98847ceihh2LGjBkol8s48sgjUSqV8O///u/o7u7G2rVrcd9992FkZARNTU0AgP/6r//CZz7zGey///649tprEQwG8dRTT+H3v/893vOe9wAYiymPx+P42Mc+hng8jt///ve45pprkE6n8aUvfelV23rhhRfi9ttvx/nnn49LL70Uy5cvx9e//nU8++yz+MMf/oBAILDZ/ebChQsXLiYHqVQKg4ODqNfrGBgYwNe+9jVks1mcddZZr3nuKaecgnnz5uH666/HM888g1tvvRWdnZ34whe+YI755je/iV133RXHHnss/H4/7r33Xnz4wx9GrVbDRz7yEcf1/vWvf+H000/HhRdeiAsuuACLFi1CPB7HBRdcgBdeeAG77babOfb//u//sGTJElx99dVbrjNcuNhSqLtwsR0ilUrVAdSPP/74Ce8NDw/XN2zYYH7y+Xy9Xq/Xzz333DqA+hVXXDHhHB6juP766+sej6e+cuVK89rpp59e7+3trVerVfPaM888UwdQv+222+r1er3+7LPP1gHU77nnnk3av3Tp0rrX662fcMIJjmvV6/V6rVZ7VbsuvPDCejQarReLRfPaueeeW58zZ475/4knnqgDqN95552Ocx944IGGr7tw4cKFi6nFbbfdVgcw4ScUCtVvv/12x7EA6p/+9KfN/5/+9KfrAOof+MAHHMedcMIJ9ba2Nsdrjb5XjjzyyPr8+fMdr82ZM6cOoP7AAw84Xh8ZGamHw+H6Jz7xCcfrl156aT0Wi9Wz2exmt9mFi8mCGzLnYrtEOp0GAMTj8QnvHXrooejo6DA/N998s+P9iy++eMI5GhOdy+UwODiI/fffH/V63REid84552DdunV45JFHzGt33nknIpEITjzxRAAwCtCDDz44IVSB+MUvfoFarYZrrrlmQo6Tx+NpaFcmk8Hg4CAOOugg5PN5vPTSSw2vDYwpXk1NTTjiiCMwODhofvbaay/E43GH/S5cuHDhYtvBzTffjIcffhgPP/wwfvCDH+Cwww7D//t//w8/+9nPXvPciy66yPH/QQcdhI0bN5rvTMD5vUI16pBDDsErr7wyIax73rx5E0LgmpqacNxxx+FHP/oR6vU6AKBareLuu+/G8ccf7+blutgm4RIiF9slEokEACCbzU5479vf/rb5IrHh9/sxc+bMCa+vWrUK5513HlpbWxGPx9HR0YFDDjkEABxfEEcccQR6enpw5513AhjL0/nRj36E4447ztg0b948fOxjH8Ott96K9vZ2HHnkkbj55psd11m2bBm8Xi922WWXV23nP/7xD5xwwgloampCMplER0eHCZuwv7gUS5cuRSqVQmdnp4McdnR0IJvNYmBg4FXv68KFCxcupgaLFy/G4YcfjsMPPxxnnnkmfv3rX2OXXXbBJZdcgnK5/Krnzp492/F/S0sLADhyR//whz/g8MMPRywWQ3NzMzo6OvDJT34SwMTvlXnz5jW8zznnnINVq1bhiSeeAAD89re/RX9/P84+++zX11gXLiYJbg6Ri+0STU1N6OnpwQsvvDDhPeYUrVixYsJ7oVBogiJTrVZxxBFHYGhoCJ/4xCew0047IRaLYe3atTjvvPNQq9XMsT6fD2eccQZuueUWfOMb38Af/vAHrFu3bkJs94033ojzzjsPv/zlL/HQQw/h0ksvxfXXX48///nPDQlZI4yMjOCQQw5BMpnEtddeiwULFiAcDuOZZ57BJz7xCYddNmq1Gjo7Ow1xs9HR0bFZNrhw4cKFi6mF1+vFYYcdhptuuglLly7FrrvuusljfT5fw9ep5Cxbtgzvfve7sdNOO+F//ud/MGvWLASDQfzmN7/Bl7/85QnfK5uqKHfkkUeiq6sLP/jBD3DwwQfjBz/4Abq7u3H44Ye/wVa6cLF14RIiF9st/u3f/g233nor/vKXv2Dx4sVv+Dp///vfsWTJEnzve9/DOeecY15/+OGHGx5/zjnn4MYbb8S9996L+++/Hx0dHQ2r6rztbW/D2972Nlx99dX44x//iAMOOADf+ta38LnPfQ4LFixArVbDP//5T7z97W9veJ9HH30UGzduxM9+9jMcfPDB5vXly5e/ZpsWLFiA3/72tzjggAPcEqkuXLhwMc0xOjoKoHFUxOvBvffei1KphF/96lcONen1hlFzcfD222/HF77wBfziF7/ABRdcsElC5sLFVMMNmXOx3eLjH/84otEoPvCBD6C/v3/C+1wRey3wA1yPr9fruOmmmxoev/vuu2P33XfHrbfeip/+9Kc47bTTHOVQ0+m0+fIi3va2t8Hr9aJUKgEAjj/+eHi9Xlx77bUTVuRoRyO7yuUyvvGNb7xmm0455RRUq1V89rOfnfDe6OgoRkZGXvMaLly4cOFi6lGpVPDQQw8hGAxi5513flPXavS9kkqlcNttt73ua5199tkYHh7GhRdeuNlV8Fy4mCq4CpGL7RY77LADfvjDH+L000/HokWLcOaZZ2KPPfZAvV7H8uXL8cMf/hBer/c1Q9R
"text/plain": [
"<Figure size 1000x1000 with 2 Axes>"
]
},
"metadata": {},
"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": "795796a4",
"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": 41,
"id": "f4c60175",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1500x1000 with 12 Axes>"
]
},
"metadata": {},
"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": "880d9cd6",
"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": 42,
"id": "2e63a031",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1500x1000 with 12 Axes>"
]
},
"metadata": {},
"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": "462814e3",
"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": "b03f9b25",
"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": 43,
"id": "a3f15b79",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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": "19fc2684",
"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": 44,
"id": "45748934",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x800 with 4 Axes>"
]
},
"metadata": {},
"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": "8353e60e",
"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": 45,
"id": "8ca44988",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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5XK50NraijFjxsDr9WLHjh3CvIH9lqy0tDSccsopaG1tpZ8RI0bAbrfH1V+FChUqVBw6WL58Od577z289957eO6553DSSSfhb3/7G1599dWE11566aVx/8eMGYO2tjb6zgTi3yvEyjR27Fjs2bOni2t2aWlpFze2tLQ0/PWvf8WaNWsQi8UAAJFIBC+++CImTZqkrqNVcdChkh8Vf0ikpKQAANxud5dzjz/+OH1p8NDr9ejVq1eX4zU1NTj//PORmZkJu92OnJwcjB07FgDiXgannHIKevTogdWrVwPYv65mzZo1+Otf/0rrVFpaimuuuQZPPvkksrOzMX78eCxfvjwun927d0Or1WLgwIGK7fzpp58wefJkpKWlITU1FTk5OdT1gX9JsaisrERnZydyc3PjiGBOTg7cbjeam5sVy1WhQoUKFQcHxxxzDMaNG4dx48Zh9uzZeOuttzBw4EDMnz8fwWBQ8dqioqK4/xkZGQAQt9bz888/x7hx42Cz2ZCeno6cnBzceOONALq+V0pLS4XlzJkzBzU1Nfj0008BAO+//z6amppw3nnnda+xKlT8BlDX/Kj4QyItLQ09evTA1q1bu5wja4Cqqqq6nDOZTF0sLZFIBKeccgra29tx/fXXo3///rDZbKirq8P555+PaDRK0+p0OsyaNQtPPPEEHn30UXz++eeor6/v4ot933334fzzz8cbb7yBd999F1deeSWWLl2Kr776Ski+RHA4HBg7dixSU1Nxxx13oKysDGazGd999x2uv/76uHrxiEajyM3NpSSNR05OTlJ1UKFChQoVBxdarRYnnXQSHnzwQVRWVmLQoEHStDqdTnicWGh2796Nk08+Gf3798f999+PwsJCGI1G/N///R8eeOCBLu8VWWS38ePHIy8vD8899xxOOOEEPPfcc8jPz8e4ceN+YStVqDhwUMmPij8sJk6ciCeffBIbN27EMccc84vz+fHHH1FRUYGnn34ac+bMocffe+89Yfo5c+bgvvvuw7p16/D2228jJydHGN1myJAhGDJkCG6++WZ88cUXOO644/DYY4/hzjvvRFlZGaLRKLZt24bhw4cLy/n444/R1taGV199FSeccAI9vnfv3oRtKisrw/vvv4/jjjtODUuqQoUKFYc5wuEwALG3Q3ewbt06BAIBvPnmm3FWou66QhNF4KpVq/Cvf/0Lr7/+Oi666CIp+VKh4veE6vam4g+L6667DlarFRdccAGampq6nCearkQgD2s2fSwWw4MPPihMP3ToUAwdOhRPPvkkXnnlFcyYMSMuBKnT6aQvKoIhQ4ZAq9UiEAgAACZNmgStVos77riji6aN1ENUr2AwiEcffTRhm6ZPn45IJIIlS5Z0ORcOh+FwOBLmoUKFChUqDj5CoRDeffddGI1GDBgw4FflJXqvdHZ2YuXKld3O67zzzkNHRwcuueSSpKPRqVDxe0C1/Kj4w6Jv3754/vnnMXPmTPTr1w+zZ8/GsGHDEIvFsHfvXjz//PPQarUJ3cz69++PsrIyLFy4EHV1dUhNTcUrr7yiuB/OnDlzsHDhQgDo8sD/8MMPMX/+fEybNg3l5eUIh8N49tlnodPpaFCEPn364KabbsKSJUswZswYnH322TCZTPjmm29QUFCApUuXYvTo0cjIyMDcuXNx5ZVXQqP
"text/plain": [
"<Figure size 1000x800 with 4 Axes>"
]
},
"metadata": {},
"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": "7fb63be6",
"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": "57e6d811",
"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": 46,
"id": "ed726508",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x1000 with 2 Axes>"
]
},
"metadata": {},
"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": "70a4d3ed",
"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": 47,
"id": "8df7f100",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x127d14f24c8>"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAZgAAAGdCAYAAAAv9mXmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAAARdUlEQVR4nO3dX2jV9/348deJkljanEPTTkswWcs2NorEMf8RChurWYuU0u5qF4VlbjcbsSjebLmZ7CrCbjpWKbJCdzOxrKCFgnPiZkKhUqsEXKGFQmEBp2lvzomBHUvy+V78IL+v36o9J+aVc07yeMC5OB8/J+8Xn6Z58jnvHC0VRVEEAKywrlYPAMDaJDAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQYuNqL7i4uBjXrl2L3t7eKJVKq708APehKIqYm5uL/v7+6Oq69z3Kqgfm2rVrMTAwsNrLArCCZmZmYuvWrfc8Z9UD09vbu9pLssZVq9VWj9ARKpVKq0dgDWnkZ/mqB8bbYqy0crnc6hFg3WnkZ7lNfgBSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEgxbICc+zYsXj88cdj06ZNsWfPnnj//fdXei4AOlzTgXnzzTfj8OHDceTIkbhy5Ups3749nn322Zidnc2YD4AOVSqKomjmBXv27Ildu3bFq6++GhERi4uLMTAwEC+//HL85je/+crX12q1qFQqy5sW7qDJb+F1q1QqtXoE1pBqtRrlcvme5zR1B3Pr1q24fPlyjIyM/P8v0NUVIyMj8d577y1vSgDWpI3NnPz555/HwsJCbNmy5bbjW7ZsiY8++uiOr6nX61Gv15ee12q1ZYwJQKdJ/y2yiYmJqFQqS4+BgYHsJQFoA00F5tFHH40NGzbEjRs3bjt+48aNeOyxx+74mvHx8ahWq0uPmZmZ5U8LQMdoKjDd3d2xY8eOOH/+/NKxxcXFOH/+fAwPD9/xNT09PVEul297ALD2NbUHExFx+PDhGB0djZ07d8bu3bvjlVdeifn5+di/f3/GfAB0qKYD85Of/CQ+++yz+O1vfxvXr1+P7373u/G3v/3tSxv/AKxvTX8O5n75HAwrzedgGuNzMKykFf8cDAA0SmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNAiqYDMzU1Fc8//3z09/dHqVSK06dPJ4wFQKdrOjDz8/Oxffv2OHbsWMY8AKwRG5t9wb59+2Lfvn0ZswCwhtiDASBF03cwzarX61Gv15ee12q17CUBaAPpdzATExNRqVSWHgMDA9lLAtAG0gMzPj4e1Wp16TEzM5O9JABtIP0tsp6enujp6cleBoA203Rgbt68GZ988snS808//TSmp6ejr68vBgcHV3Q4ADpXqSiKopkXXLhwIX74wx9+6fjo6Gj8+c9//srX12q1qFQqzSwJ99Tkt/C6VSqVWj0Ca0i1Wo1yuXzPc5oOzP0SGFaawDRGYFhJjQTG52AASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0CKja1auFqtRrlcbtXysO4URdHqEVgDarVaVCqVhs51BwNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFE0FZmJiInbt2hW9vb2xefPmePHFF+Pjjz/Omg2ADtZUYCYnJ2NsbCwuXrwY586diy+++CKeeeaZmJ+fz5oPgA5VKoqiWO6LP/vss9i8eXNMTk7G97///YZeU6vVolKpRLVajXK5vNylAWiBZn6Gb7yfharVakRE9PX13fWcer0e9Xr9tuEAWPuWvcm/uLgYhw4diqeeeiq2bdt21/MmJiaiUqksPQYGBpa7JAAdZNlvkf3qV7+KM2fOxLvvvhtbt26963l3uoMZGBjwFhlAB0p/i+zAgQPxzjvvxNTU1D3jEhHR09MTPT09y1kGgA7WVGCKooiXX345Tp06FRcuXIgnnngiay4AOlxTgRkbG4sTJ07E22+/Hb29vXH9+vWIiKhUKvHAAw+kDAhAZ2pqD6ZUKt3x+BtvvBE/+9nPGvoafk0ZoHOl7cHcx0dmAFhn/F1kAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEgxcZWLVypVFq1NGtMURStHqEjlEqlVo/AOuMOBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApmgrMa6+9FkNDQ1Eul6NcLsfw8HCcOXMmazYAOlhTgdm6dWscPXo0Ll++HB988EE8/fTT8cILL8SHH36YNR8AHapUFEVxP1+gr68vfv/738cvfvGLhs6v1WpRqVTuZ0m4zX1+C68bpVKp1SOwhlSr1SiXy/c8Z+Nyv/jCwkL89a9/jfn5+RgeHr7refV6Per1+tLzWq223CUB6CBNb/JfvXo1Hnrooejp6Ylf/vKXcerUqXjyySfvev7ExERUKpWlx8DAwH0NDEBnaPotslu3bsW///3vqFar8dZbb8Xrr78ek5OTd43Mne5gRIaV5C2yxniLjJXUyFtk970HMzIyEt/4xjfi+PHjDZ1vD4aVJjCNERhWUiOBue/PwSwuLt52hwIAEU1u8o+Pj8e+ffticHAw5ubm4sSJE3HhwoU4e/Zs1nwAdKimAjM7Oxs//elP4z//+U9UKpUYGhqKs2fPxo9+9KOs+QDoUPe9B9MsezCsNHswjbEHw0palT0YALgTgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAApBAaAFAIDQAqBASCFwACQQmAASCEwAKQQGABSCAwAKQQGgBQCA0AKgQEghcAAkEJgAEghMACkEBgAUggMACkEBoAUAgNACoEBIIXAAJBCYABIITAApBAYAFIIDAAp7iswR48ejVKpFIcOHVqhcQBYK5YdmEuXLsXx48djaGhoJecBYI1YVmBu3rwZL730UvzpT3+Khx9+eKVnAmANWFZgxsbG4rnnnouRkZGvPLder0etVrvtAcDat7HZF5w8eTKuXLkSly5dauj8iYmJ+N3vftf0YAB0tqbuYGZmZuLgwYPxl7/8JTZt2tTQa8bHx6NarS4
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"kernel = cv.getStructuringElement(cv.MORPH_CROSS , (5, 5)) \n",
"plt.imshow(kernel, cmap=\"gray\")"
]
},
{
"cell_type": "code",
"execution_count": 48,
"id": "31e1c557",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x800 with 4 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"\n",
"img_path = \"img/text_no_ocr.png\"\n",
"coins = cv.imread(img_path, cv.IMREAD_GRAYSCALE)\n",
"_, coins_bin = cv.threshold(coins, 100, 255, cv.THRESH_BINARY)\n",
"\n",
"coins_eroded = cv.erode(coins_bin, kernel, iterations=1)\n",
"# coins_dilated = cv.dilate(coins_bin, kernel, iterations=1)\n",
"coins_dilated = np.invert(cv.morphologyEx(coins_bin, cv.MORPH_BLACKHAT, kernel))\n",
"\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(\"BLACKHAT\");\n"
]
},
{
"cell_type": "markdown",
"id": "702de10a",
"metadata": {},
"source": [
"![Przykładowy wynik](img/text_no_ocr_sample_result.png)"
]
},
{
"cell_type": "markdown",
"id": "9aa0c742",
"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": 49,
"id": "88183615",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "9fda42a9",
"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": 50,
"id": "d98a9973",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAvAAAAGiCAYAAACBCPIbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAACAgUlEQVR4nO3deXhU5dk/8O+ZPZlkJnsmewJJSCAsArKotKIIKq6lVq21VK2+RbAv0lpfbau2WrF207prfUXrWhdwR3EDUXZkCUuAELJAJnsyWWc9vz/4zbyEJczMObOczPdzXXNpJnPOPBPOzNznPvdzP4IoiiKIiIiIiEgRVJEeABERERER+Y8BPBERERGRgjCAJyIiIiJSEAbwREREREQKwgCeiIiIiEhBGMATERERESkIA3giIiIiIgVhAE9EREREpCAM4ImIiIiIFIQBPBERERGRgjCAJyIiIiIKk8LCQgiCcMJt4cKFfu9DE8LxERERERHRMTZt2gS32+37ubKyEhdccAGuuuoqv/chiKIohmJwREREREQ0tMWLF+ODDz7A/v37IQiCX9swA09EREREMWdgYAAOh0OWfYmieELwrdfrodfrh9zO4XDg5ZdfxpIlS/wO3gEG8EREREQUYwYGBlBUVASr1SrL/hISEtDT0zPovnvvvRf33XffkNutWLECnZ2d+NnPfhbQ87GEhoiIiIhiis1mg9lsRl1dHUwmk+R95efno76+ftC+/MnAz5kzBzqdDu+//35Az8kMPBERERHFJJPJJDmAD3ZftbW1+Oyzz/DOO+8E/FwM4ImIiIgoJomiCKnFKMFu/8ILLyAjIwNz584NeFsG8EREREQUkyIVwHs8HrzwwguYP38+NJrAw3Eu5EREREREFEafffYZ6urqcOONNwa1PTPwRERERBSTIpWBnz17tqTnZQBPRERERDEpkjXwUrCEhoiIiIhIQZiBJyIiIqKYpNQMPAN4IiIiIopJSg3gWUJDRERERKQgzMATERERUUxSagaeATwRERERxSSlBvAsoSEiIiIiUhBm4ImIiIgoJik1A88AnoiIiIhiklIDeJbQEBEREREpCDPwRERERBSTlJqBZwBPRERERDFJqQE8S2iIiIiIiBSEGXgiIiIiiklKzcAzgCciIiKimKTUAJ4lNERERERECsIMPBERERHFJKVm4BnAExEREVFMUmoAzxIaIiIiIiIFYQaeiIiIiGKSUjPwDOCJiIiIKGZFIgCXiiU0REREREQKwgw8EREREcUkltAQERERESmIUgN4ltAQERERESkIM/BEREREFJOUmoFnAE9EREREMUmpATxLaIiIiIiIFIQZeCIiIiKKSUrNwDOAJyIiIqKYpNQAniU0REREREQKwgw8EREREcUkpWbgGcATERERUUxSagDPEhoiIiIiIgVhBp6IiIiIYpJSM/AM4ImIiIgoJik1gGcJDRERERGRgjADT0REREQxSakZeAbwRERERBSTlBrAs4SGiIiIiEhBmIEnIiIiopik1Aw8A3giIiIiiklKDeBZQkNEREREpCAM4ImIiIgoJnkz8FJvgTp8+DB+8pOfIDU1FXFxcRg7diw2b97s9/YsoSEiIiKimBSJEpqOjg6cffbZmDlzJj7++GOkp6dj//79SE5O9nsfDOCJiIiIiMLkz3/+M/Ly8vDCCy/47isqKgpoHyyhISIiIqKYJGcJjc1mG3Sz2+0nfc733nsPkydPxlVXXYWMjAycccYZeO655wIaNwN4IiIiIopZctW/5+XlwWw2+25Lly496fMdPHgQTz31FEpKSvDJJ59gwYIF+OUvf4kXX3zR7zGzhIaIiIiISKL6+nqYTCbfz3q9/qSP83g8mDx5Mh588EEAwBlnnIHKyko8/fTTmD9/vl/PxQw8EREREcUkOUtoTCbToNupAvisrCyMHj160H3l5eWoq6vze9zMwBMRERFRTIpEF5qzzz4bVVVVg+7bt28fCgoK/N4HM/BERERERGFy++23Y/369XjwwQdx4MABvPrqq3j22WexcOFCv/fBAJ6IiIiIYlIkFnI688wzsXz5crz22muoqKjA/fffj0ceeQTXXXed3/tgCQ0RERERxaRIlNAAwCWXXIJLLrkk6OdkBp6IiIiISEGYgSciIiKimBSpDLxUDOCJiIiIKCYpNYBnCQ0RERERkYIwA09EREREMUmpGXgG8EREREQUk5QawLOEhoiIiIhIQZiBJyIiIqKYpNQMPAN4IiIiIopJSg3gWUJDRERERKQgzMATERERUUxSagaeATwRERERxSSlBvAsoSEiIiIiUhBm4ImIiIgoJik1A88AnoiIiIhiklIDeJbQEBEREREpCDPwRERERBSTlJqBZwBPRERERDFJqQE8S2iIiIiIiBSEGXgiIiIiiklKzcAzgCciIiKimBWJAFyqiJbQPPHEEygsLITBYMDUqVOxcePGSA6HiIiIiCjqRSyAf+ONN7BkyRLce++92Lp1K8aPH485c+agubk5UkMiIiIiohjiLaGRegu3iAXwf//733HzzTfjhhtuwOjRo/H0008jPj4e//u//xupIRERERFRDFFqAB+RGniHw4EtW7bgrrvu8t2nUqkwa9YsrFu37oTH2+122O12388ejwft7e1ITU2FIAhhGTMRERER+U8URXR3dyM7OxsqFRsfyikiAXxrayvcbjcyMzMH3Z+ZmYm9e/ee8PilS5fiD3/4Q7iGR0REREQyqa+vR25ubqSHcVJK7UKjiNOhu+66C11dXb5bXV1dpIdERERERH5ITEyM9BBOiSU0AUhLS4NarUZTU9Og+5uammCxWE54vF6vh16vD9fwiIiIiEgmLHeWX0Qy8DqdDpMmTcLnn3/uu8/j8eDzzz/H9OnTIzEkIiIiIooxzMAHaMmSJZg/fz4mT56MKVOm4JFHHkFvby9uuOGGSA2JiIiIiGKIUmvgIxbAX3311WhpacE999wDq9WKCRMmYOXKlSdMbCUiIiIiov8TsQAeABYtWoRFixZFcghEREREFKOYgSciIiIiUhClBvCKaCNJRERERERHMQNPRERERDFJqRl4BvBEREREFJOUGsCzhIaIiIiISEGYgSciIiKimKTUDDwDeCIiIiKKSUoN4FlCQ0RERESkIMzAExEREVFMUmoGngE8ERERKYogCL7/j0TwRMMHA3giIiIiGanVaqhUKuh0Omi1Wmi1WqjVami1WgiCALfbjcbGRng8nkgPlSisGMATERFRRAmCAI1GA51OB71eD0EQYDAYoNVqoVKpoFKdfMqe0+kM80hpuFFqBp6TWImIiCgiTCYTsrKykJubi7y8PGRlZSElJQXJycmIi4uDRqM5ZfAOyBN8UWzzHkNSb4G47777IAjCoFtZWVlA+2AGnoiIiMJOpVIhJSUFGg1DEYo9Y8aMwWeffeb7OdD3Ad81RERERBSTIlVCo9FoYLFYgn5OltAQERFR2HknqBJFmlzlMzabbdDNbref8jn379+P7OxsjBgxAtdddx3q6uoCGjPfOURERBR2cgTwbrebNfAUNfLy8mA2m323pUuXnvRxU6dOxbJly7By5Uo89dRTqKmpwYwZM9Dd3e33c7GEhoiIiBSJXWhIKjlLaOrr62EymXz36/X6kz7+oosu8v3/uHHjMHXqVBQUFOA///kPbrrpJr+ekwE8ERERhd2xizEFS6vVyjASimVyBvAmk2lQAO+vpKQklJaW4sCBA35vwxIaIiIiCjudTid5H263W4aREEVWT08PqqurkZWV5fc2DOCJiIiiREJCAlJTU2NicqdarZa8D67ASlJFog/8r3/9a6xevRqHDh3Ct99+iyuvvBJqtRrXXnut3/tgCQ0REVGUiIuLg9lshl6vR1NTEzPMRCEWiTaSDQ0NuPbaa9HW1ob09HScc845WL9+PdLT0/3eBwN4IiIZCYIArVYLQRBgNBrhcrlgNpsRHx8Pt9uN7u5u34e9x+NBT08PnE4nAzUC8H813fHx8cjMzBzWQbwcNfBESvT6669L3gcDeCKiIAmCALVajbi4OCQlJUGv18NkMsFsNkO
"text/plain": [
"<Figure size 1000x500 with 2 Axes>"
]
},
"metadata": {},
"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": "fccd4605",
"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": 51,
"id": "0754cee5",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA9kAAAIbCAYAAAD/413hAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAACwv0lEQVR4nOzdd3xT1f8/8FeSpuluugdtgTItUxm1gAyplKEIggIiggOVochScQBOBEX4CIg4WIJMBUURB1AQKSDIni1QWkr33k2T8/uDb/OjNEnXTdO0r+fjcR7KPTfnnpOm7+Z9xzkyIYQAEREREREREdWa3NIdICIiIiIiImoomGQTERERERERSYRJNhEREREREZFEmGQTERERERERSYRJNhEREREREZFEmGQTERERERERSYRJNhEREREREZFEmGQTERERERERSYRJNhEREREREZFEmGSTVYiNjYVMJsOnn34qWZuRkZGQyWSIjIyUrE0iorrG+EhEZBjjI1kKk2wym7Vr10Imk+H48eOW7orZJCQk4IknnoBarYaLiwseffRRXLt2zdLdIqJ6rqHHx8uXL2P69Ono0aMH7OzsIJPJEBsba+luEZEVaOjx8ccff8SoUaMQHBwMBwcHtGnTBjNnzkRWVpalu0YSsrF0B4isVV5eHvr164fs7Gy8+eabUCqVWLJkCfr06YNTp07Bw8PD0l0kIrKIqKgofP755wgJCcE999yDU6dOWbpLRET1wgsvvAB/f3889dRTCAoKwtmzZ7F8+XLs3r0b//33H+zt7S3dRZIAk2yiGvriiy8QHR2NY8eOoVu3bgCAQYMGoX379li8eDE++ugjC/eQiMgyhg4diqysLDg7O+PTTz9lkk1E9H+2b9+Ovn37ltvWpUsXjB8/Hhs3bsTzzz9vmY6RpHi7OFlUSUkJ5s6diy5dusDV1RWOjo544IEHsH//fqOvWbJkCZo2bQp7e3v06dMH586dq7DPpUuXMHLkSLi7u8POzg5du3bFzz//XGl/CgoKcOnSJaSlpVW67/bt29GtWzd9gg0Abdu2Rf/+/bF169ZKX09EZIo1x0d3d3c4OztXuh8RUU1Yc3y8O8EGgOHDhwMALl68WOnryTowySaLysnJwTfffIO+ffti4cKFmD9/PlJTUxEREWHwysf69evx+eefY8qUKZgzZw7OnTuHBx98EMnJ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
"text/plain": [
"<Figure size 1200x700 with 8 Axes>"
]
},
"metadata": {},
"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": "1a63dd4c",
"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": 52,
"id": "2b02eb5f",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAABUkAAAGiCAYAAADa0EdrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAADbp0lEQVR4nOzdd5wkZZ0/8M9TVZ17untyntmdnc1sAJYMklkRUEAREEneiSQVEc5DfyjqnRjPjAIqKCKKhyCgKJJEBQ5Y2GWXzXlnZndy6txd9fz+GGbY2ZmuDlPdkz5vX/3Cne6uqp7QT9e3vkFIKSWIiIiIiIiIiIiIZillsg+AiIiIiIiIiIiIaDIxSEpERERERERERESzGoOkRERERERERERENKsxSEpERERERERERESzGoOkRERERERERERENKsxSEpERERERERERESzGoOkRERERERERERENKsxSEpERERERERERESzGoOkRERERERERERENKsxSEpERERERERERESzGoOkRERkmTlz5kAIMeZ2ww03TPahERERTWlcQ4mIiHJj1Rqq5en4iIhoFnrttdeg6/rIvzds2IAzzzwTF1100SQeFRER0dTHNZSIiCg3Vq2hQkoprT44IiIiALjpppvw5JNPYtu2bRBCTPbhEBERTRtcQ4mIiHKT6xrKTFIiohkoGo0iHo9btj0p5ZjFxeFwwOFwpHxOPB7Hr3/9a9x88808uSMiommDaygREVFupvsayiApEdEME41GMbfRiwMdevoHZ8jr9SIYDI762pe+9CXccccdKZ/z2GOPoa+vD1dddZVlx0FERJRP0WgUc+fOxYEDByzbJtdQIiKaDYbW0CocONBv2TYLvYay3J6IaIYZGBiA3+/HrjWN8BVNfD7fwKCBuUfuwb59++Dz+Ua+nu4K3urVq2G32/HEE09M+BiIiIgKYXgN3bt376g1byLba2ho4BpKREQz3vAaunPPd+HzuSzYXgRNjZ8p6BrKTFIiohnKV6RYEiQd2Z7Pl/EJ4549e/DMM8/gD3/4g2X7JyIiKpRs1jyrt8c1lIiIpjOfz2VJkPTd7RVuDWWQlIhohtKlAd2CWgFdGlk/57777kNFRQXOOeeciR8AERFRgUkpYUXBXS7b4BpKRETTmZRJSJm0ZDvZmugayiApEdEMZUDCwMRP8LLdhmEYuO+++3DllVdC07jMEBHR9DNZQVKuoURENN1JqUPKic/HyHYbVqyh1tVhEhERAXjmmWewd+9efOxjH5vsQyEiIppWuIYSERHlxoo1lJcniYhmKAMGsi+UH3872TjrrLMsyb4hIiKaLJOVSco1lIiIpjtDJmFYUG6f7TasWEMZJCUimqF0KaFbcKJlxTaIiIimk8nsSUpERDSdTWZP0oliuT0RERERERERERHNaswkJSKaoSZrcBMREdF0x0xSIiKi3AwNbrIik3Tiw5+yxSApEdEMZUBCZ5CUiIgoawySEhER5UYaSUjDgiCpBdvIFsvtiYiIiIiIiIiIaFZjJikR0QzFcnsiIqLcMJOUiIgoRzI5dLNiOwXGICkR0QzF6fZERES5YZCUiIgoN5xuT0RERERERERERDRNMZOUiGiGMt65WbEdIiKi2YSZpERERDkykoCRsGY7BcYgKRHRDKVbNN3eim0QERFNJwySEhER5Wao3F61ZDuFxnJ7IiIiIiIiIiIimtWYSUpENEPpcuhmxXaIiIhmE2aSEhER5chIAsbEM0lZbk9ERJZhT1IiIqLcMEhKRESUo2kcJGW5PREREREREREREc1qzCQlIpqhDAjoEJZsh4iIaDZhJikREVGudMCSoUu6BdvIDoOkREQzlCGHblZsh4iIaDZhkJSIiCg3wkhCGBMvXBcstyciIiIiIiIiIiIqLGaSEhHNULpF5fZWbIOIiGg6YSYpERFRjowkYEEmKafbExGRZRgkJSIiyg2DpERERDmaxkFSltsTERERERERERHRrMZMUiKiGcqQAoa0YLq9BdsgIiKaTphJSkRElBshkxDSgsFNkuX2RERkEZbbExER5Y4BTiIiohwYBmDo1mynwFhuT0RERERERERERLMaM0mJiGYoHQp0C66FWXANkIiIaFphuT0REVFuhJGEMCZejSg43Z6IiKwiLepJKtmTlIiIZhkGSYmIiHJk6BZNty98ug7L7YmIiIiIiIiIiGhWYyYpEdEMxcFNREREuWEmKRERUY6MJGBBuT1Ybk9ERFbRpQJdWtCTlOd3REQ0yzBISkRElBth6BAWlNsLltsTERERERERERERFRYzSYmIZigDAoYF18IMMAuGiIhmF2aSEhER5UhaNLhJFj6TlEFSIqIZij1JiYiIcsMgKRERUW6EYVhSKi8Mw4KjyQ7L7YmIiIiIiIiIiGhWYyYpEdEMZd3gJmbBEBHR7MJMUiIiohwZukXT7VluT0REFhnqSTrxxcmKbRAREU0nDJISERHlZmi6/cTPITndnoiIiIiIiIiIiKjAmElKRDRDGVCgc7o9ERFR1phJSkRElCOW2xMR0VTDnqRERES5YZCUiIgoNyy3JyIiIiIiIiIiIpqmmElKRDRDGVBgsNyeiIgoa8wkJSIiyhHL7YmIaKrRpYAuJ744WbENIiKi6YRBUiIiotwIQ0IYhiXbKTSW2xMREREREREREdGsxkxSIqIZSrdour3OcnsiIpplmElKRESUI0MHJp5IynJ7IiKyjiEVGBZMtzd4gkdERLMMg6REREQ5khYFSSWn2xMREREREREREREVFIOkREQz1HC5vRW3bLS2tuKjH/0oSktL4XK5sGzZMrz++ut5epVERETWG84kteKWDa6hREQ03QlpWHbLhhVrKMvtiYhmKAPWTKbPZmnq7e3FCSecgFNPPRVPPfUUysvLsW3bNhQXF0/4OIiIiAplMsrtuYYSEdGMMAk9Sa1aQxkkJSIiy3zjG99AfX097rvvvpGvzZ07dxKPiIiIaHrgGkpERJQbq9ZQltsTEc1QBhTLbgAwMDAw6haLxcbs8/HHH8eqVatw0UUXoaKiAocffjjuvffeQr90IiKiCbG63J5rKBERzRqGYd0NhV1DGSQlIpqhdKlYdgOA+vp6+P3+kdudd945Zp87d+7ET37yE8yfPx9//etfcd111+FTn/oUfvnLXxb65RMREU2Ilf1IuYYSEdGsYXGQtJBrKMvtiYgoI/v27YPP5xv5t8PhGPMYwzCwatUqfO1rXwMAHH744diwYQN++tOf4sorryzYsRIREU0lXEOJiIhyU8g1lEFSIqIZyoCAASsGNw1tw+fzjVqcxlNdXY0lS5aM+trixYvxyCOPTPg4iIiICsXqwU1cQ4mIaLYQhgFhweAm8U4maSHXUAZJiYhmqINL5Se6nUydcMIJ2LJly6ivbd26FY2NjRM+DiIiokKZjOn2XEOJiGhGMAyLpttnvhGr1lD2JCUiIst85jOfwSuvvIKvfe1r2L59O37zm9/gnnvuwQ033DDZh0ZERDSlcQ0lIiLKjVVrKIOkREQzlA7FslumjjrqKDz66KN46KGHcNhhh+GrX/0qvve97+Gyyy7L4yslIiKyltXT7TPBNZSIiGYEiwc3ZcKqNZTl9kREM5QhBQxpQU/SLLdx7rnn4txzz53wfomIiCbLZJTbA1xDiYhoBpiEcnvAmjWUmaREREREREREREQ0qzGTlIhohjKyLJU32w4REdFsMlmZpERERNOe1AHDgvVPWpGOmh0GSYmIZihDKjAsmG5vxTaIiIimEwZJiYiIciMMA8KC+KbIstzeCjzzJSIiIiIiIiIiolmNmaRERDOUDgEdEx/cZMU2iIiIphNmkhIREeVokgY3WYFBUiKiGYrl9kRERLlhkJSIiChH0zhIyjNfIiIiIiIiIiIimtWYSUpENEPpsKZUXp/4oRAREU0rzCQlIiLKkSGtyQI1Cr+GMkhKRDRDsdyeiIgoNwySEhER5ciQFpXbF34N5ZkvERERERERERERzWrMJCUimqF0qUC3IAvUim0QERFNJ8wkJSIiypFhAMbE276x3J6IiCwjIWBY0JNUWrA
"text/plain": [
"<Figure size 1700x500 with 6 Axes>"
]
},
"metadata": {},
"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": "e37f716a",
"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": 53,
"id": "91f86157",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAADqCAYAAACIsr4TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABpRElEQVR4nO3deZwcZZ348c9TVX1PH3PPZHIfJIQEwhkiCAgxCaKAICoii6iwi4FdYFUWf8qhriiuq4tcsgegiCgqIqeEQIJADgg3JCFA7mTuo3tm+qqq5/dHZ4YMmcl09XRP9yTP+/XKC6a7uvvpru6qbz3P9/k+QkopURRFURRFKSFasRugKIqiKIryUSpAURRFURSl5KgARVEURVGUkqMCFEVRFEVRSo4KUBRFURRFKTkqQFEURVEUpeSoAEVRFEVRlJKjAhRFURRFUUqOClAURVEURSk5KkBRFKWk3XPPPQghePnll4vdFEVRRpEKUBRFyYkQIqt/K1asKHZTFUUZg4xiN0BRlLHpN7/5zYC/f/3rX7Ns2bJ9bj/00ENHs1mKohwgVICiKEpOvvzlLw/4e/Xq1Sxbtmyf23OVSCRwu915eS5FUcYeNcSjKErBTJ48ma985Sv73H7KKadwyimn9P+9YsUKhBA88MADfPe736WhoQG/3080Gu3fpre3l3/8x3+ksrKSUCjEP/zDP9DR0bHPc99+++0cdthheDwexo0bx9KlS+ns7CzAu1MUpZBUD4qiKCXjBz/4AW63m29+85skk8kBPSiXX345kUiEG264gY0bN3LHHXewdevW/uAG4IYbbuDGG29k4cKFXHbZZf3bvfTSS7zwwgu4XK5ivTVFURxSAYqiKCUjkUjw8ssv4/P59rnP7XazfPny/iBj0qRJfPvb3+aRRx7hzDPPpKWlhZtuuolFixbxxBNPoGmZDuJZs2Zx+eWXc99993HxxReP6vtRFCV3aohHUZSScdFFFw0anABceumlA3pALrvsMgzD4PHHHwfg6aefJpVKceWVV/YHJwCXXHIJoVCIxx57rLCNVxQlr1SAoihKyZgyZcqQ982YMWPA32VlZdTX17NlyxYAtm7dCsDMmTMHbOd2u5k6dWr//YqijA0qQFEUpWD6ckM+yrKsQW8fqvdEUZSDjwpQFEUpmPLy8kFn0OTSm7Fp06YBf3d3d7N7924mT54MZHJSADZu3Dhgu1QqxebNm/vvVxRlbFABiqIoBTNt2jRWr15NKpXqv+3RRx9l+/btjp/rrrvuIp1O9/99xx13YJomp59+OgALFy7E7XZzyy23IKXs3+5///d/6erq4owzzhjBO1EUZbSpWTyKohTM17/+df74xz+yZMkSPv/5z/P+++9z3333MW3aNMfPlUqlOO200/j85z/Pxo0buf322znxxBM588wzAaiurubaa6/lxhtvZMmSJZx55pn92x177LF5KyCnKMroUD0oiqIUzOLFi/nZz37Gu+++y5VXXsmqVat49NFHGT9+vOPnuvXWWzn00EO57rrruOeeezj//PN5+OGHB+S53HDDDdx6661s27aNq666ij/84Q9ceumlPPXUU6oGiqKMMULu3ReqKIqiKIpSAlQPiqIoiqIoJUcFKIqiKIqilBwVoCiKoiiKUnKKGqDcdtttTJ48Ga/Xy/z581m7dm0xm6MoiqIoSokoWoDy+9//nquvvprrr7+eV155hSOOOILFixfT3NxcrCYpiqIoilIiijaLZ/78+Rx77LHceuutANi2zYQJE7jiiiv4t3/7t2I0SVEURVGUElGUQm2pVIp169Zx7bXX9t+maRoLFy5k1apV+2yfTCZJJpP9f9u2TXt7O5WVlUOu9aEoiqIoSmmRUhKLxRg3btyAVccHU5QApbW1FcuyqK2tHXB7bW0tGzZs2Gf7m266iRtvvHG0mqcoiqIoSgFt37592IKNY6LU/bXXXsvVV1/d/3dXVxcTJ05kduRodDEm3oKiKIqiHPQsafJO5zqCweCw2xbl7F5VVYWu6zQ1NQ24vampibq6un2293g8eDyefW7XhaECFEVRFEUZY7JJzyjKLB63283RRx/N8uXL+2+zbZvly5ezYMGCYjRJURRFUZQSUrTuh6uvvpqLLrqIY445huOOO45f/OIX9PT0cPHFFxerSYqiKIqilIiiBShf+MIXaGlp4brrrqOxsZF58+bx5JNP7pM4qyiKoijKwWdMrmYcjUYJh8PMLZ+vclAURVEUZYywpMmbHWvo6uoiFArtd1u1Fo+iKIqiKCVHBSiKoiiKopQcFaAoiqIoilJyVICiKIqiKErJUQGKoiiKoiglRwUoiqIoiqKUHDVHV1EURVGEjjA8aN4gWqAaPVCB5q8EoRPf8CQy1V3sFh50VICiKIqiHEQE6C70QCV6eDyaL4KrcgpG1XQ0bxjNG0a4vCAEQmjY6QTJbWuxVIAy6lSAoiiKohwUjPJJBI46Hz1Yhx6qQxheEJlMhyEXr7NNZLp3FFup9FEBiqIoinJQcNUeimfyx7JaSVcpPpUkqyiKohwUhOFRwckYogIURVEU5aBglE90/BhpJsFKF6A1ynBUgKIoiqIcJJz3ntiJKHZK5aAUgwpQFEVRlIOAQLh8jh+lecoQbuePU0ZOBSiKoihKdoSGZ+J80N3Fbolzmo4erHH8MDvZjUzFC9AgZTgqQFEURVGyonlDBE+4jPDJVyLcZcVujnNCz+FBcs8/ZbSpacaKohSEBBACdA27phI76MeurwEpSc+ZAaaFvrsZYVogJfrOZrSdTWgdUZA2yFwyBpRC0vyVaJ4gniknEhI60b//cuxUWNV0hO4qdisUB1SAoihKXkgATUOGg5gzJmKNryM9ZwZ2RRhr0jikxw26ntlS+0jnrZRg2YiuGMa23Wi7m/E+9hz6ziZET1wFKiVCuAOgGwgh8ExeQNjwEFv1K6zo7mI3bViauwzNX+74cXZveyZgVkadClAURRkRKQR2dTmpE44idfRhmNMnIstDmd6TQWtODHKbEGDoyMoI6coIzJtF8rQFaK0deJ5/Bc/y1ehbdyJs1dVeTEaonr79J4TAPf4owqd+m86/fR873lHcxg1H0/urxjphx7tUgFIkKkBRFMUxCchwGenDZ2YCk3mzkBXhIQKSHAgBHjd2Qy3xzy8h8elTcL38Ft6/PovrrXdVoFIkwhMYUOhMCIFROY3QKVcRe+GOku5J0YO1mdL2ypihAhRFUbImAbuqnOSp80mcfhL2uOp9h2vyTQhkwEfq5GNJHzsX9/Pr8P/2UbRdzWropwQIIXCPm0dk8fVEV/6CdPOGYjdpUEJo+QuglVGhAhRFUYYlARnwkVzyceKfXYhdU1GUg730e0l+8mOkjz4M328fxfvEc5kkW2VUaP6KQW8XQqCHxlE2/6tEn7sFq2vHKLescKStqsgWi5pmrCjKfkldJ33MHKI/vpqeS8/Drq0s7pWoENiVEXou+yLdV16EHQyoSaCjxR46GBRC4KqZRfnp38dVPXMUG5UlLZcpxmDFmvLcECVbKkBRFGVQErCqK+j5py8QvWEp5swphR/OccJlkPzkx4hevxS7MqKClFEgjP0XaBNCoAWqCJ1yNe6GeaPTqCxl1uFxFlhLKZHJMTKN+gBUQkcbRVFKhdQ0UicdQ9fP/43EWaeCx12a4/eawDz8EKI/uhJrcoMKUgpM8w0/TVcIgREeR+jEK3CNO3wUWpUdYXidr2QsbczO7YVpkDIslYOiKMoAdqiM3vM/ReIznwC3qzQDk70JgTVlPN1XX0Tw33+F1tSmkmdLgFZWTeTUa+h+6V7i7z5d9Km6RvmkHB4lkcVcyVgAGugBHfdEN5pXwzvTi+9wH5pPo/PhTqLLo8VrX4GpAEVRFGBPImxFmNiV/0D6+CNKPzDZmxCYs6YSu+brhL53C6JHrZ2Sd0JDuPzZby4EwhsiuOAStGAtPet+W9wgJYccFGmZyHSiAI3ZiwDNp4EAo8LAVe/CPd6Nd5YX7wxv5rY6F656F0IXYNDfE+Q9xEvsxRgyfmD2HaoARVGUTL7J+Fq6r/4K5pwZYys46SM
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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": "code",
"execution_count": 54,
"id": "992e29f0",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4.6.0\n"
]
}
],
"source": [
"print(cv.__version__)"
]
},
{
"cell_type": "markdown",
"id": "6dac2bf4",
"metadata": {},
"source": [
"## Kontury"
]
},
{
"cell_type": "markdown",
"id": "046e4cfe",
"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": 55,
"id": "a785f7ff",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAz8AAAFqCAYAAAA0ieQuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAACaBklEQVR4nOzdd3xc5Zn//c8500czo1HvxZJtWbLlgnEvNIMxppcEAgSSbEIIJL+EtE0lkH3CbpJN2SxpSwIpkOySQAiEXowxtrFxr7Iky5Kt3uv0c54/jBXLVWWkmdFcb156Yc2cOeeSLeme77mbouu6jhBCCCGEEEJMcmqkCxBCCCGEEEKIiSDhRwghhBBCCBEXJPwIIYQQQggh4oKEHyGEEEIIIURckPAjhBBCCCGEiAsSfoQQQgghhBBxQcKPEEIIIYQQIi5I+BFCCCGEEELEBQk/QgghhBBCiLgg4UeIMPnOd76Doiijeu0TTzyBoigcOXIkvEWd5MiRIyiKwhNPPDFu1xBCCCGG6+6776awsDDSZYg4I+FHCGDfvn3ccccd5OTkYLFYyM7O5vbbb2ffvn2RLk0IIcQkVFNTw/3338/06dOx2+3Y7XbKysq477772L17d6TLE2LSUnRd1yNdhBCR9Mwzz3DbbbeRnJzMJz7xCaZMmcKRI0f4zW9+Q3t7O3/+85+54YYbznueYDBIMBjEarWOuIZQKEQgEMBisYy69+h8jhw5wpQpU3j88ce5++67x+UaQgghzu+FF17gwx/+MEajkdtvv505c+agqioHDx7kmWeeoba2lpqaGgoKCiJd6ri6++67Wbdu3biOehDiVMZIFyBEJFVXV3PnnXdSVFTE+vXrSUtLG3zu//2//8eKFSu488472b17N0VFRWc8R39/PwkJCRiNRozG0f1IGQwGDAbDqF4rhBAidlRXV3PrrbdSUFDAG2+8QVZW1pDn/+M//oOf//znqOrZB+ecaHeEECMnw95EXPvBD37AwMAAv/71r4cEH4DU1FR+9atf0d/fz/e//33gn/N69u/fz0c+8hGSkpJYvnz5kOdO5vF4+NznPkdqaipOp5Nrr72W+vp6FEXhO9/5zuBxZ5rzU1hYyNVXX82GDRtYuHAhVquVoqIifv/73w+5RkdHB1/60pcoLy/H4XDgcrlYs2YNu3btCuPflBBCiHD4/ve/T39/P48//vhpwQfAaDTyuc99jry8POB474jD4aC6upqrrroKp9PJ7bffDsA777zDLbfcQn5+PhaLhby8PL7whS/g8XgGz/f444+jKAo7duw47Vrf+973MBgM1NfXA1BZWclNN91EZmYmVquV3Nxcbr31Vrq7u4e87o9//CMLFy7EbreTlJTEypUrefXVVweff+6551i7di3Z2dlYLBaKi4v57ne/SygUOu/fj6Zp/OQnP2HmzJlYrVYyMjK455576OzsHMbfrhDnJz0/Iq49//zzFBYWsmLFijM+v3LlSgoLC/nHP/4x5PFbbrmFadOm8b3vfY9zjRy9++67+b//+z/uvPNOFi9ezNtvv83atWuHXV9VVRU333wzn/jEJ7jrrrv47W9/y9133838+fOZOXMmAIcPH+Zvf/sbt9xyC1OmTKG5uZlf/epXXHTRRezfv5/s7OxhX08IIcT4euGFF5g6dSqLFi0a9muCwSCrV69m+fLl/PCHP8RutwPw9NNPMzAwwL333ktKSgpbtmzhZz/7GceOHePpp58G4Oabb+a+++7jySefZN68eUPO++STT3LxxReTk5OD3+9n9erV+Hw+PvvZz5KZmUl9fT0vvPACXV1dJCYmAvDQQw/xne98h6VLl/Lwww9jNpt57733ePPNN7niiiuA4zf0HA4HDzzwAA6HgzfffJNvf/vb9PT08IMf/OCcX+s999zDE088wcc+9jE+97nPUVNTw3//93+zY8cO3n33XUwm07D/3oQ4I12IONXV1aUD+nXXXXfO46699lod0Ht6evQHH3xQB/TbbrvttONOPHfCtm3bdED//Oc/P+S4u+++Wwf0Bx98cPCxxx9/XAf0mpqawccKCgp0QF+/fv3gYy0tLbrFYtG/+MUvDj7m9Xr1UCg05Bo1NTW6xWLRH3744SGPAfrjjz9+zq9XCCHE+Oju7tYB/frrrz/tuc7OTr21tXXwY2BgQNd1Xb/rrrt0QP/Xf/3X015z4piTPfLII7qiKHptbe3gY7fddpuenZ09pK3Yvn37kDZhx44dOqA//fTTZ62/srJSV1VVv+GGG05rdzRNO2dd99xzj26323Wv1zv42F133aUXFBQMfv7OO+/ogP7kk08Oee3LL798xseFGA0Z9ibiVm9vLwBOp/Ocx514vqenZ/CxT3/60+c9/8svvwzAZz7zmSGPf/aznx12jWVlZUN6pdLS0igpKeHw4cODj1kslsGx4aFQiPb2dhwOByUlJWzfvn3Y1xJCCDG+TrQjDofjtOcuvvhi0tLSBj8effTRIc/fe++9p73GZrMN/rm/v5+2tjaWLl2KrutDhrl99KMfpaGhgbfeemvwsSeffBKbzcZNN90EMNiz88orrzAwMHDG+v/2t7+haRrf/va3T5uTdPKw75Pr6u3tpa2tjRUrVjAwMMDBgwfPeG443pOVmJjI5ZdfTltb2+DH/PnzcTgcQ+oXYrQk/Ii4dSLUnAhBZ3OmkDRlypTznr+2thZVVU87durUqcOuMT8//7THkpKShox91jSNH//4x0ybNg2LxUJqaippaWns3r37tHHaQgghIudEO9LX13fac7/61a947bXX+OMf/3jac0ajkdzc3NMer6ur4+677yY5ORmHw0FaWhoXXXQRwJDf/5dffjlZWVk8+eSTwPF2409/+hPXXXfdYE1TpkzhgQce4LHHHiM1NZXVq1fz6KOPDjlPdXU1qqpSVlZ2zq9z37593HDDDSQmJuJyuUhLS+OOO+44ra5TVVZW0t3dTXp6+pAgmJaWRl9fHy0tLee8rhDDIXN+RNxKTEwkKyvrvPsp7N69m5ycHFwu1+BjJ9/VGk9nWwFOP2me0fe+9z2+9a1v8fGPf5zvfve7JCcno6oqn//859E0bULqFEIIcX4n2p29e/ee9tyJOUBnWvb55B7+E0KhEJdffjkdHR189atfZcaMGSQkJFBfX8/dd9895Pe/wWDgIx/5CP/zP//Dz3/+c959910aGhoGA8kJ//mf/8ndd9/Nc889x6uvvsrnPvc5HnnkETZv3nzG8HUmXV1dXHTRRbhcLh5++GGKi4uxWq1s376dr371q+dslzRNIz09fTCknerUhYmEGA0JPyKuXX311fzP//wPGzZsGFy17WTvvPMOR44c4Z577hnxuQsKCtA0jZqaGqZNmzb4eFVV1ZhqPtVf/vIXLrnkEn7zm98Mebyrq4vU1NSwXksIIcTYrF27lscee4wtW7awcOHCUZ9nz549HDp0iN/97nd89KMfHXz8tddeO+PxH/3oR/nP//xPnn/+eV566SXS0tJYvXr1aceVl5dTXl7ON7/5TTZu3MiyZcv45S9/yb/9279RXFyMpmns37+fuXPnnvE669ato729nWeeeYaVK1cOPl5TU3Per6m4uJjXX3+dZcuWTdhNRhF/ZNibiGtf/vKXsdls3HPPPbS3tw95rqOjg09/+tPY7Xa+/OUvj/jcJxqVn//850Me/9nPfjb6gs/AYDCctuLc008/Pbh0qRBCiOjxla98Bbvdzsc//nGam5tPe/7U3+dnc2JkwMnH67rOT3/60zMeP3v2bGbPns1jjz3GX//6V2699dYhe9P19PQQDAaHvKa8vBxVVfH5fABcf/31qKrKww8/fFoPzok6zlSX3+8/rS08kw996EOEQiG++93vnvZcMBikq6vrvOcQ4nyk50fEtWnTpvG73/2O22+/nfLycj7xiU8wZcoUjhw5wm9+8xva2tr405/+RHFx8YjPPX/+fG666SZ+8pOf0N7ePrjU9aFDhwBO2xNotK6++moefvhhPvaxj7F06VL27NnDk08+edZNWYUQQkTOtGnTeOqpp7jtttsoKSnh9ttvZ86
"text/plain": [
"<Figure size 1000x500 with 2 Axes>"
]
},
"metadata": {},
"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": "fe0024db",
"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": 56,
"id": "b6b7b6fd",
"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": "8fb4fa32",
"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": 57,
"id": "eb7fe829",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "bbe70d91",
"metadata": {},
"source": [
"Możemy również ograniczyć się tylko do zewnętrznych konturów (parametr `cv.RETR_EXTERNAL`):"
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "dfab04dc",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No. of contours: 9\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "0e0a0799",
"metadata": {},
"source": [
"Poniżej mamy zaznaczony obrys konturu wybranego obiektu, np. o indeksie 5:"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "5756eaeb",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"shapes_with_contours = shapes.copy()\n",
"\n",
"cv.drawContours(shapes_with_contours, shapes_contours, 5, (255,255,0), 2)\n",
"\n",
"plt.figure(figsize=[10,5])\n",
"plt.imshow(shapes_with_contours[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "05e6211d",
"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": 60,
"id": "2315e142",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "07e0820a",
"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": 61,
"id": "894b7fb1",
"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": "9311c0d9",
"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": 62,
"id": "a00e03ce",
"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": "3873897e",
"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": 63,
"id": "54160020",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "38d0f1f2",
"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": 64,
"id": "9184cd42",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "e3c9d01b",
"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": 65,
"id": "16f9d71b",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "8128584a",
"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": 66,
"id": "dfee5d44",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1000x500 with 1 Axes>"
]
},
"metadata": {},
"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": "de2ca7bf",
"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": 67,
"id": "1bb452fb",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1500x500 with 2 Axes>"
]
},
"metadata": {},
"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": "7f8071d0",
"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": 68,
"id": "08e79f26",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1500x500 with 2 Axes>"
]
},
"metadata": {},
"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": "dc1e0958",
"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": 72,
"id": "5900ec2b",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1500x500 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# miejsce na eksperymenty\n",
"blobs_gray = cv.imread(\"img/coins.png\", cv.IMREAD_GRAYSCALE)\n",
"\n",
"params = cv.SimpleBlobDetector_Params()\n",
"params.minThreshold = 150;\n",
"params.maxThreshold = 230;\n",
"params.filterByArea = True;\n",
"params.minArea = 50;\n",
"params.maxArea = 50000;\n",
"params.filterByConvexity = True;\n",
"params.minConvexity = 0.9;\n",
"params.maxConvexity = 1.0;\n",
"\n",
"params.filterByCircularity = False;\n",
"params.filterByInertia = False;\n",
"params.filterByColor = False;\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",
"for idx, kp in enumerate(keypoints):\n",
" # M = cv.moments(kp)\n",
" x, y = kp.pt\n",
" x = int(round(x))\n",
" y = int(round(y))\n",
" \n",
" # cv.circle(shapes_with_contours, (x,y), 5, (255,255,255), -1)\n",
" cv.putText(blobs_color, str(idx), (x+10, y+10), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 200, 255), 2)\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": "55ce79c1",
"metadata": {},
"source": [
"![Wykryte monety](img/coins_detected.png)"
]
}
],
"metadata": {
"author": "Andrzej Wójtowicz",
"email": "andre@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3.7.12 ('widzenie_komputerowe')",
"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.7.12"
},
"subtitle": "02. Operacje binarne na obrazach [laboratoria]",
"title": "Widzenie komputerowe",
"vscode": {
"interpreter": {
"hash": "6ac7fc53e11b5e853f03d2492fedb08fce658edca143f79fa3d2748d3b63b777"
}
},
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}