Skip to content

Instantly share code, notes, and snippets.

@KelSolaar
Last active August 29, 2015 14:07
Show Gist options
  • Save KelSolaar/ef72e6c63484647cfeb4 to your computer and use it in GitHub Desktop.
Save KelSolaar/ef72e6c63484647cfeb4 to your computer and use it in GitHub Desktop.
About Python, Cython & Numpy
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:8aaf7fb2464f561d187d3c08ac473005dba0308e7045120c7e85acacebaf3162"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Data"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from __future__ import division, unicode_literals\n",
"\n",
"import numpy as np\n",
"\n",
"DATA_HD = np.random.rand(1920 * 1080, 3)\n",
"DATA_PAL = np.random.rand(640 * 480, 3)\n",
"\n",
"DATA = DATA_PAL"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 1
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Python"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from colour import XYZ_to_Lab\n",
"\n",
"def XYZ_to_Lab_2d(data):\n",
" for triplet in data:\n",
" XYZ_to_Lab(triplet)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit -n 1 XYZ_to_Lab_2d(DATA)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 loops, best of 3: 6.32 s per loop\n"
]
}
],
"prompt_number": 3
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Cython"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%load_ext cythonmagic"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%cython\n",
"\n",
"import numpy as np\n",
"\n",
"cimport cython\n",
"cimport numpy as np\n",
"\n",
"from colour import CIE_E, CIE_K, ILLUMINANTS\n",
"\n",
"\n",
"def xyY_to_XYZ_cython(xyY):\n",
" cdef double x = xyY[0]\n",
" cdef double y = xyY[1]\n",
" cdef double Y = xyY[2]\n",
"\n",
" if y == 0:\n",
" return np.array([0, 0, 0])\n",
" else:\n",
" return np.array([x * Y / y, Y, (1 - x - y) * Y / y])\n",
"\n",
"\n",
"def xy_to_XYZ_cython(xy):\n",
" return xyY_to_XYZ_cython(np.array([xy[0], xy[1], 1]))\n",
"\n",
"\n",
"def XYZ_to_Lab_cython(XYZ,\n",
" illuminant=ILLUMINANTS.get(\n",
" 'CIE 1931 2 Degree Standard Observer').get('D50')):\n",
"\n",
" cdef double X = XYZ[0]\n",
" cdef double Y = XYZ[1]\n",
" cdef double Z = XYZ[2]\n",
"\n",
" cdef np.ndarray XYZ_r = xy_to_XYZ_cython(illuminant)\n",
" \n",
" cdef double Xr = XYZ_r[0]\n",
" cdef double Yr = XYZ_r[1]\n",
" cdef double Zr = XYZ_r[2]\n",
" \n",
" cdef double xr = X / Xr\n",
" cdef double yr = Y / Yr\n",
" cdef double zr = Z / Zr\n",
"\n",
" cdef double fx = xr ** (1 / 3) if xr > CIE_E else (CIE_K * xr + 16) / 116\n",
" cdef double fy = yr ** (1 / 3) if yr > CIE_E else (CIE_K * yr + 16) / 116\n",
" cdef double fz = zr ** (1 / 3) if zr > CIE_E else (CIE_K * zr + 16) / 116\n",
"\n",
" cdef double L = 116 * fy - 16\n",
" cdef double a = 500 * (fx - fy)\n",
" cdef double b = 200 * (fy - fz)\n",
"\n",
" return np.array([L, a, b])\n",
"\n",
"def XYZ_to_Lab_2d_cython(data):\n",
" for i in range(len(data)):\n",
" XYZ_to_Lab_cython(data[i])"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit XYZ_to_Lab_2d_cython(DATA)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 loops, best of 3: 1.46 s per loop\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Vectorised Numpy"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from colour import CIE_E, CIE_K, ILLUMINANTS\n",
"from colour import xyY_to_XYZ\n",
"\n",
"\n",
"def xyY_to_XYZ_numpy(xyY):\n",
" xyY = np.asarray(xyY).reshape(-1, 3)\n",
"\n",
" x, y, Y = xyY[:, 0], xyY[:, 1], xyY[:, 2]\n",
"\n",
" X = x * Y / y\n",
" Z = (1 - x - y) * Y / y\n",
" \n",
" XYZ = np.squeeze(np.dstack((X, Y, Z)))\n",
"\n",
" XYZ[np.where(XYZ[:1] == 0)] = 0\n",
"\n",
" return XYZ\n",
"\n",
"\n",
"def xy_to_XYZ_numpy(xy):\n",
" xy = np.asarray(xy).reshape(-1, 2)\n",
" ones = np.ones((xy.shape[0], 1))\n",
" xyY = np.concatenate((xy, ones), axis=1)\n",
" return xyY_to_XYZ_numpy(xyY)\n",
"\n",
"\n",
"def XYZ_to_Lab_numpy(XYZ,\n",
" illuminant=ILLUMINANTS.get(\n",
" 'CIE 1931 2 Degree Standard Observer').get('D50')):\n",
" XYZ = np.asarray(XYZ)\n",
" XYZ_r = xy_to_XYZ_numpy(illuminant)\n",
"\n",
" XYZ_f = XYZ / XYZ_r\n",
"\n",
" XYZ_m = XYZ_f > CIE_E\n",
"\n",
" XYZ_f[XYZ_m] = np.power(XYZ_f[XYZ_m], 1 / 3)\n",
" XYZ_f[~XYZ_m] = (CIE_K * XYZ_f[~XYZ_m] + 16) / 116\n",
"\n",
" X_f, Y_f, Z_f = XYZ_f[:, 0], XYZ_f[:, 1], XYZ_f[:, 2]\n",
"\n",
" L = 116 * Y_f - 16\n",
" a = 500 * (X_f - Y_f)\n",
" b = 200 * (Y_f - Z_f)\n",
" \n",
" Lab = np.squeeze(np.dstack((L, a, b)))\n",
"\n",
" return Lab"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%timeit XYZ_to_Lab_numpy(DATA)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10 loops, best of 3: 115 ms per loop\n"
]
}
],
"prompt_number": 8
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment