2022-07-25 08:52:20 +08:00
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "YOLOv7ONNXandTRT.ipynb",
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU",
"gpuClass": "standard"
},
"cells": [
{
"cell_type": "code",
"source": [
"!pip install --upgrade setuptools pip --user\n",
"!pip install onnx \n",
"!pip install onnxruntime\n",
"#!pip install --ignore-installed PyYAML\n",
"#!pip install Pillow\n",
"\n",
"!pip install protobuf<4.21.3\n",
"!pip install onnxruntime-gpu\n",
"!pip install onnx>=1.9.0\n",
"!pip install onnx-simplifier>=0.3.6 --user"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
},
"id": "sSDOngglBk_O",
"outputId": "1ab904a0-b9d0-46cd-ba26-297be83a3e0c"
},
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (57.4.0)\n",
"Collecting setuptools\n",
" Downloading setuptools-63.2.0-py3-none-any.whl (1.2 MB)\n",
"\u001b[K |████████████████████████████████| 1.2 MB 28.1 MB/s \n",
"\u001b[?25hRequirement already satisfied: pip in /usr/local/lib/python3.7/dist-packages (21.1.3)\n",
"Collecting pip\n",
" Downloading pip-22.2-py3-none-any.whl (2.0 MB)\n",
"\u001b[K |████████████████████████████████| 2.0 MB 55.5 MB/s \n",
"\u001b[?25hInstalling collected packages: setuptools, pip\n",
"\u001b[33m WARNING: The scripts pip, pip3 and pip3.7 are installed in '/root/.local/bin' which is not on PATH.\n",
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\n",
"\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
"datascience 0.10.6 requires folium==0.2.1, but you have folium 0.8.3 which is incompatible.\u001b[0m\n",
"Successfully installed pip-22.2 setuptools-63.2.0\n"
]
},
{
"output_type": "display_data",
"data": {
"application/vnd.colab-display-data+json": {
"pip_warning": {
"packages": [
"pkg_resources"
]
}
}
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Collecting onnx\n",
" Downloading onnx-1.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (13.1 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m13.1/13.1 MB\u001b[0m \u001b[31m82.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hRequirement already satisfied: typing-extensions>=3.6.2.1 in /usr/local/lib/python3.7/dist-packages (from onnx) (4.1.1)\n",
"Requirement already satisfied: numpy>=1.16.6 in /usr/local/lib/python3.7/dist-packages (from onnx) (1.21.6)\n",
"Requirement already satisfied: protobuf<=3.20.1,>=3.12.2 in /usr/local/lib/python3.7/dist-packages (from onnx) (3.17.3)\n",
"Requirement already satisfied: six>=1.9 in /usr/local/lib/python3.7/dist-packages (from protobuf<=3.20.1,>=3.12.2->onnx) (1.15.0)\n",
"Installing collected packages: onnx\n",
"Successfully installed onnx-1.12.0\n",
"\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
"\u001b[0mLooking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Collecting onnxruntime\n",
" Downloading onnxruntime-1.12.0-cp37-cp37m-manylinux_2_27_x86_64.whl (4.9 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.9/4.9 MB\u001b[0m \u001b[31m81.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hCollecting coloredlogs\n",
" Downloading coloredlogs-15.0.1-py2.py3-none-any.whl (46 kB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m1.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hRequirement already satisfied: numpy>=1.21.0 in /usr/local/lib/python3.7/dist-packages (from onnxruntime) (1.21.6)\n",
"Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from onnxruntime) (1.7.1)\n",
"Requirement already satisfied: protobuf in /usr/local/lib/python3.7/dist-packages (from onnxruntime) (3.17.3)\n",
"Requirement already satisfied: flatbuffers in /usr/local/lib/python3.7/dist-packages (from onnxruntime) (2.0)\n",
"Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from onnxruntime) (21.3)\n",
"Collecting humanfriendly>=9.1\n",
" Downloading humanfriendly-10.0-py2.py3-none-any.whl (86 kB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m10.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hRequirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->onnxruntime) (3.0.9)\n",
"Requirement already satisfied: six>=1.9 in /usr/local/lib/python3.7/dist-packages (from protobuf->onnxruntime) (1.15.0)\n",
"Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->onnxruntime) (1.2.1)\n",
"Installing collected packages: humanfriendly, coloredlogs, onnxruntime\n",
"Successfully installed coloredlogs-15.0.1 humanfriendly-10.0 onnxruntime-1.12.0\n",
"\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
"\u001b[0m/bin/bash: 4.21.3: No such file or directory\n",
"Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
"Collecting onnxruntime-gpu\n",
" Downloading onnxruntime_gpu-1.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (111.0 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m111.0/111.0 MB\u001b[0m \u001b[31m9.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hRequirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (21.3)\n",
"Requirement already satisfied: protobuf in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (3.17.3)\n",
"Requirement already satisfied: coloredlogs in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (15.0.1)\n",
"Requirement already satisfied: flatbuffers in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (2.0)\n",
"Requirement already satisfied: sympy in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (1.7.1)\n",
"Requirement already satisfied: numpy>=1.21.0 in /usr/local/lib/python3.7/dist-packages (from onnxruntime-gpu) (1.21.6)\n",
"Requirement already satisfied: humanfriendly>=9.1 in /usr/local/lib/python3.7/dist-packages (from coloredlogs->onnxruntime-gpu) (10.0)\n",
"Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->onnxruntime-gpu) (3.0.9)\n",
"Requirement already satisfied: six>=1.9 in /usr/local/lib/python3.7/dist-packages (from protobuf->onnxruntime-gpu) (1.15.0)\n",
"Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.7/dist-packages (from sympy->onnxruntime-gpu) (1.2.1)\n",
"Installing collected packages: onnxruntime-gpu\n",
"Successfully installed onnxruntime-gpu-1.12.0\n",
"\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33m WARNING: The script cmark is installed in '/root/.local/bin' which is not on PATH.\n",
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33m WARNING: The script onnxsim is installed in '/root/.local/bin' which is not on PATH.\n",
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
"\u001b[0m\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
"\u001b[0m"
]
}
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hQ5fNost-gZI",
"outputId": "396d7243-b6af-4acf-e555-38a984cd69bb"
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Python version: 3.7.13 (default, Apr 24 2022, 01:04:09) \n",
"[GCC 7.5.0], sys.version_info(major=3, minor=7, micro=13, releaselevel='final', serial=0) \n",
"Pytorch version: 1.12.0+cu113 \n"
]
}
],
"source": [
"import sys\n",
"import torch\n",
"print(f\"Python version: {sys.version}, {sys.version_info} \")\n",
"print(f\"Pytorch version: {torch.__version__} \")"
]
},
{
"cell_type": "code",
"source": [
"!nvidia-smi"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "feCaRUEI-_Os",
"outputId": "7a488cf8-f7d7-4366-ce12-442329a9266b"
},
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Mon Jul 25 00:25:03 2022 \n",
"+-----------------------------------------------------------------------------+\n",
"| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |\n",
"|-------------------------------+----------------------+----------------------+\n",
"| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
"| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |\n",
"| | | MIG M. |\n",
"|===============================+======================+======================|\n",
"| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |\n",
"| N/A 38C P8 9W / 70W | 3MiB / 15109MiB | 0% Default |\n",
"| | | N/A |\n",
"+-------------------------------+----------------------+----------------------+\n",
" \n",
"+-----------------------------------------------------------------------------+\n",
"| Processes: |\n",
"| GPU GI CI PID Type Process name GPU Memory |\n",
"| ID ID Usage |\n",
"|=============================================================================|\n",
"| No running processes found |\n",
"+-----------------------------------------------------------------------------+\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"!# Download YOLOv7 code\n",
"!git clone https://github.com/WongKinYiu/yolov7\n",
"%cd yolov7\n",
"!ls"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "yfZALjuo-_Md",
"outputId": "ccda5b64-a800-4c4a-bcb9-c7e899280751"
},
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Cloning into 'yolov7'...\n",
"remote: Enumerating objects: 409, done.\u001b[K\n",
"remote: Counting objects: 100% (149/149), done.\u001b[K\n",
"remote: Compressing objects: 100% (67/67), done.\u001b[K\n",
"remote: Total 409 (delta 118), reused 88 (delta 82), pack-reused 260\u001b[K\n",
"Receiving objects: 100% (409/409), 17.46 MiB | 12.55 MiB/s, done.\n",
"Resolving deltas: 100% (190/190), done.\n",
"/content/yolov7\n",
"cfg\t\t\t export.py models\t\t tools\n",
"data\t\t\t figure README.md\t train_aux.py\n",
"detect.py\t\t hubconf.py requirements.txt train.py\n",
"end2end_onnxruntime.ipynb inference scripts\t\t utils\n",
"end2end_tensorrt.ipynb\t LICENSE.md test.py\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"!# Download trained weights\n",
"!wget https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "eWlHa1NJ-_Jw",
"outputId": "d32d8c3e-1d32-4ec9-bc41-d3e0f9d60497"
},
"execution_count": 5,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"--2022-07-25 00:25:06-- https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-tiny.pt\n",
"Resolving github.com (github.com)... 20.205.243.166\n",
"Connecting to github.com (github.com)|20.205.243.166|:443... connected.\n",
"HTTP request sent, awaiting response... 302 Found\n",
"Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/511187726/ba7d01ee-125a-4134-8864-fa1abcbf94d5?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220725%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220725T002506Z&X-Amz-Expires=300&X-Amz-Signature=5f81912326303a5f48f2365a8976dce81a5f5c0aab99c4fff97c50d4626a28e3&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=511187726&response-content-disposition=attachment%3B%20filename%3Dyolov7-tiny.pt&response-content-type=application%2Foctet-stream [following]\n",
"--2022-07-25 00:25:06-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/511187726/ba7d01ee-125a-4134-8864-fa1abcbf94d5?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220725%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220725T002506Z&X-Amz-Expires=300&X-Amz-Signature=5f81912326303a5f48f2365a8976dce81a5f5c0aab99c4fff97c50d4626a28e3&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=511187726&response-content-disposition=attachment%3B%20filename%3Dyolov7-tiny.pt&response-content-type=application%2Foctet-stream\n",
"Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
"Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.108.133|:443... connected.\n",
"HTTP request sent, awaiting response... 200 OK\n",
"Length: 12639769 (12M) [application/octet-stream]\n",
"Saving to: ‘ yolov7-tiny.pt’ \n",
"\n",
"yolov7-tiny.pt 100%[===================>] 12.05M 10.4MB/s in 1.2s \n",
"\n",
"2022-07-25 00:25:08 (10.4 MB/s) - ‘ yolov7-tiny.pt’ saved [12639769/12639769]\n",
"\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"!python detect.py --weights ./yolov7-tiny.pt --conf 0.25 --img-size 640 --source inference/images/horses.jpg"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UX7u8eqj-_Hi",
"outputId": "8fc1e981-e105-4c71-e964-bcb3a927ad8d"
},
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Namespace(agnostic_nms=False, augment=False, classes=None, conf_thres=0.25, device='', exist_ok=False, img_size=640, iou_thres=0.45, name='exp', no_trace=False, nosave=False, project='runs/detect', save_conf=False, save_txt=False, source='inference/images/horses.jpg', update=False, view_img=False, weights=['./yolov7-tiny.pt'])\n",
"YOLOR 🚀 v0.1-58-g13458cd torch 1.12.0+cu113 CUDA:0 (Tesla T4, 15109.75MB)\n",
"\n",
"Fusing layers... \n",
"Model Summary: 200 layers, 6219709 parameters, 229245 gradients\n",
" Convert model to Traced-model... \n",
" traced_script_module saved! \n",
" model is traced! \n",
"\n",
"/usr/local/lib/python3.7/dist-packages/torch/functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:2894.)\n",
" return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]\n",
" The image with the result is saved in: runs/detect/exp/horses.jpg\n",
"Done. (0.216s)\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"from PIL import Image\n",
"Image.open('/content/yolov7/runs/detect/exp/horses.jpg')"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 529
},
"id": "wZD-nZXX-_Ez",
"outputId": "7486afe2-bbbb-4c12-898a-7d750dd14287"
},
"execution_count": 7,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=773x512 at 0x7F0098757250>"
],
"image/png": "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
},
"metadata": {},
"execution_count": 7
}
]
},
{
"cell_type": "code",
"source": [
"# export ONNX for ONNX inference\n",
"%cd /content/yolov7/\n",
"!python export.py --weights ./yolov7-tiny.pt \\\n",
" --grid --end2end --simplify \\\n",
" --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 \\\n",
2022-07-25 09:27:28 +08:00
" --img-size 640 640 --max-wh 640 # For onnxruntime, you need to specify this value as an integer, when it is 0 it means agnostic NMS, \n",
2022-07-25 08:52:20 +08:00
" # otherwise it is non-agnostic NMS"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "VaPGM88g-_CE",
"outputId": "c0abb5d2-b0db-4f14-9eaa-8adfdca807bf"
},
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"/content/yolov7\n",
"Import onnx_graphsurgeon failure: No module named 'onnx_graphsurgeon'\n",
"Namespace(batch_size=1, conf_thres=0.35, device='cpu', dynamic=False, end2end=True, grid=True, img_size=[640, 640], include_nms=False, iou_thres=0.65, max_wh=640, simplify=True, topk_all=100, weights='./yolov7-tiny.pt')\n",
"YOLOR 🚀 v0.1-58-g13458cd torch 1.12.0+cu113 CPU\n",
"\n",
"Fusing layers... \n",
"Model Summary: 200 layers, 6219709 parameters, 6219709 gradients\n",
"/usr/local/lib/python3.7/dist-packages/torch/functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:2894.)\n",
" return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]\n",
"\n",
"Starting TorchScript export with torch 1.12.0+cu113...\n",
"/content/yolov7/models/yolo.py:51: TracerWarning: Converting a tensor to a Python boolean might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
" if self.grid[i].shape[2:4] != x[i].shape[2:4]:\n",
"TorchScript export success, saved as ./yolov7-tiny.torchscript.pt\n",
"\n",
"Starting ONNX export with onnx 1.12.0...\n",
"onnxruntime\n",
"/usr/local/lib/python3.7/dist-packages/torch/_tensor.py:1083: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at aten/src/ATen/core/TensorBody.h:477.)\n",
" return self._grad\n",
"/content/yolov7/models/experimental.py:99: TracerWarning: Converting a tensor to a Python integer might cause the trace to be incorrect. We can't record the data flow of Python values, so this value will be treated as a constant in the future. This means that the trace might not generalize to other inputs!\n",
" batches = torch.randint(0, batch, (num_det,)).sort()[0].to(device)\n",
"/usr/local/lib/python3.7/dist-packages/torch/onnx/symbolic_opset9.py:4187: UserWarning: Exporting aten::index operator of advanced indexing in opset 12 is achieved by combination of multiple ONNX operators, including Reshape, Transpose, Concat, and Gather. If indices include negative values, the exported graph will produce incorrect results.\n",
" + \"If indices include negative values, the exported graph will produce incorrect results.\"\n",
"\n",
"Starting to simplify ONNX...\n",
"ONNX export success, saved as ./yolov7-tiny.onnx\n",
"CoreML export failure: No module named 'coremltools'\n",
"\n",
"Export complete (6.95s). Visualize with https://github.com/lutzroeder/netron.\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# show ONNX model\n",
"!ls"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "h9lzPkMxu7B8",
"outputId": "4aeff7ba-ff05-43f0-f725-868ec5b194ba"
},
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"cfg\t\t\t inference\t tools\n",
"data\t\t\t LICENSE.md\t traced_model.pt\n",
"detect.py\t\t models\t train_aux.py\n",
"end2end_onnxruntime.ipynb README.md\t train.py\n",
"end2end_tensorrt.ipynb\t requirements.txt utils\n",
"export.py\t\t runs\t\t yolov7-tiny.onnx\n",
"figure\t\t\t scripts\t yolov7-tiny.pt\n",
"hubconf.py\t\t test.py\t yolov7-tiny.torchscript.pt\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"# Inference for ONNX model\n",
"import cv2\n",
"cuda = True\n",
"w = \"/content/yolov7/yolov7-tiny.onnx\"\n",
"img = cv2.imread('/content/yolov7/inference/images/horses.jpg')"
],
"metadata": {
"id": "Ifw8pYU11Ske"
},
"execution_count": 10,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import cv2\n",
"import time\n",
"import requests\n",
"import random\n",
"import numpy as np\n",
"import onnxruntime as ort\n",
"from PIL import Image\n",
"from pathlib import Path\n",
"from collections import OrderedDict,namedtuple\n",
"\n",
"providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if cuda else ['CPUExecutionProvider']\n",
"session = ort.InferenceSession(w, providers=providers)\n",
"\n",
"\n",
"def letterbox(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):\n",
" # Resize and pad image while meeting stride-multiple constraints\n",
" shape = im.shape[:2] # current shape [height, width]\n",
" if isinstance(new_shape, int):\n",
" new_shape = (new_shape, new_shape)\n",
"\n",
" # Scale ratio (new / old)\n",
" r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])\n",
" if not scaleup: # only scale down, do not scale up (for better val mAP)\n",
" r = min(r, 1.0)\n",
"\n",
" # Compute padding\n",
" new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))\n",
" dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding\n",
"\n",
" if auto: # minimum rectangle\n",
" dw, dh = np.mod(dw, stride), np.mod(dh, stride) # wh padding\n",
"\n",
" dw /= 2 # divide padding into 2 sides\n",
" dh /= 2\n",
"\n",
" if shape[::-1] != new_unpad: # resize\n",
" im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)\n",
" top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))\n",
" left, right = int(round(dw - 0.1)), int(round(dw + 0.1))\n",
" im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) # add border\n",
" return im, r, (dw, dh)\n",
"\n",
"names = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', \n",
" 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', \n",
" 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', \n",
" 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', \n",
" 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', \n",
" 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', \n",
" 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', \n",
" 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', \n",
" 'hair drier', 'toothbrush']\n",
"colors = {name:[random.randint(0, 255) for _ in range(3)] for i,name in enumerate(names)}\n",
"\n",
"img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n",
"\n",
"image = img.copy()\n",
"image, ratio, dwdh = letterbox(image, auto=False)\n",
"image = image.transpose((2, 0, 1))\n",
"image = np.expand_dims(image, 0)\n",
"image = np.ascontiguousarray(image)\n",
"\n",
"im = image.astype(np.float32)\n",
"im /= 255\n",
"im.shape\n",
"\n",
"outname = [i.name for i in session.get_outputs()]\n",
"outname\n",
"\n",
"inname = [i.name for i in session.get_inputs()]\n",
"inname\n",
"\n",
"inp = {inname[0]:im}"
],
"metadata": {
"id": "ipHqto0J0kkq"
},
"execution_count": 11,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# ONNX inference\n",
"outputs = session.run(outname, inp)[0]\n",
"outputs"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "07vh3pUa1ccC",
"outputId": "10e8169b-611d-4fd5-d3a7-aa1e7992f077"
},
"execution_count": 12,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"array([[ 0.0000000e+00, 3.6190897e+02, 2.8389810e+02, 4.9353049e+02,\n",
" 3.9562729e+02, 1.7000000e+01, 9.2383695e-01],\n",
" [ 0.0000000e+00, -1.0339355e+00, 2.6461755e+02, 2.6221347e+02,\n",
" 4.4826135e+02, 1.7000000e+01, 9.2106491e-01],\n",
" [ 0.0000000e+00, 2.1546237e+02, 2.7049042e+02, 3.5089426e+02,\n",
" 4.1111603e+02, 1.7000000e+01, 7.6384634e-01],\n",
" [ 0.0000000e+00, -9.6609497e-01, 2.6136026e+02, 1.2928018e+02,\n",
" 3.3445981e+02, 1.7000000e+01, 6.9170278e-01],\n",
" [ 0.0000000e+00, 3.0596021e+02, 2.8081891e+02, 3.7848901e+02,\n",
" 3.7234491e+02, 1.7000000e+01, 4.6638101e-01]], dtype=float32)"
]
},
"metadata": {},
"execution_count": 12
}
]
},
{
"cell_type": "code",
"source": [
"ori_images = [img.copy()]\n",
"\n",
"for i,(batch_id,x0,y0,x1,y1,cls_id,score) in enumerate(outputs):\n",
" image = ori_images[int(batch_id)]\n",
" box = np.array([x0,y0,x1,y1])\n",
" box -= np.array(dwdh*2)\n",
" box /= ratio\n",
" box = box.round().astype(np.int32).tolist()\n",
" cls_id = int(cls_id)\n",
" score = round(float(score),3)\n",
" name = names[cls_id]\n",
" color = colors[name]\n",
" name += ' '+str(score)\n",
" cv2.rectangle(image,box[:2],box[2:],color,2)\n",
" cv2.putText(image,name,(box[0], box[1] - 2),cv2.FONT_HERSHEY_SIMPLEX,0.75,[225, 255, 255],thickness=2) \n",
"\n",
"Image.fromarray(ori_images[0])"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 529
},
"id": "CIRXv-gT1gQv",
"outputId": "f1669666-a246-4fb9-9570-8a688b515490"
},
"execution_count": 13,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"<PIL.Image.Image image mode=RGB size=773x512 at 0x7F00026318D0>"
],
"image/png": "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
},
"metadata": {},
"execution_count": 13
}
]
}
]
}