{"version":3,"sources":["constants.js","utils.js","draw.js","model.js","App.js","index.js"],"names":["WORD_INDEX","ANSWERS","CANVAS_SIZE","IMAGE_SIZE","MIN_SHAPE_SIZE","MAX_SHAPE_SIZE","COLORS","black","gray","red","green","blue","yellow","teal","brown","COLOR_NAMES","Object","keys","SHAPES","randint","min","max","Math","floor","random","CANVAS_RATIO","MIN_CANVAS_SHAPE_SIZE","MAX_CANVAS_SHAPE_SIZE","SIN_60","sqrt","drawShape","context","shape","colorName","r","g","b","fillStyle","fillRect","drawBackground","w","h","drawRectangle","beginPath","arc","PI","fill","drawCircle","s","x","y","ceil","moveTo","lineTo","drawTriangle","console","error","loadModelPromise","tf","then","model","getBagOfWords","str","trim","replace","toLowerCase","bagOfWords","Array","length","split","forEach","token","imageData","question","a","questionBOW","imageTensor","fromPixels","expandDims","div","sub","questionTensor","predict","argMax","arraySync","answerIndex","catch","SAMPLE_QUESTIONS","randomQuestion","isEmbedded","URLSearchParams","window","location","search","has","App","useState","color","setColor","setShape","setQuestion","answer","setAnswer","modelLoaded","setModelLoaded","predicting","setPredicting","mainCanvas","useRef","smallCanvas","onPredict","useCallback","useEffect","current","ctx","getContext","ratio","scale","drawImage","getInference","onQuestionChange","e","target","value","randomizeImage","randomizeQuestion","q","className","href","rel","Card","Header","Body","ref","width","height","style","display","Text","Button","onClick","disabled","Form","Group","controlId","Control","as","placeholder","onChange","variant","size","Alert","ReactDOM","render","document","getElementById"],"mappings":"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","file":"static/js/main.3d679468.chunk.js","sourcesContent":["// All of these constants should be kept in sync with their counterparts in easy-VQA,\n// the repo that contains the code to generate the dataset.\n\nconst WORD_INDEX = {'is': 1, 'shape': 2, 'the': 3, 'a': 4, 'image': 5, 'there': 6, 'not': 7, 'what': 8, 'does': 9, 'contain': 10, 'in': 11, 'present': 12, 'color': 13, 'no': 14, 'triangle': 15, 'rectangle': 16, 'circle': 17, 'teal': 18, 'gray': 19, 'brown': 20, 'blue': 21, 'green': 22, 'yellow': 23, 'red': 24, 'black': 25, 'of': 26};\nconst ANSWERS = ['green', 'triangle', 'no', 'rectangle', 'gray', 'red', 'blue', 'yes', 'circle', 'black', 'yellow', 'brown', 'teal'];\n\nconst CANVAS_SIZE = 256;\nconst IMAGE_SIZE = 64;\nconst MIN_SHAPE_SIZE = IMAGE_SIZE / 8;\nconst MAX_SHAPE_SIZE = IMAGE_SIZE / 2;\n\nconst COLORS = {\n black: 'black',\n gray: 'rgb(128, 128, 128)',\n red: 'red',\n green: 'green',\n blue: 'blue',\n yellow: 'yellow',\n teal: 'teal',\n brown: 'rgb(165, 42, 42)',\n};\nconst COLOR_NAMES = Object.keys(COLORS);\n\nconst SHAPES = [\n 'rectangle',\n 'circle',\n 'triangle',\n];\n\nexport {\n WORD_INDEX,\n ANSWERS,\n CANVAS_SIZE,\n IMAGE_SIZE,\n MIN_SHAPE_SIZE,\n MAX_SHAPE_SIZE,\n COLORS,\n COLOR_NAMES,\n SHAPES,\n};\n","// Returns a random integer in [min, max] INCLUSIVE (to match Python's randint()).\nexport function randint(min, max) {\n return Math.floor(min + Math.random() * (max + 1 - min));\n}\n","import { CANVAS_SIZE, IMAGE_SIZE, MIN_SHAPE_SIZE, MAX_SHAPE_SIZE, COLORS } from './constants';\nimport { randint } from './utils';\n\nconst CANVAS_RATIO = CANVAS_SIZE / IMAGE_SIZE;\nconst MIN_CANVAS_SHAPE_SIZE = MIN_SHAPE_SIZE * CANVAS_RATIO;\nconst MAX_CANVAS_SHAPE_SIZE = MAX_SHAPE_SIZE * CANVAS_RATIO;\n\nfunction drawBackground(context) {\n // The range (230, 255) matches the corresponding range in easy-VQA\n const r = randint(230, 255);\n const g = randint(230, 255);\n const b = randint(230, 255);\n context.fillStyle = `rgb(${r}, ${g}, ${b})`;\n context.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);\n}\n\nfunction drawRectangle(context) {\n const w = randint(MIN_CANVAS_SHAPE_SIZE, MAX_CANVAS_SHAPE_SIZE);\n const h = randint(MIN_CANVAS_SHAPE_SIZE, MAX_CANVAS_SHAPE_SIZE);\n context.fillRect(randint(0, CANVAS_SIZE - w), randint(0, CANVAS_SIZE - h), w, h);\n}\n\nfunction drawCircle(context) {\n const r = randint(MIN_CANVAS_SHAPE_SIZE, MAX_CANVAS_SHAPE_SIZE) / 2;\n context.beginPath();\n context.arc(randint(r, CANVAS_SIZE - r), randint(r, CANVAS_SIZE - r), r, 0, 2 * Math.PI);\n context.fill();\n}\n\nconst SIN_60 = Math.sqrt(3) / 2;\nfunction drawTriangle(context) {\n const s = randint(MIN_CANVAS_SHAPE_SIZE, MAX_CANVAS_SHAPE_SIZE);\n let x = randint(0, CANVAS_SIZE - s);\n let y = randint(Math.ceil(s * SIN_60), CANVAS_SIZE);\n context.beginPath();\n context.moveTo(x, y);\n context.lineTo(x + s, y);\n context.lineTo(x + s / 2, y - s * SIN_60);\n context.lineTo(x, y);\n context.fill();\n}\n\nexport function drawShape(context, shape, colorName) {\n drawBackground(context);\n\n context.fillStyle = COLORS[colorName];\n switch (shape) {\n case 'rectangle':\n drawRectangle(context);\n break;\n case 'circle':\n drawCircle(context);\n break;\n case 'triangle':\n drawTriangle(context);\n break;\n default:\n console.error('Invalid shape name provided', shape);\n break;\n }\n}\n","import * as tf from '@tensorflow/tfjs';\n\nimport {WORD_INDEX, ANSWERS} from './constants';\n\nexport const loadModelPromise = tf.loadLayersModel('/model.json')\n .then(model => {\n return model;\n });\n\nfunction getBagOfWords(str) {\n str = str.trim()\n .replace(/[^\\w\\s]|_/g, '')\n .replace(/\\s+/g, ' ')\n .toLowerCase();\n\n // We have to add 1 to maintain consistency with how the BOW vectors are\n // generated in our Python implementation. See easy-VQA-keras for more.\n const bagOfWords = Array(Object.keys(WORD_INDEX).length + 1).fill(0);\n\n const tokens = str.split(' ');\n tokens.forEach(token => {\n if (token in WORD_INDEX) {\n bagOfWords[WORD_INDEX[token]] += 1;\n }\n });\n return bagOfWords;\n}\n\nexport async function getInference(imageData, question) {\n const questionBOW = getBagOfWords(question);\n return loadModelPromise.then(model => {\n let imageTensor = tf.browser.fromPixels(imageData, 3);\n imageTensor = imageTensor.expandDims(0);\n imageTensor = imageTensor.div(255).sub(0.5);\n\n let questionTensor = tf.tensor(questionBOW);\n questionTensor = questionTensor.expandDims(0);\n\n let output = model.predict([imageTensor, questionTensor]);\n\n let [answerIndex] = output.argMax(1).arraySync();\n return ANSWERS[answerIndex];\n })\n .catch(console.error);\n}\n","import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport Button from 'react-bootstrap/Button';\nimport Card from 'react-bootstrap/Card';\nimport Form from 'react-bootstrap/Form';\nimport Alert from 'react-bootstrap/Alert';\n\nimport { drawShape } from './draw';\nimport { getInference, loadModelPromise } from './model';\nimport { CANVAS_SIZE, IMAGE_SIZE, COLOR_NAMES, SHAPES } from './constants';\nimport { randint } from './utils';\n\nimport 'bootstrap/dist/css/bootstrap.min.css';\nimport './App.css';\n\nconst SAMPLE_QUESTIONS = [\n 'What color is the shape?',\n 'Is there a blue shape in the image?',\n 'Is there a red shape?',\n 'Is there a green shape in the image?',\n 'Is there a black shape?',\n 'Is there not a teal shape in the image?',\n 'Does the image contain a rectangle?',\n 'Does the image not contain a circle?',\n 'What shape is present?',\n 'Is no triangle present?',\n 'Is a circle present?',\n 'Is a rectangle present?',\n 'Is there a triangle?',\n 'What is the color of the shape?',\n 'What shape does the image contain?',\n];\n\nconst randomQuestion = () => SAMPLE_QUESTIONS[randint(0, SAMPLE_QUESTIONS.length - 1)];\n\nconst urlParams = new URLSearchParams(window.location.search);\nconst isEmbedded = urlParams.has('embed');\n\nfunction App() {\n const [color, setColor] = useState(null);\n const [shape, setShape] = useState(null);\n const [question, setQuestion] = useState(randomQuestion());\n const [answer, setAnswer] = useState(null);\n const [modelLoaded, setModelLoaded] = useState(false);\n const [predicting, setPredicting] = useState(false);\n\n const mainCanvas = useRef(null);\n const smallCanvas = useRef(null);\n\n const onPredict = useCallback(() => {\n setPredicting(true);\n }, [setPredicting]);\n\n useEffect(() => {\n if (smallCanvas.current) {\n const ctx = smallCanvas.current.getContext('2d');\n const ratio = IMAGE_SIZE / CANVAS_SIZE;\n ctx.scale(ratio, ratio);\n }\n }, [smallCanvas]);\n\n useEffect(() => {\n if (predicting) {\n // Draw the main canvas to our smaller, correctly-sized canvas\n const ctx = smallCanvas.current.getContext('2d');\n ctx.drawImage(mainCanvas.current, 0, 0);\n\n getInference(smallCanvas.current, question).then(answer => {\n setAnswer(answer);\n setPredicting(false);\n });\n }\n }, [predicting, question]);\n\n const onQuestionChange = useCallback(\n e => {\n setQuestion(e.target.value);\n setAnswer(null);\n },\n [setQuestion]\n );\n\n const randomizeImage = useCallback(() => {\n const context = mainCanvas.current.getContext('2d');\n const colorName = COLOR_NAMES[randint(0, COLOR_NAMES.length - 1)];\n const shape = SHAPES[randint(0, SHAPES.length - 1)];\n\n drawShape(context, shape, colorName);\n\n setColor(colorName);\n setShape(shape);\n setAnswer(null);\n }, [mainCanvas]);\n\n const randomizeQuestion = useCallback(() => {\n let q = question;\n while (q === question) {\n q = randomQuestion();\n }\n setQuestion(q);\n setAnswer(null);\n }, [question, setQuestion]);\n\n useEffect(() => {\n randomizeImage();\n\n loadModelPromise.then(() => {\n setModelLoaded(true);\n });\n }, []);\n\n return (\n <div className=\"root\">\n {!isEmbedded && (\n <>\n <h1>easy-VQA Demo</h1>\n <h2>\n A Javascript demo of a{' '}\n <a href=\"https://victorzhou.com/blog/easy-vqa/\">Visual Question Answering (VQA)</a>{' '}\n model trained on the{' '}\n <a\n href=\"https://github.com/vzhou842/easy-VQA\"\n target=\"_blank\"\n rel=\"nofollow noreferrer\"\n >\n easy-VQA dataset\n </a>\n .\n </h2>\n <p className=\"description\">\n <b>Read the <a href=\"https://victorzhou.com/blog/easy-vqa/\">blog post</a></b> or see the source code on{' '}\n <a\n href=\"https://github.com/vzhou842/easy-VQA-demo\"\n target=\"_blank\"\n rel=\"nofollow noreferrer\"\n >\n Github\n </a>\n .\n </p>\n </>\n )}\n <div className=\"container\">\n <Card>\n <Card.Header>The Image</Card.Header>\n <Card.Body>\n <canvas ref={mainCanvas} width={CANVAS_SIZE} height={CANVAS_SIZE} />\n <canvas\n ref={smallCanvas}\n width={IMAGE_SIZE}\n height={IMAGE_SIZE}\n style={{ display: 'none' }}\n />\n <figcaption className=\"image-caption\">\n A <b>{color}</b>, <b>{shape}</b> shape.\n </figcaption>\n <br />\n <Card.Text>Want a different image?</Card.Text>\n <Button onClick={randomizeImage} disabled={predicting}>\n Random Image\n </Button>\n </Card.Body>\n </Card>\n <Card>\n <Card.Header>The Question</Card.Header>\n <Card.Body>\n <Form>\n <Form.Group controlId=\"formQuestion\">\n <Form.Control\n as=\"textarea\"\n placeholder={SAMPLE_QUESTIONS[0]}\n value={question}\n onChange={onQuestionChange}\n disabled={predicting}\n />\n </Form.Group>\n </Form>\n <Card.Text>Want a different question?</Card.Text>\n <Button onClick={randomizeQuestion} disabled={predicting}>\n Random Question\n </Button>\n </Card.Body>\n </Card>\n </div>\n <Button variant=\"success\" size=\"lg\" onClick={onPredict} disabled={!modelLoaded || predicting}>\n {modelLoaded ? (predicting ? 'Predicting...' : 'Predict') : 'Loading model...'}\n </Button>\n <br />\n {!!answer ? (\n <Alert variant=\"primary\">\n Prediction: <b>{answer}</b>\n </Alert>\n ) : predicting ? (\n <Alert variant=\"light\">The prediction will appear here soon...</Alert>\n ) : (\n <Alert variant=\"light\">Click Predict!</Alert>\n )}\n </div>\n );\n}\n\nexport default App;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\n\nReactDOM.render(<App />, document.getElementById('root'));\n"],"sourceRoot":""}