Skip to content

Instantly share code, notes, and snippets.

@soumitradev
Last active January 7, 2020 18:41
Show Gist options
  • Save soumitradev/62bddefbb4b3c1ee5135a2fd83ee25dd to your computer and use it in GitHub Desktop.
Save soumitradev/62bddefbb4b3c1ee5135a2fd83ee25dd to your computer and use it in GitHub Desktop.
Benchmarks of JuliaImages compared to OpenCV and PIL (Pillow) on Python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Julia Images.jl Benchmark\n",
"Since the Julia Benchmark package [BenchmarkTools.jl](https://github.com/JuliaCI/BenchmarkTools.jl) automatically selects the number of samples, the Python benchmarks (computed using [timeit](https://github.com/python/cpython/blob/3.8/Lib/timeit.py)) are configured according to the number of samples BenchmarkTools takes.\n",
"\n",
"Our tests consist of the following benchmarks:\n",
"1. Loading images\n",
"2. Saving images\n",
"3. Resizing (Scaling) images\n",
"4. Rotating Images\n",
"5. Getting the histogram (Grayscale Histogram)\n",
"6. Equalizing the Grayscale Histogram\n",
"7. Converting image to grayscale\n",
"8. Changing colorspace to HSV\n",
"9. Applying Gaussian Blur"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"using Images, FileIO, ImageTransformations\n",
"using BenchmarkTools"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Loading Images"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 3.39 MiB\n",
" allocs estimate: 336\n",
" --------------\n",
" minimum time: 98.244 ms (0.00% GC)\n",
" median time: 106.476 ms (0.00% GC)\n",
" mean time: 114.129 ms (2.76% GC)\n",
" maximum time: 233.633 ms (42.20% GC)\n",
" --------------\n",
" samples: 44\n",
" evals/sample: 1"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"@benchmark img = load(\"images/lighthouse.png\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Saving Images"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 3.39 MiB\n",
" allocs estimate: 294\n",
" --------------\n",
" minimum time: 72.101 ms (0.00% GC)\n",
" median time: 94.444 ms (0.00% GC)\n",
" mean time: 100.002 ms (3.54% GC)\n",
" maximum time: 267.381 ms (47.54% GC)\n",
" --------------\n",
" samples: 50\n",
" evals/sample: 1"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark save(\"imagecopy.jpg\", img)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Resizing (Scaling) images"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 11.25 MiB\n",
" allocs estimate: 6\n",
" --------------\n",
" minimum time: 199.242 ms (2.10% GC)\n",
" median time: 217.271 ms (0.00% GC)\n",
" mean time: 230.759 ms (5.26% GC)\n",
" maximum time: 346.454 ms (29.23% GC)\n",
" --------------\n",
" samples: 22\n",
" evals/sample: 1"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark img_big = imresize(img, ratio=3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Rotating Images"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 1.13 MiB\n",
" allocs estimate: 5\n",
" --------------\n",
" minimum time: 17.941 ms (0.00% GC)\n",
" median time: 25.083 ms (0.00% GC)\n",
" mean time: 27.162 ms (2.81% GC)\n",
" maximum time: 103.582 ms (80.08% GC)\n",
" --------------\n",
" samples: 184\n",
" evals/sample: 1"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark img_rotated = imrotate(img, pi/2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Getting the histogram (Grayscale Histogram)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 386.06 KiB\n",
" allocs estimate: 5\n",
" --------------\n",
" minimum time: 30.496 ms (0.00% GC)\n",
" median time: 37.067 ms (0.00% GC)\n",
" mean time: 39.977 ms (3.37% GC)\n",
" maximum time: 179.244 ms (79.44% GC)\n",
" --------------\n",
" samples: 125\n",
" evals/sample: 1"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark edges, counts = imhist(img,256)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Equalizing the Grayscale Histogram"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 1.13 MiB\n",
" allocs estimate: 6\n",
" --------------\n",
" minimum time: 60.802 ms (0.00% GC)\n",
" median time: 73.083 ms (0.00% GC)\n",
" mean time: 80.208 ms (3.12% GC)\n",
" maximum time: 200.695 ms (65.34% GC)\n",
" --------------\n",
" samples: 63\n",
" evals/sample: 1"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark imgeq = histeq(img,256)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Converting image to grayscale"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 384.19 KiB\n",
" allocs estimate: 4\n",
" --------------\n",
" minimum time: 2.176 ms (0.00% GC)\n",
" median time: 3.917 ms (0.00% GC)\n",
" mean time: 3.931 ms (3.85% GC)\n",
" maximum time: 99.903 ms (95.84% GC)\n",
" --------------\n",
" samples: 1270\n",
" evals/sample: 1"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark gray = Gray.(img)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Changing colorspace to HSV"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 4.50 MiB\n",
" allocs estimate: 4\n",
" --------------\n",
" minimum time: 7.200 ms (0.00% GC)\n",
" median time: 12.941 ms (0.00% GC)\n",
" mean time: 13.802 ms (8.85% GC)\n",
" maximum time: 105.233 ms (88.81% GC)\n",
" --------------\n",
" samples: 362\n",
" evals/sample: 1"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark imghsv = HSV.(img)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. Applying Gaussian Blur"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"BenchmarkTools.Trial: \n",
" memory estimate: 18.44 MiB\n",
" allocs estimate: 1301\n",
" --------------\n",
" minimum time: 45.655 ms (7.25% GC)\n",
" median time: 60.413 ms (6.41% GC)\n",
" mean time: 67.063 ms (10.96% GC)\n",
" maximum time: 248.881 ms (67.55% GC)\n",
" --------------\n",
" samples: 75\n",
" evals/sample: 1"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"img = load(\"images/lighthouse.png\")\n",
"@benchmark gauss = imfilter(img, Kernel.gaussian(3))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Summary:\n",
"\n",
"Since `Images.jl` gives us the mean time while `timeit` gives us the total time of the benchmark, we have taken the mean time in `timeit` so that the benchmarks are comparable.\n",
"\n",
"### Table for comparison\n",
"\n",
"Here is the table of the Benchmarks:\n",
"\n",
"| Testcase/Framework | Images.jl | Pillow (PIL) | OpenCV |\n",
"|----------------------------------|------------|--------------|-----------|\n",
"| Loading images | 114.129 ms | 3.758 ms | 17.943 ms |\n",
"| Saving images | 100.002 ms | 309.918 ms | 37.732 ms |\n",
"| Resizing (Scaling) images | 230.759 ms | 19.11 ms | 5.656 ms |\n",
"| Rotating images | 27.162 ms | 3.649 ms | 2.88 ms |\n",
"| Calculating Greyscale Histogram | 39.977 ms | 2.143 ms | 0.418 ms |\n",
"| Greyscale Histogram equalization | 80.208 ms | 5.322 ms | 0.008 ms |\n",
"| Converting to Greyscale | 3.931 ms | 0.831 ms | 0.212 ms |\n",
"| Changing colorspace to HSV | 13.802 ms | 26.352 ms | 1.277 ms |\n",
"| Applying Gaussian Blur | 67.063 ms | 33.943 ms | 1.626 ms |\n",
"\n",
"We find that Pillow (PIL) consistently gives sub great timings for the operations with the one outlier of saving images, while OpenCV varies wildly and takes comparatively (to itself) more time for some basic tasks related to inputting and outputting files.\n",
"\n",
"Comparing Images.jl to the other 2 frameworks, Images.jl is never the fastest, which is a point where significant improvement can be made. However, Images.jl compares well with the two other frameworks when the operation includes changing the colorspace and saving images. Another point of concern is the fact that Images.jl is the slowest of the 3 frameworks in 7/9 of the tests. This might be due to OpenCV's powerful C and C++ bindings, or because of the powerful and fast `numpy` backend that Python has.\n",
"\n",
"Maybe the algorithms for Images.jl are not the most efficient? Maybe these algorithms need updating?"
]
}
],
"metadata": {
"kernel_info": {
"name": "julia-1.2"
},
"kernelspec": {
"display_name": "Julia 1.2.0",
"language": "julia",
"name": "julia-1.2"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.2.0"
},
"nteract": {
"version": "0.15.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
MIT License
Copyright (c) 2019 - 2020 Soumitra Shewale (soumitradev)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment