s470623-wko/wko-02.ipynb

2140 lines
1.7 MiB
Plaintext
Raw Normal View History

2022-11-27 23:20:17 +01:00
{
"cells": [
{
"cell_type": "markdown",
"id": "46f39503",
"metadata": {
"id": "46f39503"
},
"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": {
"id": "c8f8f691"
},
"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": 2,
"id": "0ddcac8e",
"metadata": {
"executionInfo": {
"elapsed": 656,
"status": "ok",
"timestamp": 1668431434742,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "0ddcac8e"
},
"outputs": [],
"source": [
"import cv2 as cv\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "2vj-kIAEQ5ud",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 18463,
"status": "ok",
"timestamp": 1668431474720,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "2vj-kIAEQ5ud",
"outputId": "4e6b17fc-6b41-43aa-de0c-32b8e65b65f0"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mounted at /content/drive\n",
"/content/drive/My Drive/aitech-wko-pub\n"
]
}
],
"source": [
"from google.colab import drive\n",
"drive.mount('/content/drive')\n",
"%cd /content/drive/My Drive/aitech-wko-pub"
]
},
{
"cell_type": "markdown",
"id": "89072615",
"metadata": {
"id": "89072615"
},
"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": 5,
"id": "6bf564d2",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 318
},
"executionInfo": {
"elapsed": 2556,
"status": "ok",
"timestamp": 1668431641196,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "6bf564d2",
"outputId": "d0ca06fd-083a-4309-d38a-50a4871fc4a6"
},
"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": "795796a4",
"metadata": {
"id": "795796a4"
},
"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": null,
"id": "f4c60175",
"metadata": {
"id": "f4c60175"
},
"outputs": [],
"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": {
"id": "880d9cd6"
},
"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": null,
"id": "2e63a031",
"metadata": {
"id": "2e63a031"
},
"outputs": [],
"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": {
"id": "462814e3"
},
"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": {
"id": "b03f9b25"
},
"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": null,
"id": "a3f15b79",
"metadata": {
"id": "a3f15b79"
},
"outputs": [],
"source": [
"kernel_ellipse = cv.getStructuringElement(cv.MORPH_ELLIPSE, (7, 7))\n",
"plt.imshow(kernel_ellipse, cmap='gray');"
]
},
{
"cell_type": "markdown",
"id": "19fc2684",
"metadata": {
"id": "19fc2684"
},
"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": null,
"id": "45748934",
"metadata": {
"id": "45748934"
},
"outputs": [],
"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": {
"id": "8353e60e"
},
"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": null,
"id": "8ca44988",
"metadata": {
"id": "8ca44988"
},
"outputs": [],
"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": {
"id": "7fb63be6"
},
"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": {
"id": "57e6d811"
},
"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": null,
"id": "ed726508",
"metadata": {
"id": "ed726508"
},
"outputs": [],
"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": {
"id": "70a4d3ed"
},
"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": 94,
"id": "334ef7c2",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
},
"executionInfo": {
"elapsed": 1440,
"status": "ok",
"timestamp": 1668435234627,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "334ef7c2",
"outputId": "47e5c142-ecee-4dc4-ac42-b181ea4790ee"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[2.15670e+04]\n",
" [8.30000e+01]\n",
" [7.90000e+01]\n",
" [9.80000e+01]\n",
" [1.81000e+02]\n",
" [5.50000e+01]\n",
" [8.50000e+01]\n",
" [9.20000e+01]\n",
" [2.19000e+02]\n",
" [5.60000e+01]\n",
" [6.70000e+01]\n",
" [6.50000e+01]\n",
" [2.25000e+02]\n",
" [4.20000e+01]\n",
" [6.90000e+01]\n",
" [7.00000e+01]\n",
" [2.94000e+02]\n",
" [5.60000e+01]\n",
" [4.80000e+01]\n",
" [4.00000e+01]\n",
" [2.20000e+02]\n",
" [5.70000e+01]\n",
" [5.50000e+01]\n",
" [3.70000e+01]\n",
" [2.28000e+02]\n",
" [5.60000e+01]\n",
" [5.00000e+01]\n",
" [6.20000e+01]\n",
" [3.48000e+02]\n",
" [4.60000e+01]\n",
" [3.90000e+01]\n",
" [6.30000e+01]\n",
" [2.65000e+02]\n",
" [1.90000e+01]\n",
" [3.90000e+01]\n",
" [6.10000e+01]\n",
" [1.84000e+02]\n",
" [2.60000e+01]\n",
" [2.60000e+01]\n",
" [4.40000e+01]\n",
" [5.12000e+02]\n",
" [2.60000e+01]\n",
" [4.70000e+01]\n",
" [4.30000e+01]\n",
" [3.57000e+02]\n",
" [3.60000e+01]\n",
" [4.20000e+01]\n",
" [4.30000e+01]\n",
" [1.63000e+02]\n",
" [4.40000e+01]\n",
" [4.40000e+01]\n",
" [3.90000e+01]\n",
" [3.77000e+02]\n",
" [4.00000e+01]\n",
" [3.90000e+01]\n",
" [3.00000e+01]\n",
" [1.92000e+02]\n",
" [2.80000e+01]\n",
" [3.80000e+01]\n",
" [3.40000e+01]\n",
" [1.23000e+02]\n",
" [3.40000e+01]\n",
" [3.10000e+01]\n",
" [3.70000e+01]\n",
" [2.29000e+02]\n",
" [2.60000e+01]\n",
" [3.30000e+01]\n",
" [4.70000e+01]\n",
" [1.65000e+02]\n",
" [1.90000e+01]\n",
" [4.90000e+01]\n",
" [3.10000e+01]\n",
" [1.57000e+02]\n",
" [3.20000e+01]\n",
" [2.70000e+01]\n",
" [2.90000e+01]\n",
" [1.98000e+02]\n",
" [3.40000e+01]\n",
" [4.80000e+01]\n",
" [1.80000e+01]\n",
" [2.26000e+02]\n",
" [3.20000e+01]\n",
" [2.90000e+01]\n",
" [2.40000e+01]\n",
" [1.59000e+02]\n",
" [2.90000e+01]\n",
" [2.60000e+01]\n",
" [4.10000e+01]\n",
" [1.96000e+02]\n",
" [2.10000e+01]\n",
" [4.60000e+01]\n",
" [1.90000e+01]\n",
" [3.78000e+02]\n",
" [4.00000e+01]\n",
" [3.00000e+01]\n",
" [2.20000e+01]\n",
" [3.33000e+02]\n",
" [3.90000e+01]\n",
" [1.70000e+01]\n",
" [3.30000e+01]\n",
" [2.16000e+02]\n",
" [2.30000e+01]\n",
" [3.70000e+01]\n",
" [3.10000e+01]\n",
" [1.76000e+02]\n",
" [2.10000e+01]\n",
" [3.50000e+01]\n",
" [3.70000e+01]\n",
" [5.72000e+02]\n",
" [2.10000e+01]\n",
" [3.00000e+01]\n",
" [2.50000e+01]\n",
" [3.57000e+02]\n",
" [2.50000e+01]\n",
" [4.00000e+01]\n",
" [3.80000e+01]\n",
" [2.19000e+02]\n",
" [3.00000e+01]\n",
" [3.50000e+01]\n",
" [2.50000e+01]\n",
" [2.38000e+02]\n",
" [3.50000e+01]\n",
" [2.80000e+01]\n",
" [3.00000e+01]\n",
" [2.58000e+02]\n",
" [1.70000e+01]\n",
" [5.30000e+01]\n",
" [2.90000e+01]\n",
" [2.51000e+02]\n",
" [3.70000e+01]\n",
" [3.10000e+01]\n",
" [3.02000e+02]\n",
" [4.40000e+01]\n",
" [2.70000e+01]\n",
" [3.50000e+01]\n",
" [2.14000e+02]\n",
" [3.10000e+01]\n",
" [4.10000e+01]\n",
" [3.50000e+01]\n",
" [2.05000e+02]\n",
" [3.40000e+01]\n",
" [2.90000e+01]\n",
" [2.60000e+01]\n",
" [2.86000e+02]\n",
" [2.00000e+01]\n",
" [3.50000e+01]\n",
" [2.80000e+01]\n",
" [2.97000e+02]\n",
" [2.60000e+01]\n",
" [4.00000e+01]\n",
" [3.30000e+01]\n",
" [3.13000e+02]\n",
" [3.70000e+01]\n",
" [3.10000e+01]\n",
" [1.80000e+01]\n",
" [3.45000e+02]\n",
" [4.50000e+01]\n",
" [1.60000e+01]\n",
" [3.80000e+01]\n",
" [1.76000e+02]\n",
" [2.10000e+01]\n",
" [3.60000e+01]\n",
" [3.60000e+01]\n",
" [3.39000e+02]\n",
" [2.40000e+01]\n",
" [3.40000e+01]\n",
" [2.90000e+01]\n",
" [1.69000e+02]\n",
" [3.70000e+01]\n",
" [2.90000e+01]\n",
" [3.00000e+01]\n",
" [1.62000e+02]\n",
" [2.90000e+01]\n",
" [2.80000e+01]\n",
" [2.80000e+01]\n",
" [1.50000e+02]\n",
" [4.20000e+01]\n",
" [4.90000e+01]\n",
" [5.30000e+01]\n",
" [1.76000e+02]\n",
" [3.50000e+01]\n",
" [5.10000e+01]\n",
" [4.00000e+01]\n",
" [2.21000e+02]\n",
" [3.40000e+01]\n",
" [3.90000e+01]\n",
" [3.20000e+01]\n",
" [1.50000e+02]\n",
" [3.90000e+01]\n",
" [4.40000e+01]\n",
" [2.80000e+01]\n",
" [2.83000e+02]\n",
" [3.10000e+01]\n",
" [3.60000e+01]\n",
" [3.80000e+01]\n",
" [1.24000e+02]\n",
" [4.20000e+01]\n",
" [4.50000e+01]\n",
" [3.40000e+01]\n",
" [1.74000e+02]\n",
" [2.80000e+01]\n",
" [3.00000e+01]\n",
" [5.50000e+01]\n",
" [1.65000e+02]\n",
" [3.90000e+01]\n",
" [4.20000e+01]\n",
" [4.60000e+01]\n",
" [1.26000e+02]\n",
" [3.90000e+01]\n",
" [4.00000e+01]\n",
" [3.10000e+01]\n",
" [1.73000e+02]\n",
" [4.50000e+01]\n",
" [5.40000e+01]\n",
" [3.10000e+01]\n",
" [3.01000e+02]\n",
" [5.90000e+01]\n",
" [4.10000e+01]\n",
" [5.50000e+01]\n",
" [2.30000e+02]\n",
" [4.00000e+01]\n",
" [4.70000e+01]\n",
" [4.80000e+01]\n",
" [2.81000e+02]\n",
" [7.20000e+01]\n",
" [4.60000e+01]\n",
" [3.90000e+01]\n",
" [2.74000e+02]\n",
" [5.90000e+01]\n",
" [4.30000e+01]\n",
" [5.60000e+01]\n",
" [3.06000e+02]\n",
" [6.60000e+01]\n",
" [5.20000e+01]\n",
" [5.90000e+01]\n",
" [4.00000e+02]\n",
" [5.70000e+01]\n",
" [5.90000e+01]\n",
" [6.80000e+01]\n",
" [4.08000e+02]\n",
" [8.10000e+01]\n",
" [8.00000e+01]\n",
" [6.80000e+01]\n",
" [2.46000e+02]\n",
" [8.00000e+01]\n",
" [8.60000e+01]\n",
" [9.40000e+01]\n",
" [4.18000e+02]\n",
" [1.19000e+02]\n",
" [8.60000e+01]\n",
" [7.90000e+01]\n",
" [2.76000e+02]\n",
" [1.10000e+02]\n",
" [1.01000e+02]\n",
" [8.60000e+01]\n",
" [4.13867e+05]]\n"
]
},
{
"data": {
"application/vnd.google.colaboratory.intrinsic+json": {
"type": "string"
},
"text/plain": [
"\"\\nkernel_ellipse = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))\\ncoins_eroded = cv.erode(gray, kernel_ellipse, iterations=1)\\ncoins_dilated = cv.dilate(coins_eroded, kernel_ellipse, iterations=1)\\n#_, img_bin = cv.threshold(image, 200, 255, cv.THRESH_BINARY)\\n\\nedges = cv.Canny(coins_dilated, 50, 150, apertureSize=3)\\n\\nlines = cv.HoughLinesP(\\n edges, # Input edge image\\n 1, # Distance resolution in pixels\\n np.pi/180, # Angle resolution in radians\\n threshold=100, # Min number of votes for valid line\\n minLineLength=50, # Min allowed length of line\\n maxLineGap=2 # Max allowed gap between line for joining them\\n )\\n\\nfor points in lines:\\n x1,y1,x2,y2=points[0]\\n cv.line(image,(x1,y1),(x2,y2),(255,255,255),2)\\n\\n#cnts = cv.findContours(detected_lines, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\\n#for c in contours:\\n# cv.drawContours(image, [c], -1, (255,255,255), 2)\\n\\nplt.axis('off')\\nplt.imshow(image)\""
]
},
"execution_count": 94,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"image = cv.imread(\"img/text_no_ocr.png\", cv.IMREAD_COLOR)\n",
"image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)\n",
"#coins = cv.imread(\"img/coins.png\", cv.IMREAD_GRAYSCALE)\n",
"#_, coins_bin = cv.threshold(coins, 125, 255, cv.THRESH_BINARY_INV)\n",
"\n",
"#kernel_ellipse = cv.getStructuringElement(cv.MORPH_ELLIPSE, (6, 6))\n",
"#coins_eroded = cv.erode(gray, kernel_ellipse, iterations=1)\n",
"#coins_dilated = cv.dilate(coins_eroded, kernel_ellipse, iterations=1)\n",
"\n",
"_, img_bin = cv.threshold(image, 0, 1, cv.THRESH_BINARY)\n",
"\n",
"\n",
"plt.figure(figsize=[10,10])\n",
"plt.subplot(121) \n",
"plt.imshow(image, cmap='gray')\n",
"plt.title(\"Grayscale\")\n",
"plt.subplot(122)\n",
"plt.imshow(img_bin, cmap='gray')\n",
"plt.title(\"Cleared\");\n",
"\n",
"\n",
"img = cv.imread(\"img/text_no_ocr.png\", cv.IMREAD_GRAYSCALE)\n",
"_, img_bin = cv.threshold(img, 254, 255, cv.THRESH_BINARY)\n",
"\n",
"hist = cv.calcHist([img], [0], None, [256], [0, 256])\n",
"print(hist)\n",
"\n",
"plt.figure()\n",
"plt.axis(\"off\")\n",
"plt.imshow(cv.cvtColor(img, cv.COLOR_GRAY2RGB))\n",
"# plot the histogram\n",
"plt.figure()\n",
"plt.title(\"Grayscale Histogram\")\n",
"plt.xlabel(\"Bins\")\n",
"plt.ylabel(\"# of Pixels\")\n",
"plt.plot(hist)\n",
"plt.xlim([0, 256])\n",
"'''\n",
"kernel_ellipse = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))\n",
"coins_eroded = cv.erode(gray, kernel_ellipse, iterations=1)\n",
"coins_dilated = cv.dilate(coins_eroded, kernel_ellipse, iterations=1)\n",
"#_, img_bin = cv.threshold(image, 200, 255, cv.THRESH_BINARY)\n",
"\n",
"edges = cv.Canny(coins_dilated, 50, 150, apertureSize=3)\n",
"\n",
"lines = cv.HoughLinesP(\n",
" edges, # Input edge image\n",
" 1, # Distance resolution in pixels\n",
" np.pi/180, # Angle resolution in radians\n",
" threshold=100, # Min number of votes for valid line\n",
" minLineLength=50, # Min allowed length of line\n",
" maxLineGap=2 # Max allowed gap between line for joining them\n",
" )\n",
"\n",
"for points in lines:\n",
" x1,y1,x2,y2=points[0]\n",
" cv.line(image,(x1,y1),(x2,y2),(255,255,255),2)\n",
"\n",
"#cnts = cv.findContours(detected_lines, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n",
"#for c in contours:\n",
"# cv.drawContours(image, [c], -1, (255,255,255), 2)\n",
"\n",
"plt.axis('off')\n",
"plt.imshow(image)'''"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "xJDQHKGxE2NK",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 19111,
"status": "ok",
"timestamp": 1666023152005,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -120
},
"id": "xJDQHKGxE2NK",
"outputId": "309b522e-1f71-4ad6-a006-097380941eb3"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mounted at /content/drive\n",
"/content/drive/My Drive/aitech-wko-pub\n"
]
}
],
"source": [
"from google.colab import drive\n",
"drive.mount('/content/drive')\n",
"%cd /content/drive/My Drive/aitech-wko-pub"
]
},
{
"cell_type": "markdown",
"id": "702de10a",
"metadata": {
"id": "702de10a"
},
"source": [
"![Przykładowy wynik](img/text_no_ocr_sample_result.png)"
]
},
{
"cell_type": "markdown",
"id": "9aa0c742",
"metadata": {
"id": "9aa0c742"
},
"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": 27,
"id": "88183615",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 242
},
"executionInfo": {
"elapsed": 1121,
"status": "ok",
"timestamp": 1668432394606,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "88183615",
"outputId": "b2746d54-d2c7-4f27-e572-c7ec74f702ef"
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAADhCAYAAAAK9fv7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOydeVxU1f//X2f2GfZFEAFBUFHEJeSDG5Xmkmb10dTEPdNENLdKzXL5pD9Ty8oykzTNJTWzPpaV69fcWjQ3FJfcEEVwQxYRGJjl/ftD8EPGMnPnztwBz/PxeD+43LnnnPc5d3vfs7zfjIjA4XA4HA6Hw7EdmdQKcDgcDofD4dQWuGHF4XA4HA6HIxLcsOJwOBwOh8MRCW5YcTgcDofD4YgEN6w4HA6Hw+FwRIIbVhwOh8PhcDgiYRfDijHWnTF2jjF2kTH2pj3K4HA4HA6Hw3E2mNh+rBhjcgDnAXQFcA3AYQADiOiMqAVxOBwOh8PhOBn26LGKBXCRiFKJqATA1wD+bYdyOBwOh8PhcJwKexhWgQDSy/1/rXQfh8PhcDgcTq1GIVXBjLFRAEaV/ttaKj04HA6Hw+FwrCSLiOpU9IM9DKsMAMHl/g8q3fc3iGgZgGUAwBjjAQs5HA6Hw+HUFK5U9oM9hgIPA2jEGGvAGFMBiAewxQ7lcDgcDofD4TgVovdYEZGRMfYqgB0A5ABWEtFpscvhcDgcDofDcTZEd7cgSAk+FMjhcDgcDqfmcJSIYir6gXte53A4HA6HwxEJblhxOBwOh8PhiAQ3rDgcDofD4XBEghtWHA6Hw+FwOCLBDSsOh8PhcDgckeCGFYfD4XA4HI5IcMOKw+FwOBwORyS4YcXhcDgcDocjEtyw4nA4HA6HwxEJblhxOBwOh8PhiAQ3rDgcDofDqWHIZPz17ayIHoSZw+FwOByO7SiVSmg0Gvj7+6Nu3bqIjIyEj48PIiMj4erqih07diApKUlqNTkPwQ0rDofD4XAkhDEGlUqFgIAANGrUCJGRkfD19UVcXBxCQkLg7e0NnU4HpVL5t3R3797F559/DiKSSHNORXDDisPhcDgciWjfvj0mTZqE+vXro1GjRnB3d4dcLrcobU5ODjeqnBBuWHE4HA6HIxEDBgxA3759pVaDIyLVzn5jjK1kjN1ijJ0qt8+bMbaLMXah9K9X6X7GGPuEMXaRMXaSMRZtT+U5HA6Hw6nJ8EnotQ9LzugqAN0f2vcmgN1E1AjA7tL/AaAHgEalMgrAUnHU5HA4HA6ndqFQKBAVFSU4vdlsFlEbjlhUa1gR0X4A2Q/t/jeA1aXbqwH0Krd/Dd3nIABPxliAWMpyOBwOh1NbYIzBxcVFcPpjx46JqA1HLIT2QfoT0fXS7RsA/Eu3AwGklzvuWuk+DofD4XA4ImLpJHeOY7F58joREWPM6mUJjLFRuD9cyOFwOBzOI4erqyu8vLwEp/f29hZRG45YCO2xulk2xFf691bp/gwAweWOCyrd9w+IaBkRxRBRjEAdOBwOh/OI4ObmhunTp8PHx0dqVUTD1dXVpvqkpaWJpwxHNIQaVlsADCvdHgbgh3L7h5auDmwLIK/ckCGHw+FwOIIICQnBW2+9hR9//BGhoaFSqyMKjDEwxqRWgyMy1Q4FMsY2AOgIwJcxdg3ALADzAXzDGBsB4AqAF0sP3wrgGQAXARQCGG4HnTkcziOGWq1GQEAANBoNGjZsCIPBgM6dO8NgMODq1avIyckBAOj1epw5cwYZGRkoKiqSWGuOmDRs2BBqtRrt2rXDxo0b0b9//xrfY6NSqbi7hVpItYYVEQ2o5KfOFRxLAMbaqhSHw3l0USqVqF+/PgICAtChQwdEREQgIiICUVFRUCqVUKvVIKIKJ+4SEQoKCnDu3DkcO3YMV69exapVq3Djxg0YjUYJasMRC39//wdGSGxsLDZt2oTExEQcOXJEYs2EExERIXhVoNFofPBBwXEuuOd1DocjOR4eHmjevDl69OiBuLg4tGzZssLYaNXBGIOrqytat26N1q1bAwBeffVVnDp1Cjt37sRXX32F69ev8zAgNZB69er97f+YmBhs2bIFL774In799VeJtLINmUwmeChQr9fX+B67WgsRSS4AiAsXLo+WqFQqatKkCU2aNImSk5OppKSE7InZbKbMzExasmQJxcTEkEKhkLwNuFgu69atq/C8njhxglq0aCG5fkJk6tSpgq/n/Px8Cg0NlbwOj7AcoUpsGj64y+FwHIq7uzuGDBmCHTt24NChQ/jwww/RsmVLq3unrIUxhoCAAIwZMwb79u3D0qVL0aRJEz55uIbTokULbNu2Dc8991yNm69Um1Y4cv5HzboKORxOjcXHxweJiYn47bff8OWXX6Jjx45wd3eXRBedToeRI0fiwIEDePPNN7k/oBpAVQZwvXr18PXXX6Nbt24O1IjDqRhuWHE4HLuiUqnQq1cv7Nq1C0uWLEFUVJTTeIz29fXF3LlzsW3bNkRHR/PeKydFrVYjIiKiymN0Oh0+/fRT9O7du8b1XAmhsLAQxcXFUqvBqYDaf/VxOBzJiIqKwldffYWvv/4ajz32mFMaLowxxMbGYvv27ejXrx8UCr6mx9koKSnB1atXqz0uPDwc69atQ79+/ZzyWnsYrVYrOG1OTg7y8/NF1IYjFtyw4nA4ouPu7o6RI0di9+7d6NevH9RqtdQqVUudOnWwevVqjB07lhtXToZSqYS/v3/1B+K+sbJ06VJMnDjRqY0ruVyOli1bCk5fWFiIkpISETXiiAU3rDgcjqi0bNkS27Ztw+effw4/Pz+p1bEKjUaDBQsW4JNPPqkRxuCjglwut2qit5eXF2bNmoXRo0c7zbDzwzDGbDLgU1JSuGHlpPDPMg6HIwpqtRoDBgzAvHnzULduXanVEYxarcbIkSORmZmJ+fPnc8eiNRQPDw988MEHaNSoEaZPn47CwkKpVfob3t7eCAsLE5zeWedXqVQquLu7Q6lUIjw8HNHR0XBxccGFCxfw3XffPRI+5LhhxeFwbMbFxQVz5szBq6++ane3CY5AqVRixowZMBqNeO+992A2m6VW6ZFGoVAI6nnSarWYMGECAgIC8PrrryMzM9MO2glDJpPZ1GMlpWEll8uh0+ng7u6OBg0aIDg4GJGRkXBxcUHbtm0RFhYGuVwOT0/PB3XMyspCcnIyLl68KJnejoIbVhwOxya8vb3xwQcfYOjQobVqNZZKpcLkyZOxfft2JCcnS63OI42rqytcXV0FpZXJZIiPj4fRaERCQoLT9VwJ5ejRo3bLWy6XQy6XQ6lUwtfXF25ubujSpQvq168PmUyGFi1aoF69evDz84Orq6tFH1O+vr544YUX8N5779lNb2eBG1YcDkcwfn5+WL16NZ5++mmnnigsFG9vbyQlJaFnz564c+eO1Oo8sri7u8PNzc2mPAYOHAij0Yi33noL169fF0kz6RBjiFomk6FOnTqoU6cOmjdv/sBoatGiBerWrQu1Wo3AwEAoFArodDqbyxs4cCA+++wz3Lt3z+a8nBluWHE4HEE0btwYH3zwgcOMqrIl93q9HkqlEoGBgQDuD/fYc4JymzZtMHv2bEycOBEGg8Fu5XAqhzFmc2+oTCbDSy+9hPDwcLz44ou4ceOGSNoJQ6PROGRivVqtRkhICFQqFfz9/REaGormzZvD09MT3t7eaN26Ndzd3QX3CFpDs2bN0KFDB+zYscPuZUkJN6w4HI7V1K9fHxs2bEB0dLToeev1ely8eBFnz57FyZMnce7cOQDA9evXcfLkSRQXF0OpVMLPzw+MMTRq1AiPP/44nnjiCbRq1couL4hXXnkFv/zyC7777jvR8+Y4lscffxwrV65EYmIirly5IpkeDRo0EBx5oKSkpNq5SpGRkZg2bRrCw8PRvHlzKJVKyOVySV2JKBQKJCQkYPfu3bV7UUhlQQQdKZA+mCIXLlwslPr169Pvv/8uOHhsRRgMBjp27Bi98cYbFBMTQzqdjmQymVV6qdVqatmyJa1bt46uXr0qqn5ERCkpKeTr6yt5+z+K8vzzz5P
"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": "9fda42a9",
"metadata": {
"id": "9fda42a9"
},
"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": 28,
"id": "d98a9973",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 313
},
"executionInfo": {
"elapsed": 1176,
"status": "ok",
"timestamp": 1668432398142,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "d98a9973",
"outputId": "911d9a3b-19ac-4fe0-a4f0-13d79212e609"
},
"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": "fccd4605",
"metadata": {
"id": "fccd4605"
},
"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": 29,
"id": "0754cee5",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 400
},
"executionInfo": {
"elapsed": 3705,
"status": "ok",
"timestamp": 1668432415512,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "0754cee5",
"outputId": "094d3518-d6df-49a9-b2fd-86d7ac947600"
},
"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": "1a63dd4c",
"metadata": {
"id": "1a63dd4c"
},
"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": 30,
"id": "2b02eb5f",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 313
},
"executionInfo": {
"elapsed": 2178,
"status": "ok",
"timestamp": 1668432422835,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "2b02eb5f",
"outputId": "259c869e-0b71-40a5-cab1-03cc7a096153"
},
"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": "e37f716a",
"metadata": {
"id": "e37f716a"
},
"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": 31,
"id": "91f86157",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 178
},
"executionInfo": {
"elapsed": 512,
"status": "ok",
"timestamp": 1668432430152,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "91f86157",
"outputId": "dbef439c-e166-419c-b9dd-d7774c613c54"
},
"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": "6dac2bf4",
"metadata": {
"id": "6dac2bf4"
},
"source": [
"## Kontury"
]
},
{
"cell_type": "markdown",
"id": "046e4cfe",
"metadata": {
"id": "046e4cfe"
},
"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": 32,
"id": "a785f7ff",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 277
},
"executionInfo": {
"elapsed": 1365,
"status": "ok",
"timestamp": 1668432439228,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "a785f7ff",
"outputId": "8247b5a1-2394-4a0d-b83d-4d98565fb081"
},
"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": "fe0024db",
"metadata": {
"id": "fe0024db"
},
"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": 33,
"id": "b6b7b6fd",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 391,
"status": "ok",
"timestamp": 1668432455350,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "b6b7b6fd",
"outputId": "b96d0614-f14b-4774-cd6c-742aa992e67e"
},
"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": {
"id": "8fb4fa32"
},
"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": 34,
"id": "eb7fe829",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 663,
"status": "ok",
"timestamp": 1668432458504,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "eb7fe829",
"outputId": "691ccdbb-a79c-41a9-c390-d87545bd880c"
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAWsAAAEyCAYAAAA8x/FHAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3dd3xT1fvA8c9JFy0UyqbsvQQERcCBskFEEQcKLhR+KF8Qt+D4Km78ynCi4kREhqCCi42AykaWDCl7yYZSupvz++PcNilt6Uxukj7v1yuv5p57b/I0TZ6enHuG0lojhBDCtznsDkAIIUTuJFkLIYQfkGQthBB+QJK1EEL4AUnWQgjhByRZCyGEH/BYslZK9VBK7VBKxSilRnrqeYQQojhQnuhnrZQKAv4BugIHgTVAP6311iJ/MiGEKAY8VbNuA8RorXdrrZOBaUBvDz2XEEIEvGAPPW414IDb9kGgrfsBSqnBwGBr83IPxSGEEP7khNa6YnY7PJWsc6W1nghMBFBKyZh3IYSAfTnt8FQzyCGghtt2datMCCFEAXgqWa8BGiil6iilQoE7gTkeei4hhAh4HmkG0VqnKqWGAfOAIOBzrfXfnnguIYQoDjzSdS/fQUibtRBCAKzTWrfOboeMYBRCCD8gyVoIIfyAbV33hBABLjoaQkJc2/HxcOKEffH4OUnWQojCcTjg6quzlk+eDLVqubaXLIEXX8x8TFoa/PmnZ+MLEIF7gbFvXyhZMmv5okWwf3+RP50QxU6vXlCxIoSFwYcfFuwxkpJgyBBzf8cOSdwXucAYWMn6uuvg+uvN/SFDoHTprMd89x3s3Alaw7PPmp9CiLzr1Am6dYN77oGqVS9+rHbSbNlrbLnuv7k/7oYNMG+euT92LBw/XvhY/U8xSNZt28Knn0KzZnk7XmuYMsW84YQQuatbF8aMgcaNoUmTLLuj/t1Ei98uaObQmqoxcznc4Posx6+86VOSI8pn/1wLF0Lv3qadu3gJ8GTdoIH5j1ynTqbioKQkBrVpA8D2Pn1YOmpU5vNSU+GHH+D22wv19EIENIcD1q2DiAho2DDzPq3pMfEKHM4UgpPjiDy9O88Pe7ZiE5yOEOJLV+e3u37OesDmzXDyJHTsWMhfwK8EcLIuWxZ274aoKLOtNf1uvJHqK1eC1kScOgVAalgYyaVKAfDl0qUcb9oUlDIJe9o0qWELkR2lzOerVi1zH6ymQ03Hr6+n/OF1hCacRBXiKbRykFyiLAAbO73MztZDXM/ldMLSpdC5c3FpsgzQZB0VBceOZXQPCkpM5MbBg2kxefJF3zxOh4P3YmI4U7u2eVNoDe+8AyNGQHJygUIRIuCULAlr10KjRqAUyplKcNI5mv45lkt+fwO0s1BJOjsaxe+3T+dI3S6klIhyfT6dThg/3lxnSkkp4mf1KQGarE+ehHLlAAiNjaXDqFFcOX58nk7VSjFhyxZONG3qKhw0CD77rEChCBFQqlSBGTOgfXsAlDOVGtu+p/23fb0WwtxBKzlZrY2rlg3wzDOmYpWQ4LU4vCywh5uHxsZyzZtv5jlRAyitGdS2LbV++81V2KJFRvIXotiqVQs+/jgjUaOd1NoyzauJGqD7Z1dR7Z8fqbR3mavwjTdg2DAoUcKrsfgC/61Z33uv6dsZEUGlTZsYcumlBXruo82a8dHmza6C666DZctyPkGIQFazJowbB7femlHUaOU7XD730SJv8sir+MhqrO71IYca3egqrF4dDgXkFPkBWLN+8klzdbqQSh86ROsJE4ogICH8XMWKMGFCpkTdYvELtJr/lG2JGiDi3CFa//oI1bf94Cp8800ICrIvKBv4b7K2hMbGctOgQQU+P/z0aerNn1+EEQnhh0qUgDlz4IYbMopaLhhJkxVjCXLaf0Gv1Jk9lD+8xlXQvz/8nE13vwDm93ODOFJTqbZmTe4HCv9UsiRs2mR3FDBqlJnrIlAFBUG7dhmbzZa+TKNV7xKc6jsX8hqumcCpqpdzoMkt5qJj167w22/QoYPdoXmF3ydrEeAOH85+2gBv+/RT00a6eLHdkXiGW/tv/XUTab70FRzOVBsDyio08QxXz+zHonsXcrzmNWawTs2aEBxsxksEOL9P1trh4HzFipQs4DwCacHBJEgPEN9lXZcIS0yk/MmTXn/6pLAwTlaoAKGhgdtGWqVKxuvsSE0kLP5EoRN1Ung50oKz77ERmnC6wDX2oLRkun5xLd8/foCE0tWhdm2YP9/MVxLg/D5ZJ0VF8dXChQXuDXKicWPmfP55EUclilqnxYv5xa091VvmdetGj/TJhQLV+vUZA8sq7VtOy0XPFfihEkpWJq5sHdZ3H8uJGldle0zz314iOmYu5Q6vK1B7uALKHV7HociqoBzmm1edOrBnT4Hj9gf+e4Hxxx/N9IpAYlQUe6+7Lt8PkRoayj83unUHWrECjh4tqghFEdLKzv4IAaxHDwgPByA4KZYquxcW6GFSQkuxu8XdbOgymvmDVuSYqAE2d3iR+YNWsPOKh9jbrF+Bnu+6aTfjSLMS/eWXm9HHAc5/a9bPPQcPPQRhYcTWrMnKRx6h9tKl+XqIlJIlWfz6666Czz4zc+oKn6N8YDxAQBo1KmNenRLnj3HJH//L90M4HSFs6DKaf9oMzbrz1VchMdHcb9YM7rwzY9e6699FpaWQEFmFJivyPqAtXbNlr7Gp08v5Ps9f+W/NGmDgQDNnAHC4TRs29e+f51O1UsxxH1o+Z07gXjwSIheO1ERa/zI83+dp4I9bv86aqN94wywA8tJL8Npr5vbUU6bMbdCZDgphU8eX2ZyX+a7dKKDJn2NcBV26ZOp2GIj8O1nPnp1x91y1aswfO5aP167lSKtWFz3t22nTmLh2LdtvvtlVuH17wLd5+TNpBvGAV17JmP/d4UylWsyv+X6IJXfPZX/T21wFM2eaZonRo+HbbzP30jh40JTde6855tgxAFJDS7H1qqfY0v7Zgv8u9eplnb41wPhvMwiY2bgaNzZNF0pxvkoVzlepwleLFuFISeHRWrUITv8KBix94QXWDB1KQrly6OBg12PMnQsvF5+vU0IApidF+tJ3BWhm0sCZys3NRT6tTY35/vshLu7iJ+7bZ25Nm5oug2FhpIZFcr5MTTTkebRkUGoCPT5uzdwH1+Y7dn/k38kazBJdLVvC8uWme1WJEiSWNXPjvnHuXKZDtcNh+maCeXOdOwdbt5q15KzmFCGKHa259a1K+T5t/gO/k1Aq2mzs3m26z+Xnc3TypBniHhsLQMzl/0eZ49tovOqdPJ2ugLAEt+6cYWGme2VaWt5j8CP+3QySbtMmKFMGHn7Y1LKtpYB0cHCmW0ai3rvXNHtERcGVV0qiFsWew5m/BJdQqgqpoSXNSEKn0yTrgnyOUlLMuQDKQUKpyqSEZLPQdV688Ybp3RKg/L9m7e7TT83trbcuvhbjkCEmYQu/Ib1BfMv6bm9xpkpLs5GQYBbQLYjERHNx0ErYW9s/Q6X9v1Nt5y95Oj0oJYHyh1abea8DXGAl63RPPWV3BKKIyQXGInbFFWYFmMLS2sx9XRixsfDdd3DLLfk+Nfz8UVouGMGiAUsKF4MfCIxmEBHwpGZdxLp3Nwm7KIwcWbjzT56E998vmlgCmCRr4RekZu05V8/sh/KxSZtEVpKshV+QmrXnVN63FIW8vr5OkrXwC1Kz9pzZw3fidBTi8tWBA4ULoHbtYreQQEFIshZ+QWrWRez8+YwVwtNCSpL3oShGaOJZVFqy6boXGQkVKhQ8lkqVMk0mFZSalOdTnSqI5PDiMcWxJGvhF6RmXcTGj4dZswp8+hW/DKPckfVmIyICVq4s2ANFRMCqVRmbLZaMosqeRXk+Pb5MDZbfUfDfw59IshZ+QWrWvid613yCUqxFBEqVgo4d8/8gbovzljoZQ+mT2wse0Pr1ZmWhAFWoZK2U2quU2qyU2qCUWmuVlVNKLVBK7bR+li2aUEVxJjVr33PpkhcJTTxtNipXNgPS8jPz3eOPg9vCH1X2LKLazvxPJpXh66/hr78Kfr6PK4q
"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": "bbe70d91",
"metadata": {
"id": "bbe70d91"
},
"source": [
"Możemy również ograniczyć się tylko do zewnętrznych konturów (parametr `cv.RETR_EXTERNAL`):"
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "dfab04dc",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 340
},
"executionInfo": {
"elapsed": 876,
"status": "ok",
"timestamp": 1668432464504,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "dfab04dc",
"outputId": "00c5ba6e-a41a-4b98-dc69-e358a023756a"
},
"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": "0e0a0799",
"metadata": {
"id": "0e0a0799"
},
"source": [
"Poniżej mamy zaznaczony obrys konturu wybranego obiektu, np. o indeksie 5:"
]
},
{
"cell_type": "code",
"execution_count": 36,
"id": "5756eaeb",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 362,
"status": "ok",
"timestamp": 1668432472716,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "5756eaeb",
"outputId": "e8ee591c-c3a0-406d-cc1f-c2f76d85be9a"
},
"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, 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": {
"id": "05e6211d"
},
"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": 37,
"id": "2315e142",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 615,
"status": "ok",
"timestamp": 1668432478180,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "2315e142",
"outputId": "fb80d4c6-4655-4d5b-92c1-6a8ca10fea6c"
},
"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": "07e0820a",
"metadata": {
"id": "07e0820a"
},
"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": 38,
"id": "894b7fb1",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 331,
"status": "ok",
"timestamp": 1668432495552,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "894b7fb1",
"outputId": "ad2a7374-99c0-4e51-c7bb-44a57d257a14"
},
"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": {
"id": "9311c0d9"
},
"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": 39,
"id": "a00e03ce",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 443,
"status": "ok",
"timestamp": 1668432496416,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "a00e03ce",
"outputId": "f97e637b-59ec-4007-a0ec-197d97e6acec"
},
"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": {
"id": "3873897e"
},
"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": 40,
"id": "54160020",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 361,
"status": "ok",
"timestamp": 1668432502619,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "54160020",
"outputId": "ca2c78a0-1e81-44e7-a2c5-41f53f9e3713"
},
"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": "38d0f1f2",
"metadata": {
"id": "38d0f1f2"
},
"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": 41,
"id": "9184cd42",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 549,
"status": "ok",
"timestamp": 1668432510640,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "9184cd42",
"outputId": "5eb5c881-3526-4275-c3a2-88a7dbd47a35"
},
"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": "e3c9d01b",
"metadata": {
"id": "e3c9d01b"
},
"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": 42,
"id": "16f9d71b",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 487,
"status": "ok",
"timestamp": 1668432518719,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "16f9d71b",
"outputId": "635bc815-85dc-4d45-a997-03f150cefa79"
},
"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": "8128584a",
"metadata": {
"id": "8128584a"
},
"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": 43,
"id": "dfee5d44",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 323
},
"executionInfo": {
"elapsed": 527,
"status": "ok",
"timestamp": 1668432521344,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "dfee5d44",
"outputId": "249327dc-b0f8-413d-d593-56e2ee6f9e93"
},
"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": "de2ca7bf",
"metadata": {
"id": "de2ca7bf"
},
"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": 44,
"id": "1bb452fb",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"executionInfo": {
"elapsed": 2036,
"status": "ok",
"timestamp": 1668432544826,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "1bb452fb",
"outputId": "6e263d9b-22fa-4d62-92db-190c5e90dbca"
},
"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": "7f8071d0",
"metadata": {
"id": "7f8071d0"
},
"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": 45,
"id": "08e79f26",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"executionInfo": {
"elapsed": 1450,
"status": "ok",
"timestamp": 1668432554349,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "08e79f26",
"outputId": "e488edb9-1195-4a9b-ca33-4b82f0131c2f"
},
"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": "dc1e0958",
"metadata": {
"id": "dc1e0958"
},
"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": 75,
"id": "5900ec2b",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 352
},
"executionInfo": {
"elapsed": 1456,
"status": "ok",
"timestamp": 1668434187069,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "5900ec2b",
"outputId": "a9340b66-f091-407f-9f8b-ceed352e8855"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"No. of contours: 7\n"
]
},
{
"data": {
"text/plain": [
"Text(0.5, 1.0, 'Kontury')"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1080x360 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"coins_color = cv.imread(\"img/coins.png\", cv.IMREAD_COLOR)\n",
"coins_gray = cv.cvtColor(coins_color, cv.COLOR_BGR2GRAY)\n",
"_, coins = cv.threshold(coins_gray, 170, 255, cv.THRESH_BINARY_INV)\n",
"\n",
"coins_contours, _ = cv.findContours(coins, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)\n",
"print(f\"No. of contours: {len(coins_contours)}\")\n",
"\n",
"coins_with_contours = coins.copy()\n",
"#cv.drawContours(coins_with_contours, coins_contours, -1, (255,255,0), 2)\n",
"\n",
"for idx, contour in enumerate(coins_contours):\n",
" (x,y), radius = cv.minEnclosingCircle(contour)\n",
" cv.circle(coins_with_contours, (int(x),int(y)), int(round(radius)), (255,0,255), -1)\n",
"\n",
" cv.putText(coins_with_contours, str(idx+1), (int(x)+10, int(y)+10), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 200, 255), 2)\n",
"\n",
"_, bologna_labels = cv.connectedComponents(coins_with_contours)\n",
"\n",
"coins_color = cv.cvtColor(coins_color, cv.COLOR_BGR2RGB)\n",
"plt.figure(figsize=[15,5])\n",
"plt.subplot(121)\n",
"plt.imshow(coins_color)\n",
"plt.title(\"Color\")\n",
"plt.subplot(122)\n",
"plt.imshow(bologna_labels, cmap='inferno')\n",
"plt.title(\"Kontury\")"
]
},
{
"cell_type": "markdown",
"id": "55ce79c1",
"metadata": {
"id": "55ce79c1"
},
"source": [
"![Wykryte monety](img/coins_detected.png)"
]
}
],
"metadata": {
"author": "Andrzej Wójtowicz",
"colab": {
"collapsed_sections": [],
"provenance": []
},
"email": "andre@amu.edu.pl",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10"
},
"subtitle": "02. Operacje binarne na obrazach [laboratoria]",
"title": "Widzenie komputerowe",
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}