s444380-wko/wko-09.ipynb

1343 lines
1.5 MiB
Plaintext
Raw Normal View History

2023-01-22 20:08:13 +01:00
{
"cells": [
{
"cell_type": "markdown",
"id": "80377b3b",
"metadata": {
"id": "80377b3b"
},
"source": [
"![Logo 1](img/aitech-logotyp-1.jpg)\n",
"<div class=\"alert alert-block alert-info\">\n",
"<h1> Widzenie komputerowe </h1>\n",
"<h2> 09. <i>Metody głębokiego uczenia (1)</i> [laboratoria]</h2> \n",
"<h3>Andrzej Wójtowicz (2021)</h3>\n",
"</div>\n",
"\n",
"![Logo 2](img/aitech-logotyp-2.jpg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "gnrjIhVmeHQQ",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 2133,
"status": "ok",
"timestamp": 1673872019054,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "gnrjIhVmeHQQ",
"outputId": "36f987aa-4863-43c5-84e2-c90d990d7cf6"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\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": "07159136",
"metadata": {
"id": "07159136"
},
"source": [
"W poniższym materiale zobaczymy w jaki sposób korzystać z metod głębokiego uczenia sieci neuronowych w pakiecie OpenCV.\n",
"\n",
"Na początku załadujmy niezbędne biblioteki:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b2e906f0",
"metadata": {
"id": "b2e906f0"
},
"outputs": [],
"source": [
"import cv2 as cv\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"id": "f4348bc5",
"metadata": {
"id": "f4348bc5"
},
"source": [
"OpenCV wspiera [wiele](https://github.com/opencv/opencv/wiki/Deep-Learning-in-OpenCV) bibliotek i modeli sieci neuronowych. Modele trenuje się poza OpenCV - bibliotekę wykorzystuje się tylko do predykcji, aczkolwiek sama w sobie ma całkiem sporo możliwych optymalizacji w porównaniu do źródłowych bibliotek neuronowych, więc predykcja może być tutaj faktycznie szybsza.\n",
"\n",
"Pliki z modelami i danymi pomocniczymi będziemy pobierali z sieci i będziemy je zapisywali w katalogu `dnn`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "42b85f55",
"metadata": {
"id": "42b85f55"
},
"outputs": [],
"source": [
"!mkdir -p dnn"
]
},
{
"cell_type": "markdown",
"id": "ac09b098",
"metadata": {
"id": "ac09b098"
},
"source": [
"# Klasyfikacja obrazów\n",
"\n",
"Spróbujemy wykorzystać sieć do klasyfikacji obrazów wyuczonej na zbiorze [ImageNet](https://www.image-net.org/). Pobierzmy plik zawierający opis 1000 możliwych klas:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "85b1b68c",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 523,
"status": "ok",
"timestamp": 1673870782915,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "85b1b68c",
"outputId": "834910f4-0f40-40dd-a763-c7ea03bcdb0b"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dnn/classification_ 100%[===================>] 21.17K --.-KB/s in 0.002s \n"
]
}
],
"source": [
"!wget -q --show-progress -O dnn/classification_classes_ILSVRC2012.txt https://raw.githubusercontent.com/opencv/opencv/master/samples/data/dnn/classification_classes_ILSVRC2012.txt "
]
},
{
"cell_type": "markdown",
"id": "fd0c577b",
"metadata": {
"id": "fd0c577b"
},
"source": [
"Spójrzmy na pierwsze pięć klas w pliku:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fb0d0546",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 309,
"status": "ok",
"timestamp": 1673870783220,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "fb0d0546",
"outputId": "e4d6d029-a709-4db9-ba61-074dda0f0167"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1000 ['tench, Tinca tinca', 'goldfish, Carassius auratus', 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias', 'tiger shark, Galeocerdo cuvieri', 'hammerhead, hammerhead shark']\n"
]
}
],
"source": [
"with open('dnn/classification_classes_ILSVRC2012.txt', 'r') as f_fd:\n",
" classes = f_fd.read().splitlines()\n",
" \n",
"print(len(classes), classes[:5])"
]
},
{
"cell_type": "markdown",
"id": "5b0ee6ff",
"metadata": {
"id": "5b0ee6ff"
},
"source": [
"Do klasyfikacji użyjemy sieci [DenseNet](https://arxiv.org/abs/1608.06993). Pobierzemy jedną z mniejszych [reimplementacji](https://github.com/shicai/DenseNet-Caffe), która jest hostowana m.in. na Google Drive (musimy doinstalować jeden pakiet):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fb2bf2a1",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 8460,
"status": "ok",
"timestamp": 1673870791676,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "fb2bf2a1",
"outputId": "8adc83f6-7f46-4d92-b781-8bdee129f9ea"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Requirement already satisfied: gdown in /usr/local/lib/python3.8/dist-packages (4.4.0)\n",
"Requirement already satisfied: requests[socks] in /usr/local/lib/python3.8/dist-packages (from gdown) (2.25.1)\n",
"Requirement already satisfied: six in /usr/local/lib/python3.8/dist-packages (from gdown) (1.15.0)\n",
"Requirement already satisfied: tqdm in /usr/local/lib/python3.8/dist-packages (from gdown) (4.64.1)\n",
"Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.8/dist-packages (from gdown) (4.6.3)\n",
"Requirement already satisfied: filelock in /usr/local/lib/python3.8/dist-packages (from gdown) (3.9.0)\n",
"Requirement already satisfied: chardet<5,>=3.0.2 in /usr/local/lib/python3.8/dist-packages (from requests[socks]->gdown) (4.0.0)\n",
"Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.8/dist-packages (from requests[socks]->gdown) (2.10)\n",
"Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.8/dist-packages (from requests[socks]->gdown) (1.24.3)\n",
"Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.8/dist-packages (from requests[socks]->gdown) (2022.12.7)\n",
"Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /usr/local/lib/python3.8/dist-packages (from requests[socks]->gdown) (1.7.1)\n"
]
}
],
"source": [
"!pip3 install --user --disable-pip-version-check gdown"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27996509",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 30749,
"status": "ok",
"timestamp": 1673870822419,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "27996509",
"outputId": "af15b1c7-5256-4687-c326-d184f9225bf1"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Access denied with the following error:\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"\n",
" \tCannot retrieve the public link of the file. You may need to change\n",
"\tthe permission to 'Anyone with the link', or have had many accesses. \n",
"\n",
"You may still be able to access the file from the browser:\n",
"\n",
"\t https://drive.google.com/uc?id=0B7ubpZO7HnlCcHlfNmJkU2VPelE \n",
"\n"
]
}
],
"source": [
"import gdown\n",
"\n",
"url = 'https://drive.google.com/uc?id=0B7ubpZO7HnlCcHlfNmJkU2VPelE'\n",
"output = 'dnn/DenseNet_121.caffemodel'\n",
"gdown.download(url, output, quiet=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "648ec9c9",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 30,
"status": "ok",
"timestamp": 1673870822421,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "648ec9c9",
"outputId": "033c3cb3-cf27-4ee4-cddc-1f0fb914823c"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dnn/DenseNet_121.pr 100%[===================>] 74.68K --.-KB/s in 0.01s \n"
]
}
],
"source": [
"!wget -q --show-progress -O dnn/DenseNet_121.prototxt https://raw.githubusercontent.com/shicai/DenseNet-Caffe/master/DenseNet_121.prototxt"
]
},
{
"cell_type": "markdown",
"id": "f7294c54",
"metadata": {
"id": "f7294c54"
},
"source": [
"Konkretne biblioteki neuronowe posiadają dedykowane funkcje do ładowania modeli, np. [`readNetFromCaffe()`](https://docs.opencv.org/4.5.3/d6/d0f/group__dnn.html#ga29d0ea5e52b1d1a6c2681e3f7d68473a) lub [`readNetFromTorch()`](https://docs.opencv.org/4.5.3/d6/d0f/group__dnn.html#ga65a1da76cb7d6852bdf7abbd96f19084), jednak można też użyć ogólnej [`readNet()`](https://docs.opencv.org/4.5.3/d6/d0f/group__dnn.html#ga3b34fe7a29494a6a4295c169a7d32422):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6fd2d6b3",
"metadata": {
"id": "6fd2d6b3"
},
"outputs": [],
"source": [
"model = cv.dnn.readNet(model='dnn/DenseNet_121.prototxt', config='dnn/DenseNet_121.caffemodel', framework='Caffe')"
]
},
{
"cell_type": "markdown",
"id": "fe22fd6f",
"metadata": {
"id": "fe22fd6f"
},
"source": [
"Spróbujemy sklasyfikować poniższy obraz:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6ace4606",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 324
},
"executionInfo": {
"elapsed": 1774,
"status": "ok",
"timestamp": 1673872039753,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "6ace4606",
"outputId": "d40ea7ed-a573-45d3-d222-3de0bfca6664"
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 360x360 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"image = cv.imread('img/flamingo.jpg')\n",
"plt.figure(figsize=[5,5])\n",
"plt.imshow(image[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "e51db3ac",
"metadata": {
"id": "e51db3ac"
},
"source": [
"Aby móc przepuścić obraz przez sieć musimy zmienić jego formę reprezentacji poprzez funkcję [`blobFromImage()`](https://docs.opencv.org/4.5.3/d6/d0f/group__dnn.html#ga29f34df9376379a603acd8df581ac8d7). Aby uzyskać sensowne dane musimy ustawić parametry dotyczące preprocessingu (informacje o tym są zawarte na [stronie modelu](https://github.com/shicai/DenseNet-Caffe)):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d4e945ae",
"metadata": {
"id": "d4e945ae"
},
"outputs": [],
"source": [
"image_blob = cv.dnn.blobFromImage(image=image, scalefactor=0.017, size=(224, 224), mean=(104, 117, 123), \n",
" swapRB=False, crop=False)"
]
},
{
"cell_type": "markdown",
"id": "625aebdd",
"metadata": {
"id": "625aebdd"
},
"source": [
"Ustawiamy dane wejściowe w naszej sieci i pobieramy obliczone wartości:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "753333a1",
"metadata": {
"id": "753333a1"
},
"outputs": [],
"source": [
"model.setInput(image_blob)\n",
"outputs = model.forward()[0]"
]
},
{
"cell_type": "markdown",
"id": "34316ddb",
"metadata": {
"id": "34316ddb"
},
"source": [
"Wyliczamy która klasa jest najbardziej prawdopodobna:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13423a6d",
"metadata": {
"id": "13423a6d"
},
"outputs": [],
"source": [
"outputs = outputs.reshape(1000, 1)\n",
"\n",
"label_id = np.argmax(outputs)\n",
"\n",
"probs = np.exp(outputs) / np.sum(np.exp(outputs))"
]
},
{
"cell_type": "markdown",
"id": "874c1b1d",
"metadata": {
"id": "874c1b1d"
},
"source": [
"Wynik:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ec75a3c5",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 298
},
"executionInfo": {
"elapsed": 599,
"status": "ok",
"timestamp": 1673872040722,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "ec75a3c5",
"outputId": "892ae88a-5d5e-4846-c7dd-b55d293649a8"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"99.99 %\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.imshow(image[:,:,::-1])\n",
"plt.title(classes[label_id])\n",
"print(\"{:.2f} %\".format(np.max(probs) * 100.0))"
]
},
{
"cell_type": "markdown",
"id": "3808c42c",
"metadata": {
"id": "3808c42c"
},
"source": [
"# Wykrywanie twarzy\n",
"\n",
"Do wykrywania twarzy użyjemy sieci bazującej na [SSD](https://github.com/weiliu89/caffe/tree/ssd):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3c0df387",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 674,
"status": "ok",
"timestamp": 1673872041392,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "3c0df387",
"outputId": "ab118eec-c022-4fa4-8388-e5b1c2d7c309"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dnn/res10_300x300_s 100%[===================>] 5.10M 28.5MB/s in 0.2s \n",
"dnn/res10_300x300_s 100%[===================>] 27.45K --.-KB/s in 0.005s \n"
]
}
],
"source": [
"!wget -q --show-progress -O dnn/res10_300x300_ssd_iter_140000_fp16.caffemodel https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel\n",
"!wget -q --show-progress -O dnn/res10_300x300_ssd_iter_140000_fp16.prototxt https://raw.githubusercontent.com/opencv/opencv/master/samples/dnn/face_detector/deploy.prototxt"
]
},
{
"cell_type": "markdown",
"id": "c6142f6e",
"metadata": {
"id": "c6142f6e"
},
"source": [
"Ładujemy model:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "60d41efb",
"metadata": {
"id": "60d41efb"
},
"outputs": [],
"source": [
"model = cv.dnn.readNet(model='dnn/res10_300x300_ssd_iter_140000_fp16.prototxt', config='dnn/res10_300x300_ssd_iter_140000_fp16.caffemodel', framework='Caffe')"
]
},
{
"cell_type": "markdown",
"id": "ad612cc6",
"metadata": {
"id": "ad612cc6"
},
"source": [
"Będziemy chcieli wykryć twarze na poniższym obrazie:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b404d8c4",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 312
},
"executionInfo": {
"elapsed": 3065,
"status": "ok",
"timestamp": 1673872044455,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "b404d8c4",
"outputId": "b930b343-d669-43b3-bc3e-abbfbb80192a"
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 504x504 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"image = cv.imread('img/people.jpg')\n",
"plt.figure(figsize=[7,7])\n",
"plt.imshow(image[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "a77f8e64",
"metadata": {
"id": "a77f8e64"
},
"source": [
"Znajdujemy twarze i oznaczamy je na zdjęciu (za próg przyjęliśmy 0.5; zob. informacje o [preprocessingu](https://github.com/opencv/opencv/tree/master/samples/dnn#face-detection)):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1d16f230",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 498
},
"executionInfo": {
"elapsed": 2910,
"status": "ok",
"timestamp": 1673872047360,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "1d16f230",
"outputId": "a8d7bce6-dc61-4d51-d4b9-6bf66ef4fa2e"
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 864x864 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"height, width, _ = image.shape\n",
"\n",
"image_blob = cv.dnn.blobFromImage(image, scalefactor=1.0, size=(300, 300), mean=[104, 177, 123], \n",
" swapRB=False, crop=False)\n",
"\n",
"model.setInput(image_blob)\n",
"\n",
"detections = model.forward()\n",
"\n",
"image_out = image.copy()\n",
"\n",
"for i in range(detections.shape[2]):\n",
" confidence = detections[0, 0, i, 2]\n",
" if confidence > 0.5:\n",
"\n",
" box = detections[0, 0, i, 3:7] * np.array([width, height, width, height])\n",
" (x1, y1, x2, y2) = box.astype('int')\n",
"\n",
" cv.rectangle(image_out, (x1, y1), (x2, y2), (0, 255, 0), 6)\n",
" label = '{:.3f}'.format(confidence)\n",
" label_size, base_line = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 3.0, 1)\n",
" cv.rectangle(image_out, (x1, y1 - label_size[1]), (x1 + label_size[0], y1 + base_line), \n",
" (255, 255, 255), cv.FILLED)\n",
" cv.putText(image_out, label, (x1, y1), cv.FONT_HERSHEY_SIMPLEX, 3.0, (0, 0, 0))\n",
" \n",
"plt.figure(figsize=[12,12])\n",
"plt.imshow(image_out[:,:,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "590841cd",
"metadata": {
"id": "590841cd"
},
"source": [
"## Punkty charakterystyczne twarzy\n",
"\n",
"W OpenCV jest możliwość wykrywania punktów charakterystycznych twarzy (ang. *facial landmarks*). Użyjemy zaimplementowanego [modelu](http://www.jiansun.org/papers/CVPR14_FaceAlignment.pdf) podczas Google Summer of Code przy użyciu [`createFacemarkLBF()`](https://docs.opencv.org/4.5.3/d4/d48/namespacecv_1_1face.html#a0bec73a729ed878430c2feb9ce65bc2a):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8534a399",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 1195,
"status": "ok",
"timestamp": 1673872048533,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "8534a399",
"outputId": "7aba2198-7b31-4cca-dc05-14989e3f002e"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dnn/lbfmodel.yaml 100%[===================>] 53.76M 54.9MB/s in 1.0s \n"
]
}
],
"source": [
"!wget -q --show-progress -O dnn/lbfmodel.yaml https://raw.githubusercontent.com/kurnianggoro/GSOC2017/master/data/lbfmodel.yaml"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c2971f10",
"metadata": {
"id": "c2971f10"
},
"outputs": [],
"source": [
"landmark_detector = cv.face.createFacemarkLBF()\n",
"landmark_detector.loadModel('dnn/lbfmodel.yaml')"
]
},
{
"cell_type": "markdown",
"id": "761dbc15",
"metadata": {
"id": "761dbc15"
},
"source": [
"Ograniczamy nasze poszukiwania do twarzy:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "39215601",
"metadata": {
"id": "39215601"
},
"outputs": [],
"source": [
"faces = []\n",
"\n",
"for detection in detections[0][0]:\n",
" if detection[2] >= 0.5:\n",
" left = detection[3] * width\n",
" top = detection[4] * height\n",
" right = detection[5] * width\n",
" bottom = detection[6] * height\n",
"\n",
" face_w = right - left\n",
" face_h = bottom - top\n",
"\n",
" face_roi = (left, top, face_w, face_h)\n",
" faces.append(face_roi)\n",
"\n",
"faces = np.array(faces).astype(int)\n",
"\n",
"_, landmarks_list = landmark_detector.fit(image, faces)"
]
},
{
"cell_type": "markdown",
"id": "56aa90c9",
"metadata": {
"id": "56aa90c9"
},
"source": [
"Model generuje 68 punktów charakterycznych, które możemy zwizualizować:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6d3ab726",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 528
},
"executionInfo": {
"elapsed": 976,
"status": "ok",
"timestamp": 1673872050591,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "6d3ab726",
"outputId": "c623f431-9475-4887-c055-af5e27db2f43"
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"image_display = image.copy()\n",
"landmarks = landmarks_list[0][0].astype(int)\n",
"\n",
"for idx, landmark in enumerate(landmarks):\n",
" cv.circle(image_display, landmark, 2, (0,255,255), -1)\n",
" cv.putText(image_display, str(idx), landmark, cv.FONT_HERSHEY_SIMPLEX, 0.35, (0, 255, 0), 1, \n",
" cv.LINE_AA)\n",
"\n",
"plt.figure(figsize=(10,10))\n",
"plt.imshow(image_display[700:1050,500:910,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "7cee8969",
"metadata": {
"id": "7cee8969"
},
"source": [
"Jeśli nie potrzebujemy numeracji, to możemy użyć prostszego podejścia, tj. funkcji [`drawFacemarks()`](https://docs.opencv.org/4.5.3/db/d7c/group__face.html#ga318d9669d5ed4dfc6ab9fae2715310f5):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1039e253",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 328
},
"executionInfo": {
"elapsed": 966,
"status": "ok",
"timestamp": 1673872051549,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "1039e253",
"outputId": "f8be80e7-d4c0-4a3f-9039-d9775f8ec577"
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 720x720 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"image_display = image.copy()\n",
"for landmarks_set in landmarks_list:\n",
" cv.face.drawFacemarks(image_display, landmarks_set, (0, 255, 0))\n",
"\n",
"plt.figure(figsize=(10,10))\n",
"plt.imshow(image_display[500:1050,500:1610,::-1]);"
]
},
{
"cell_type": "markdown",
"id": "db16a1bf",
"metadata": {
"id": "db16a1bf"
},
"source": [
"# Zadanie 1\n",
"\n",
"W katalogu `vid` znajdują się filmy `blinking-*.mp4`. Napisz program do wykrywania mrugnięć. Opcjonalnie możesz użyć *eye aspect ratio* z [tego artykułu](http://vision.fe.uni-lj.si/cvww2016/proceedings/papers/05.pdf) lub zaproponować własne rozwiązanie."
]
},
{
"cell_type": "markdown",
"id": "xm1aHfWnrEye",
"metadata": {
"id": "xm1aHfWnrEye"
},
"source": [
"Na podstawie [link do tutorialu](https://pyimagesearch.com/2017/04/24/eye-blink-detection-opencv-python-dlib/)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "57d5ec8f",
"metadata": {
"id": "57d5ec8f"
},
"outputs": [],
"source": [
"from scipy.spatial import distance as dist\n",
"from imutils.video import FileVideoStream\n",
"from imutils.video import VideoStream\n",
"from imutils import face_utils\n",
"import numpy as np\n",
"import argparse\n",
"import imutils\n",
"import time\n",
"import dlib\n",
"import cv2"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3ea13684",
"metadata": {
"id": "3ea13684"
},
"outputs": [],
"source": [
"def eye_aspect_ratio(eye):\n",
"\tA = dist.euclidean(eye[1], eye[5])\n",
"\tB = dist.euclidean(eye[2], eye[4])\n",
"\tC = dist.euclidean(eye[0], eye[3])\n",
"\n",
"\tear = (A + B) / (2.0 * C)\n",
"\n",
"\treturn ear"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "I6VGyOghkh9t",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 1551,
"status": "ok",
"timestamp": 1673872566723,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "I6VGyOghkh9t",
"outputId": "8fdbc09d-019f-4ddd-cd5d-97b328645377"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dnn/shape_predictor 100%[===================>] 95.08M 62.0MB/s in 1.5s \n"
]
}
],
"source": [
"!wget -q --show-progress -O dnn/shape_predictor_68_face_landmarks.dat https://raw.githubusercontent.com/italojs/facial-landmarks-recognition/master/shape_predictor_68_face_landmarks.dat"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9b11261e",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 1147,
"status": "ok",
"timestamp": 1673872952727,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "9b11261e",
"outputId": "23f5dc53-28bb-4715-bee3-5082178a1745"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(42, 48)\n",
"(36, 42)\n"
]
}
],
"source": [
"EYE_AR_THRESH = 0.3\n",
"EYE_AR_CONSEC_FRAMES = 6\n",
"\n",
"COUNTER = 0\n",
"TOTAL = 0\n",
"\n",
"detector = dlib.get_frontal_face_detector()\n",
"predictor = dlib.shape_predictor(\"dnn/shape_predictor_68_face_landmarks.dat\")\n",
"\n",
"(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS[\"left_eye\"]\n",
"(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS[\"right_eye\"]\n",
"print(face_utils.FACIAL_LANDMARKS_IDXS[\"left_eye\"])\n",
"print(face_utils.FACIAL_LANDMARKS_IDXS[\"right_eye\"])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "W22AEG6plpnD",
"metadata": {
"id": "W22AEG6plpnD"
},
"outputs": [],
"source": [
"cap = cv2.VideoCapture(\"vid/blinking-woman1.mp4\")\n",
"n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
"width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) \n",
"height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n",
"fps = cap.get(cv2.CAP_PROP_FPS)\n",
"\n",
"out = cv2.VideoWriter('vid/blinking_woman1_detection.avi', cv2.VideoWriter_fourcc(*'MJPG'), fps, (width, height))\n",
"cap = cv2.VideoCapture(\"vid/blinking-woman2.mp4\")\n",
"n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
"width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) \n",
"height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n",
"fps = cap.get(cv2.CAP_PROP_FPS)\n",
"\n",
"out = cv2.VideoWriter('vid/blinking_woman2_detection.avi', cv2.VideoWriter_fourcc(*'MJPG'), fps, (width, height))\n",
"for _ in range(n_frames-2):\n",
" ok, frame = cap.read()\n",
" if not ok:\n",
" break\n",
" gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n",
"\n",
" rects = detector(gray, 0)\n",
" for rect in rects:\n",
" shape = predictor(gray, rect)\n",
" shape = face_utils.shape_to_np(shape)\n",
" leftEye = shape[lStart:lEnd]\n",
" rightEye = shape[rStart:rEnd]\n",
"\n",
" leftEAR = eye_aspect_ratio(leftEye)\n",
" rightEAR = eye_aspect_ratio(rightEye)\n",
"\n",
" ear = (leftEAR + rightEAR) / 2.0\n",
" leftEyeHull = cv2.convexHull(leftEye)\n",
" rightEyeHull = cv2.convexHull(rightEye)\n",
" \n",
" cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)\n",
" cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1)\n",
"\n",
" if ear < EYE_AR_THRESH:\n",
" COUNTER += 1\n",
" else:\n",
" if COUNTER >= EYE_AR_CONSEC_FRAMES:\n",
" TOTAL += 1\n",
" \n",
" COUNTER = 0\n",
"\n",
" cv2.putText(frame, \"Blinks: {}\".format(TOTAL), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)\n",
" cv2.putText(frame, \"EAR: {:.2f}\".format(ear), (300, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)\n",
"\n",
" out.write(frame)\n",
"\n",
"out.release()\n",
"cap.release()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8476713b",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"executionInfo": {
"elapsed": 261,
"status": "ok",
"timestamp": 1673872725033,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "8476713b",
"outputId": "ce4cee77-814d-44ec-880b-a1cddffe5c0f"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[0;35m[avi @ 0x5639ad76e000] \u001b[0m\u001b[0;33mFormat avi detected only with low score of 1, misdetection possible!\n",
"\u001b[0m\u001b[1;31mvid/blinking_woman1_detection.avi: Invalid data found when processing input\n",
"\u001b[0m"
]
}
],
"source": [
"!ffmpeg -y -hide_banner -loglevel warning -nostats -i vid/blinking_woman1_detection.avi -vcodec libx264 vid/blinking_woman1_detection.mp4"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b3b169e6",
"metadata": {
"id": "b3b169e6"
},
"outputs": [],
"source": [
"!ffmpeg -y -hide_banner -loglevel warning -nostats -i vid/blinking_woman2_detection.avi -vcodec libx264 vid/blinking_woman2_detection.mp4"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "adf3bb76",
"metadata": {
"id": "adf3bb76"
},
"outputs": [],
"source": [
"import IPython.display"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1032d7d6",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 305
},
"executionInfo": {
"elapsed": 272,
"status": "error",
"timestamp": 1673872734432,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "1032d7d6",
"outputId": "dce328f0-5e7e-4e66-c26a-7df8f7d63be0"
},
"outputs": [
{
"ename": "ValueError",
"evalue": "ignored",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-42-c1428997a36b>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mIPython\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisplay\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mVideo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"vid/blinking_woman1_detection.mp4\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwidth\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m800\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m/usr/local/lib/python3.8/dist-packages/IPython/core/display.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, data, url, filename, embed, mimetype, width, height)\u001b[0m\n\u001b[1;32m 1372\u001b[0m \u001b[0;34m\"Consider passing Video(url='...')\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1373\u001b[0m ])\n\u001b[0;32m-> 1374\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1375\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1376\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmimetype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmimetype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: To embed videos, you must pass embed=True (this may make your notebook files huge)\nConsider passing Video(url='...')"
]
}
],
"source": [
"IPython.display.Video(\"vid/blinking_woman1_detection.mp4\", width=800)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "49d59535",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 421
},
"executionInfo": {
"elapsed": 10,
"status": "ok",
"timestamp": 1673872737034,
"user": {
"displayName": "Cezary Gałązkiewicz",
"userId": "01409497901784152256"
},
"user_tz": -60
},
"id": "49d59535",
"outputId": "67e99800-235c-4aea-9421-e3340eac2222"
},
"outputs": [
{
"data": {
"text/html": [
"<video src=\"vid/blinking_woman2_detection.mp4\" controls width=\"800\" >\n",
" Your browser does not support the <code>video</code> element.\n",
" </video>"
],
"text/plain": [
"<IPython.core.display.Video object>"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"IPython.display.Video(\"vid/blinking_woman2_detection.mp4\", width=800)"
]
}
],
"metadata": {
"author": "Andrzej Wójtowicz",
"colab": {
"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.9.2"
},
"subtitle": "09. Wykrywanie i rozpoznawanie tekstu [laboratoria]",
"title": "Widzenie komputerowe",
"vscode": {
"interpreter": {
"hash": "9140c0930ad6b6c35ab9dcb3930a3fc3a0ddbb5eeb7900bcf692f72b8c01d4e3"
}
},
"year": "2021"
},
"nbformat": 4,
"nbformat_minor": 5
}