Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaScript, GPU et Palet Breton - BreizhCamp 2018

JavaScript, GPU et Palet Breton - BreizhCamp 2018

(Vidéo : https://www.youtube.com/watch?v=vN5vcZpzero)

On est en été, j’ai une bière à la main et une brindille dans l’autre pour essayer de mesurer quel est le palet qui remporte le point.

C’est à ce moment que je me dis qu’à notre époque on doit pouvoir trouver mieux comme instrument de mes... - “T’as bougé le palet !” - grrr c’est décidé je vais faire une app.

Alors on y va ! C++, OpenCV, CUDA, SIMD, on sort l’artillerie lourde… sauf que non, on va se la jouer hype et faire de l’analyse d’image en JavaScript (!) avec l‘aide du GPU (?)

En 15 minutes on va voir comment ca marche et comment c’est tout simple en fait !

De3b2ef28385b01a1b44a9debc66dd6e?s=128

Antoine CAILLY

March 29, 2018
Tweet

Transcript

  1. JavaScript, GPU et palet breton

  2. Palet breton ?

  3. None
  4. None
  5. None
  6. None
  7. None
  8. ?

  9. None
  10. T’as bougé le palet !

  11. None
  12. None
  13. C++, OpenCV, CUDA, SIMD

  14. C++, OpenCV, CUDA, SIMD nope

  15. JavaScript ?

  16. JavaScript + GPU

  17. GPU ?

  18. GPU ? les shaders !

  19. https://openclassrooms.com/courses/developpez-vos-applications-3d-avec-opengl-3-3/introduction-aux-shaders-1 CPU CPU GPU DÉFINITION DES COORDONNÉES

  20. https://openclassrooms.com/courses/developpez-vos-applications-3d-avec-opengl-3-3/introduction-aux-shaders-1 CPU CPU GPU DÉFINITION DES COORDONNÉES VERTEX SHADER

  21. https://openclassrooms.com/courses/developpez-vos-applications-3d-avec-opengl-3-3/introduction-aux-shaders-1 CPU CPU GPU DÉFINITION DES COORDONNÉES VERTEX SHADER “PIXELLISATION”

    DES TRIANGLES
  22. https://openclassrooms.com/courses/developpez-vos-applications-3d-avec-opengl-3-3/introduction-aux-shaders-1 CPU CPU GPU DÉFINITION DES COORDONNÉES VERTEX SHADER “PIXELLISATION”

    DES TRIANGLES FRAGMENT SHADER TEXTURE IMAGE
  23. https://openclassrooms.com/courses/developpez-vos-applications-3d-avec-opengl-3-3/introduction-aux-shaders-1 CPU CPU GPU DÉFINITION DES COORDONNÉES AFFICHAGE VERTEX SHADER

    “PIXELLISATION” DES TRIANGLES FRAGMENT SHADER TEXTURE IMAGE
  24. CPU CPU GPU AFFICHAGE FRAGMENT SHADER TEXTURE IMAGE

  25. CPU CPU GPU RESULTATS FRAGMENT SHADER TEXTURE PARAMÈTRES

  26. CPU CPU GPU RESULTATS FRAGMENT SHADER TEXTURE PARAMÈTRES JAVASCRIPT

  27. CPU CPU GPU RESULTATS FRAGMENT SHADER TEXTURE PARAMÈTRES JAVASCRIPT magique

  28. CPU CPU GPU RESULTATS FRAGMENT SHADER TEXTURE PARAMÈTRES super rapide

    ! JAVASCRIPT magique
  29. CPU CPU GPU RESULTATS FRAGMENT SHADER TEXTURE PARAMÈTRES super rapide

    ! lent lent JAVASCRIPT magique
  30. … // initialisation du shader et définition de fonctions utilitaires

    uniform highp sampler2D user_a; uniform highp vec2 user_aSize; uniform highp vec3 user_aDim; uniform highp sampler2D user_b; uniform highp vec2 user_bSize; uniform highp vec3 user_bDim; highp float kernelResult = 0.0; void kernel() { float user_sum=0.0; for (float user_i=0.0; (user_i<512.0); user_i++){ user_sum+=( get(user_a, vec2(user_aSize[0],user_aSize[1]), vec3(user_aDim[0],user_aDim[1],user_aDim[2]), threadId.y, user_i) * get(user_b, vec2(user_bSize[0],user_bSize[1]), vec3(user_bDim[0],user_bDim[1],user_bDim[2]), user_i, threadId.x) ); } kernelResult = user_sum; return; } const gpu = new GPU(); const multiplyMatrix = gpu.createKernel(function(a, b) { var sum = 0; for (var i = 0; i < 512; i++) { sum += a[this.thread.y][i] * b[i][this.thread.x]; } return sum; }).setOutput([512, 512]);
  31. uniform highp vec3 uOutputDim; uniform highp vec2 uTexSize; varying highp

    vec2 vTexCoord; void main(void) { index = floor(vTexCoord.s * float(uTexSize.x)) + floor(vTexCoord.t * float(uTexSize.y)) * uTexSize.x; threadId = indexTo3D(index, uOutputDim); kernel(); gl_FragColor = encode32(kernelResult); } const c = multiplyMatrix(a, b);
  32. 0.532s x2.72 sur PC 0.196s Multiplication de matrice

  33. 4.301s x14.13 sur smartphone 0.304s Multiplication de matrice

  34. The algorithm

  35. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  36. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  37. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  38. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  39. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  40. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE
  41. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' />
  42. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' /> > npm install sobel
  43. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' /> > npm install sobel var smallestCircle = minBy(circles, c => c.radius)
  44. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' /> > npm install sobel var smallestCircle = minBy(circles, c => c.radius) var nearestCircle = minBy(otherCircles, c => squareDistance(c, smallestCircle))
  45. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' /> > npm install sobel var smallestCircle = minBy(circles, c => c.radius) var nearestCircle = minBy(otherCircles, c => squareDistance(c, smallestCircle)) <img src={imageDataEncodedInBase64} />
  46. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    DÉTECTION DE CONTOUR (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE <input type='file' accept='image/*' capture='camera' /> > npm install sobel var smallestCircle = minBy(circles, c => c.radius) var nearestCircle = minBy(otherCircles, c => squareDistance(c, smallestCircle)) <img src={imageDataEncodedInBase64} /> ← CA SE COMPLIQUE ICI
  47. HOUGH TRANSFORM ou comment éviter de parcourir tous les pixels

  48. None
  49. 1 1 1 1 1 1 1 1 1 1

    1
  50. 1 1 1 1 1 1 1 1 1 1

    1 1 1 2 2 1 1 1 1 1
  51. 1 1 1 1 1 1 1 1 1 1

    1 1 1 1 1 1 1 2 3 2 1 1 1 1 1 1
  52. 2 2 2 2 2 2 2 2 1 2

    2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 2 2 3 2 2 4 16 4 2 2 2 2 2 4 4 4 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 2 2 2 2
  53. 2 2 2 2 2 2 2 2 1 2

    2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 2 2 3 2 2 4 16 4 2 2 2 2 2 4 4 4 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 2 2 2 3 2 2 2 2 2
  54. 2.065 s sur PC NO GPU

  55. 5.346 s sur smartphone NO GPU

  56. Difficilement parallélisable trop compliqué à mon goût

  57. BRUTE FORCE ou comment parcourir tous les pixels

  58. 0

  59. 1 1 2

  60. 1 1 1 3

  61. 1 1 1 1 1 1 1 1 16 1

    1 1 1 1 1 1 1
  62. Premiers essais

  63. 7.080 s sur PC GPU 2.065 s NO GPU

  64. 7.080 s sur PC 2.065 s NO GPU

  65. PRISE DE PHOTO GRAND CERCLE LE PLUS PROCHE DU PETIT

    SEUILLAGE (SOBEL) DÉTECTION DE CERCLES PLUS PETIT CERCLE AFFICHAGE CPU GPU lent
  66. Pour chaque rayon : Calculer le score de tous les

    pixels Identifier les cercles potentiels Merger avec les résultats précédents Limiter les allers-retours Fusionner les étapes (kernels)
  67. Pour tous les rayons : Calculer le score de tous

    les pixels Identifier les cercles potentiels Merger avec les résultats précédents Limiter les allers-retours Fusionner les étapes (kernels)
  68. Limiter les allers-retours Brancher la sortie d’une étape sur l’entrée

    de la suivante gpu.combineKernels(...)
  69. 1.256 s sur PC GPU 2.065 s NO GPU

  70. 2.112 s sur smartphone GPU 5.346 s NO GPU

  71. 2.112 s sur smartphone 5.346 s NO GPU

  72. Et après... Sobel sur GPU Offscreen Canvas

  73. https://acailly.github.io/palet/ @AntoineCailly acailly