621 lines
20 KiB
Plaintext
621 lines
20 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "819ce420",
|
|
"metadata": {},
|
|
"source": [
|
|
"![Logo 1](img/aitech-logotyp-1.jpg)\n",
|
|
"<div class=\"alert alert-block alert-info\">\n",
|
|
"<h1> Widzenie komputerowe </h1>\n",
|
|
"<h2> 06. <i>Rozpoznawanie i segmentacja obrazów</i> [laboratoria]</h2> \n",
|
|
"<h3>Andrzej Wójtowicz (2021)</h3>\n",
|
|
"</div>\n",
|
|
"\n",
|
|
"![Logo 2](img/aitech-logotyp-2.jpg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a6dc5acc",
|
|
"metadata": {},
|
|
"source": [
|
|
"W poniższych materiałach zobaczymy w jaki sposób możemy klasycznym podejściem rozpoznawać ludzi na zdjęciach, a ponadto w jaki sposób szybko podzielić obraz na elementy znajdujące się na pierwszym planie i w tle obrazu.\n",
|
|
"\n",
|
|
"Na początku załadujmy niezbędne biblioteki."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e45bb312",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import cv2 as cv\n",
|
|
"import numpy as np\n",
|
|
"import sklearn.svm\n",
|
|
"import sklearn.metrics\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"%matplotlib inline\n",
|
|
"import os\n",
|
|
"import random"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5b757675",
|
|
"metadata": {},
|
|
"source": [
|
|
"Naszym głównym celem będzie rozpoznawanie ludzi na zdjęciach przy pomocy klasycznej metody *histogram of oriented gradients* (HOG). Krótko mówiąc, dla danego zdjęcia chcemy uzyskać wektor cech, który będziemy mogli wykorzystać w klasyfikatorze SVM. Szczegóły znajdują się w *6.3.2 Pedestrian detection* R. Szeliski (2022) *Computer Vision: Algorithms and Applications*, natomiast tutaj zobrazujemy techniczne wykorzystanie tej metody.\n",
|
|
"\n",
|
|
"# Klasyfikacja obrazów przy użyciu HOG i SVM\n",
|
|
"\n",
|
|
"Spróbjemy zbudować klasyfikator, który wskazuje czy na zdjęciu znajduje się osoba z okularami czy bez okularów. Rozpakujmy zbiór danych, z którego będziemy korzystali:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7b953b82",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!cd datasets && unzip -qo glasses.zip"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f4a457f3",
|
|
"metadata": {},
|
|
"source": [
|
|
"Następnie wczytujemy dane i dzielimy je na dwa zbiory w proporcjach 80/20:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "737d95c1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"dataset_dir = \"datasets/glasses\"\n",
|
|
"images_0 = os.listdir(f\"{dataset_dir}/with\")\n",
|
|
"images_0 = [f\"{dataset_dir}/with/{x}\" for x in images_0]\n",
|
|
"images_1 = os.listdir(f\"{dataset_dir}/without\")\n",
|
|
"images_1 = [f\"{dataset_dir}/without/{x}\" for x in images_1]\n",
|
|
"images = images_0 + images_1\n",
|
|
"random.seed(1337)\n",
|
|
"random.shuffle(images)\n",
|
|
"\n",
|
|
"train_data = []\n",
|
|
"test_data = []\n",
|
|
"train_labels = []\n",
|
|
"test_labels = []\n",
|
|
"\n",
|
|
"splitval = int((1-0.2)*len(images))\n",
|
|
"\n",
|
|
"for x in images[:splitval]:\n",
|
|
" train_data.append(cv.imread(x, cv.IMREAD_COLOR))\n",
|
|
" train_labels.append(x.split(\"/\")[2])\n",
|
|
" \n",
|
|
"for x in images[splitval:]:\n",
|
|
" test_data.append(cv.imread(x, cv.IMREAD_COLOR))\n",
|
|
" test_labels.append(x.split(\"/\")[2])\n",
|
|
" \n",
|
|
"d_labels = {\"with\": 0, \"without\": 1}\n",
|
|
" \n",
|
|
"train_labels = np.array([d_labels[x] for x in train_labels])\n",
|
|
"test_labels = np.array([d_labels[x] for x in test_labels])\n",
|
|
"\n",
|
|
"print(f\"Train data: {len(train_data)}, test data: {len(test_data)}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "265147e3",
|
|
"metadata": {},
|
|
"source": [
|
|
"Poniżej znajduje się kilka przykładowych zdjęć."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e0595915",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.figure(figsize=(10,2))\n",
|
|
"for i in range(5):\n",
|
|
" plt.subplot(151 + i)\n",
|
|
" plt.imshow(train_data[i][:,:,::-1]);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e05e27e8",
|
|
"metadata": {},
|
|
"source": [
|
|
"Tworzymy deskryptor HOG przy pomocy funkcji [`cv.HOGDescriptor()`](https://docs.opencv.org/4.5.3/d5/d33/structcv_1_1HOGDescriptor.html). Metodą [`compute()`](https://docs.opencv.org/4.5.3/d5/d33/structcv_1_1HOGDescriptor.html#a38cd712cd5a6d9ed0344731fcd121e8b) tworzymy wektory cech, które posłużą nam jako dane wejściowe do klasyfikatora. Poniżej znajduje się również przykładowa konfiguracja deskryptora:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f21e8924",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"hp_win_size = (96, 32)\n",
|
|
"hp_block_size = (8, 8)\n",
|
|
"hp_block_stride = (8, 8)\n",
|
|
"hp_cell_size = (4, 4)\n",
|
|
"hp_n_bins = 9\n",
|
|
"hp_deriv_aperture = 0\n",
|
|
"hp_win_sigma = 4.0\n",
|
|
"hp_histogram_norm_type = 1\n",
|
|
"hp_l2_hys_threshold = 0.2\n",
|
|
"hp_gamma_correction = True\n",
|
|
"hp_n_levels = 64\n",
|
|
"hp_signed_gradient = True\n",
|
|
"\n",
|
|
"hog_descriptor = cv.HOGDescriptor(\n",
|
|
" hp_win_size, hp_block_size, hp_block_stride, hp_cell_size, \n",
|
|
" hp_n_bins, hp_deriv_aperture, hp_win_sigma, \n",
|
|
" hp_histogram_norm_type, hp_l2_hys_threshold, \n",
|
|
" hp_gamma_correction, hp_n_levels, hp_signed_gradient)\n",
|
|
"\n",
|
|
"train_hog = np.vstack([hog_descriptor.compute(x).ravel() for x in train_data])\n",
|
|
"test_hog = np.vstack([hog_descriptor.compute(x).ravel() for x in test_data])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "755b8ebe",
|
|
"metadata": {},
|
|
"source": [
|
|
"Do klasyfikacji użyjemy klasyfikatora SVM. Możemy użyć implementacji znajdującej się w module [`cv.ml`](https://docs.opencv.org/4.5.3/d1/d2d/classcv_1_1ml_1_1SVM.html):"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b46783d4",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model = cv.ml.SVM_create()\n",
|
|
"model.setGamma(0.02)\n",
|
|
"model.setC(2.5)\n",
|
|
"model.setKernel(cv.ml.SVM_RBF)\n",
|
|
"model.setType(cv.ml.SVM_C_SVC)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d8f47c54",
|
|
"metadata": {},
|
|
"source": [
|
|
"Trenujemy model:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "810f9a1e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model.train(np.array(train_hog), cv.ml.ROW_SAMPLE, train_labels);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "69d39eee",
|
|
"metadata": {},
|
|
"source": [
|
|
"Sprawdzamy wynik na danych testowych:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "763b6dc7",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"predictions = model.predict(test_hog)[1].ravel()\n",
|
|
"accuracy = (test_labels == predictions).mean()\n",
|
|
"print(f\"ACC: {accuracy * 100:.2f} %\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2dd04ec5",
|
|
"metadata": {},
|
|
"source": [
|
|
"Możemy również użyć implementacji klasyfikatora znajdującej się w bibliotece [`scikit-learn`](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html):"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "13b7ba1c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model = sklearn.svm.SVC(C=2.5, gamma=0.02, kernel='rbf')\n",
|
|
"model.fit(train_hog, train_labels)\n",
|
|
"\n",
|
|
"predictions = model.predict(test_hog)\n",
|
|
"accuracy = (test_labels == predictions).mean()\n",
|
|
"print(f\"ACC: {accuracy * 100:.2f} %\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2259c310",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Rozpoznawanie ludzi\n",
|
|
"\n",
|
|
"Powyższą metodykę klasyfikcji możemy zastosować do rozpoznawania obiektów na zdjęciach, np. ludzi. W tym wypadku będziemy chcieli wskazać gdzie na zdjęciu znajduje się dany obiekt lub obiekty.\n",
|
|
"\n",
|
|
"Rozpocznijmy od rozpakowania zbioru danych:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d8497390",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"!cd datasets && unzip -qo inria-person-sub.zip"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "30374bad",
|
|
"metadata": {},
|
|
"source": [
|
|
"Wczytujemy dane, które są już podzielone na dwa zbiory:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "978d77cf",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"dataset_dir = \"datasets/INRIAPerson\"\n",
|
|
"\n",
|
|
"images_train_0 = os.listdir(f\"{dataset_dir}/train_64x128_H96/negPatches\")\n",
|
|
"images_train_0 = [f\"{dataset_dir}/train_64x128_H96/negPatches/{x}\" for x in images_train_0]\n",
|
|
"images_train_1 = os.listdir(f\"{dataset_dir}/train_64x128_H96/posPatches\")\n",
|
|
"images_train_1 = [f\"{dataset_dir}/train_64x128_H96/posPatches/{x}\" for x in images_train_1]\n",
|
|
"\n",
|
|
"images_test_0 = os.listdir(f\"{dataset_dir}/test_64x128_H96/negPatches\")\n",
|
|
"images_test_0 = [f\"{dataset_dir}/test_64x128_H96/negPatches/{x}\" for x in images_test_0]\n",
|
|
"images_test_1 = os.listdir(f\"{dataset_dir}/test_64x128_H96/posPatches\")\n",
|
|
"images_test_1 = [f\"{dataset_dir}/test_64x128_H96/posPatches/{x}\" for x in images_test_1]\n",
|
|
"\n",
|
|
"train_data = []\n",
|
|
"test_data = []\n",
|
|
"train_labels = []\n",
|
|
"test_labels = []\n",
|
|
"\n",
|
|
"for x in images_train_0:\n",
|
|
" img = cv.imread(x, cv.IMREAD_COLOR)\n",
|
|
" if img is not None:\n",
|
|
" train_data.append(img)\n",
|
|
" train_labels.append(0)\n",
|
|
"\n",
|
|
"for x in images_train_1:\n",
|
|
" img = cv.imread(x, cv.IMREAD_COLOR)\n",
|
|
" if img is not None:\n",
|
|
" train_data.append(img)\n",
|
|
" train_labels.append(1)\n",
|
|
" \n",
|
|
"for x in images_test_0:\n",
|
|
" img = cv.imread(x, cv.IMREAD_COLOR)\n",
|
|
" if img is not None:\n",
|
|
" test_data.append(img)\n",
|
|
" test_labels.append(0)\n",
|
|
"\n",
|
|
"for x in images_test_1:\n",
|
|
" img = cv.imread(x, cv.IMREAD_COLOR)\n",
|
|
" if img is not None:\n",
|
|
" test_data.append(img)\n",
|
|
" test_labels.append(1)\n",
|
|
"\n",
|
|
"print(f\"Train data: {len(train_data)}, test data: {len(test_data)}\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9bf41d6e",
|
|
"metadata": {},
|
|
"source": [
|
|
"Poniżej znajduje się kilka przykładowych zdjęć ze zbioru:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f29d47c1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.figure(figsize=(10,2))\n",
|
|
"for i in range(3):\n",
|
|
" plt.subplot(161 + i)\n",
|
|
" plt.imshow(train_data[i][:,:,::-1]);\n",
|
|
"for i in range(3):\n",
|
|
" plt.subplot(164 + i)\n",
|
|
" plt.imshow(train_data[-(i+1)][:,:,::-1]);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "57cec468",
|
|
"metadata": {},
|
|
"source": [
|
|
"Tworzymy deskryptor i wektory cech:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d5248df2",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"hp_win_size = (64, 128)\n",
|
|
"hp_block_size = (16, 16)\n",
|
|
"hp_block_stride = (8, 8)\n",
|
|
"hp_cell_size = (8, 8)\n",
|
|
"hp_n_bins = 9\n",
|
|
"hp_deriv_aperture = 1\n",
|
|
"hp_win_sigma = -1\n",
|
|
"hp_histogram_norm_type = 0\n",
|
|
"hp_l2_hys_threshold = 0.2\n",
|
|
"hp_gamma_correction = True\n",
|
|
"hp_n_levels = 64\n",
|
|
"hp_signed_gradient = False\n",
|
|
"\n",
|
|
"hog_descriptor = cv.HOGDescriptor(\n",
|
|
" hp_win_size, hp_block_size, hp_block_stride, hp_cell_size, \n",
|
|
" hp_n_bins, hp_deriv_aperture, hp_win_sigma, \n",
|
|
" hp_histogram_norm_type, hp_l2_hys_threshold, \n",
|
|
" hp_gamma_correction, hp_n_levels, hp_signed_gradient)\n",
|
|
"\n",
|
|
"train_hog = np.vstack([hog_descriptor.compute(x).ravel() for x in train_data])\n",
|
|
"test_hog = np.vstack([hog_descriptor.compute(x).ravel() for x in test_data])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c6782aa9",
|
|
"metadata": {},
|
|
"source": [
|
|
"Następnie tworzymy klasyfikator:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8f6108ed",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model = cv.ml.SVM_create()\n",
|
|
"model.setGamma(0)\n",
|
|
"model.setC(0.01)\n",
|
|
"model.setKernel(cv.ml.SVM_LINEAR)\n",
|
|
"model.setType(cv.ml.SVM_C_SVC)\n",
|
|
"model.setTermCriteria((cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 1000, 1e-3))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "bbfbde58",
|
|
"metadata": {},
|
|
"source": [
|
|
"Uczymy model:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "afd0bbb4",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model.train(np.array(train_hog), cv.ml.ROW_SAMPLE, np.array(train_labels));"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "09626eed",
|
|
"metadata": {},
|
|
"source": [
|
|
"Sprawdzamy jakość klasyfikacji:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "fa3be6b6",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"predictions = model.predict(test_hog)[1].ravel()\n",
|
|
"accuracy = (test_labels == predictions).mean()\n",
|
|
"print(f\"ACC: {accuracy * 100:.2f} %\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c6df6682",
|
|
"metadata": {},
|
|
"source": [
|
|
"Poniżej znajduje się podejście przy pomocy biblioteki *scikit-learn*:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7b3de8d1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"model2 = sklearn.svm.SVC(C=0.01, gamma='auto', kernel='linear', max_iter=1000)\n",
|
|
"model2.fit(train_hog, train_labels)\n",
|
|
"\n",
|
|
"predictions = model2.predict(test_hog)\n",
|
|
"accuracy = (test_labels == predictions).mean()\n",
|
|
"print(f\"Accuracy: {sklearn.metrics.accuracy_score(test_labels, predictions) * 100:.2f} %\")\n",
|
|
"print(f\"Precision: {sklearn.metrics.precision_score(test_labels, predictions) * 100:.2f} %\")\n",
|
|
"print(f\"Recall: {sklearn.metrics.recall_score(test_labels, predictions) * 100:.2f} %\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6e84c568",
|
|
"metadata": {},
|
|
"source": [
|
|
"Mając teraz wyuczony model, chcielibyśmy sprawdzić czy np. na zdjęciu `img/pedestrians.jpg` znajdują się ludzie, tak aby uzyskać ew. obramowania z ich występowaniem. W pierwszej kolejności w naszym deskryptorze HOG ustawiamy współczynniki klasfikatora SVM przy pomocy metody [`setSVMDetector()`](https://docs.opencv.org/4.5.3/d5/d33/structcv_1_1HOGDescriptor.html#a6de5ac55631eed51e36278cde3a2c159). Następnie przy pomocy metody [`detectMultiScale()`](https://docs.opencv.org/4.5.3/d5/d33/structcv_1_1HOGDescriptor.html#a91e56a2c317392e50fbaa2f5dc78d30b) znajdujemy wyszukiwane obiekty (ludzi) w różnych skalach."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d6458103",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"image = cv.imread(\"img/pedestrians.jpg\", cv.IMREAD_COLOR)\n",
|
|
"scale = 600 / image.shape[0]\n",
|
|
"image = cv.resize(image, None, fx=scale, fy=scale)\n",
|
|
"\n",
|
|
"support_vectors = model.getSupportVectors()\n",
|
|
"rho, _, _ = model.getDecisionFunction(0)\n",
|
|
"detector = np.zeros(support_vectors.shape[1] + 1, dtype=support_vectors.dtype)\n",
|
|
"detector[:-1] = -support_vectors[:]\n",
|
|
"detector[-1] = rho\n",
|
|
"\n",
|
|
"hog_descriptor.setSVMDetector(detector)\n",
|
|
"\n",
|
|
"locations, weights = hog_descriptor.detectMultiScale(\n",
|
|
" image, winStride=(8, 8), padding=(32, 32), scale=1.05,\n",
|
|
" finalThreshold=2, hitThreshold=1.0)\n",
|
|
"\n",
|
|
"for location, weight in zip(locations, weights):\n",
|
|
" x1, y1, w, h = location\n",
|
|
" x2, y2 = x1 + w, y1 + h\n",
|
|
" cv.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), thickness=3, lineType=cv.LINE_AA)\n",
|
|
" cv.putText(image, f\"{weight[0]:.2f}\", (x1,y1), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2, cv.LINE_AA)\n",
|
|
"\n",
|
|
"plt.figure(figsize=(6,6))\n",
|
|
"plt.imshow(image[:,:,::-1]);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cd287c92",
|
|
"metadata": {},
|
|
"source": [
|
|
"Coś nam nawet udało się wykryć jak na tak niewielki zbiór danych uczących ;) Z drugiej strony, dwie osoby na pierwszym planie zostały pominięte, a osoba po prawej jest dyskusyjna jeśli chodzi o zakres oznaczenia.\n",
|
|
"\n",
|
|
"W OpenCV dostępny jest domyślny klasyfikator w funkcji [`HOGDescriptor_getDefaultPeopleDetector()`](https://docs.opencv.org/4.5.3/d5/d33/structcv_1_1HOGDescriptor.html#a9c7a0b2aa72cf39b4b32b3eddea78203) i poniżej możemy zobaczyć jak sobie radzi na badanym zdjęciu:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "57a745c9",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"image = cv.imread(\"img/pedestrians.jpg\", cv.IMREAD_COLOR)\n",
|
|
"scale = 600 / image.shape[0]\n",
|
|
"image = cv.resize(image, None, fx=scale, fy=scale)\n",
|
|
"\n",
|
|
"hog_dflt_descriptor = cv.HOGDescriptor(\n",
|
|
" hp_win_size, hp_block_size, hp_block_stride, hp_cell_size, \n",
|
|
" hp_n_bins, hp_deriv_aperture, hp_win_sigma, \n",
|
|
" hp_histogram_norm_type, hp_l2_hys_threshold, \n",
|
|
" hp_gamma_correction, hp_n_levels, hp_signed_gradient)\n",
|
|
"\n",
|
|
"detector_dflt = cv.HOGDescriptor_getDefaultPeopleDetector()\n",
|
|
"hog_dflt_descriptor.setSVMDetector(detector_dflt)\n",
|
|
"\n",
|
|
"locations, weights = hog_dflt_descriptor.detectMultiScale(\n",
|
|
" image, winStride=(8, 8), padding=(32, 32), scale=1.05,\n",
|
|
" finalThreshold=2, hitThreshold=1.0)\n",
|
|
"\n",
|
|
"for location, weight in zip(locations, weights):\n",
|
|
" x1, y1, w, h = location\n",
|
|
" x2, y2 = x1 + w, y1 + h\n",
|
|
" cv.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), thickness=3, lineType=cv.LINE_AA)\n",
|
|
" cv.putText(image, f\"{weight[0]:.2f}\", (x1,y1), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2, cv.LINE_AA)\n",
|
|
"\n",
|
|
"plt.figure(figsize=(6,6))\n",
|
|
"plt.imshow(image[:,:,::-1]);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6c8cf915",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Segmentacja obrazu metodą GrabCut\n",
|
|
"\n",
|
|
"## Zadanie 1\n",
|
|
"\n",
|
|
"W poniższym zadaniu użyjemy algorytmu [GrabCut](https://en.wikipedia.org/wiki/GrabCut), będącego interaktywną metodą segmentacji obrazu, dzielącą obraz na pierwszy i drugi plan. W OpenCV algorytm jest zaimplementowany w funkcji [`cv.grabCut()`](https://docs.opencv.org/4.5.3/d3/d47/group__imgproc__segmentation.html#ga909c1dda50efcbeaa3ce126be862b37f). Dodatkowe informacje o algorytmie znajdują się w [dokumentacji](https://docs.opencv.org/4.5.3/d8/d83/tutorial_py_grabcut.html).\n",
|
|
"\n",
|
|
"Przygotuj interaktywną aplikację, która wykorzystuje algorytm GrabCut. W aplikacji powinna być możliwość zaznaczenia początkowego prostokąta, a następnie elementy maski (zwróć uwagę z jakich elementów może składać się maska). Przykładowe działanie możesz zaprezentować na obrazie `img/messi5.jpg`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "35f22bca",
|
|
"metadata": {},
|
|
"source": [
|
|
"![GrabCut - wynik](img/grabcut-result.png)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"author": "Andrzej Wójtowicz",
|
|
"email": "andre@amu.edu.pl",
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"lang": "pl",
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.7.3"
|
|
},
|
|
"subtitle": "06. Segmentacja i rozpoznawanie obrazów [laboratoria]",
|
|
"title": "Widzenie komputerowe",
|
|
"year": "2021"
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|