├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── src ├── index.js └── style.css └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | .env.test 60 | 61 | # parcel-bundler cache (https://parceljs.org/) 62 | .cache 63 | 64 | # next.js build output 65 | .next 66 | 67 | # nuxt.js build output 68 | .nuxt 69 | 70 | # vuepress build output 71 | .vuepress/dist 72 | 73 | # Serverless directories 74 | .serverless/ 75 | 76 | # FuseBox cache 77 | .fusebox/ 78 | 79 | # DynamoDB Local files 80 | .dynamodb/ 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Object Detection 2 | 3 | ## Setup 4 | 5 | ### Clone this Repo 6 | 7 | Run `git clone https://github.com/ichtrojan/Object-Detection.git && cd Object-Detection` 8 | 9 | ![clone](https://res.cloudinary.com/ichtrojan/image/upload/v1552174039/Screenshot_2019-03-10_at_12.26.22_AM_cdsj2g.png) 10 | 11 | ## Install dependencies 12 | 13 | Run `yarn install` 14 | 15 | ![install dependencies](https://res.cloudinary.com/ichtrojan/image/upload/v1552174173/Screenshot_2019-03-10_at_12.29.24_AM_vpral5.png) 16 | 17 | ## Run Application 18 | 19 | Run `npm start` to run the application 20 | 21 | ![run app](https://res.cloudinary.com/ichtrojan/image/upload/v1552174310/Screenshot_2019-03-10_at_12.31.23_AM_brqtjd.png) 22 | 23 | ## Test Application 24 | 25 | Visit `localhost:3000` on your browser (Excluding Safari) to test the application; you will be asked to give permission to access the camera on your machine. 26 | 27 | ![permission](https://res.cloudinary.com/ichtrojan/image/upload/v1552174435/Screenshot_2019-03-10_at_12.33.48_AM_m9fkjm.png) 28 | 29 | If permission is granted, you can proceed to test your application. 30 | 31 | ![test](https://res.cloudinary.com/ichtrojan/image/upload/v1552175031/Screenshot_2019-03-10_at_12.37.39_AM_ovl8y5.png) 32 | 33 | --- 34 | 35 | I wrote this README while I was bored, so if anything doesn't make sense it's totally my fault, do send in a PR for anything you'd like to correct, add or remove. 36 | 37 | E go be ✌️ 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "object-detection", 3 | "version": "1.0.0", 4 | "description": "", 5 | "keywords": [], 6 | "main": "src/index.js", 7 | "dependencies": { 8 | "@tensorflow-models/coco-ssd": "0.1.1", 9 | "@tensorflow/tfjs": "0.14.0", 10 | "react": "16.5.2", 11 | "react-dom": "16.5.2", 12 | "react-magic-dropzone": "1.0.1", 13 | "react-scripts": "^2.0.3" 14 | }, 15 | "devDependencies": {}, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test --env=jsdom", 20 | "eject": "react-scripts eject" 21 | }, 22 | "browserslist": [">0.2%", "not dead", "not ie <= 11", "not op_mini all"] 23 | } 24 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | Object Detection 24 | 25 | 26 | 27 | 30 |
31 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | import * as cocoSsd from "@tensorflow-models/coco-ssd"; 5 | import "@tensorflow/tfjs"; 6 | import "./style.css"; 7 | 8 | class App extends React.Component { 9 | componentDidMount() { 10 | const video = document.getElementById("video"); 11 | const webCamPromise = navigator.mediaDevices 12 | .getUserMedia({ 13 | audio: false, 14 | video: { 15 | facingMode: "user", 16 | width: 600, 17 | height: 500 18 | } 19 | }) 20 | .then(stream => { 21 | video.srcObject = stream; 22 | return new Promise((resolve, reject) => { 23 | video.onloadedmetadata = () => { 24 | video.play(); 25 | resolve(); 26 | }; 27 | }); 28 | }); 29 | const modelPromise = cocoSsd.load(); 30 | Promise.all([modelPromise, webCamPromise]).then(values => { 31 | this.detectFrame(video, values[0]); 32 | }); 33 | } 34 | 35 | detectFrame = (video, model) => { 36 | model.detect(video).then(predictions => { 37 | this.renderPredictions(predictions); 38 | requestAnimationFrame(() => { 39 | this.detectFrame(video, model); 40 | }); 41 | }); 42 | }; 43 | 44 | renderPredictions = predictions => { 45 | const c = document.getElementById("canvas"); 46 | const ctx = c.getContext("2d"); 47 | ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 48 | // Font options. 49 | const font = "16px sans-serif"; 50 | ctx.font = font; 51 | ctx.textBaseline = "top"; 52 | predictions.forEach(prediction => { 53 | const x = prediction.bbox[0]; 54 | const y = prediction.bbox[1]; 55 | const width = prediction.bbox[2]; 56 | const height = prediction.bbox[3]; 57 | // Draw the bounding box. 58 | ctx.strokeStyle = "#00FFFF"; 59 | ctx.lineWidth = 4; 60 | ctx.strokeRect(x, y, width, height); 61 | // Draw the label background. 62 | ctx.fillStyle = "#00FFFF"; 63 | const textWidth = ctx.measureText(prediction.class).width; 64 | const textHeight = parseInt(font, 10); // base 10 65 | ctx.fillRect(x, y, textWidth + 4, textHeight + 4); 66 | }); 67 | 68 | predictions.forEach(prediction => { 69 | const x = prediction.bbox[0]; 70 | const y = prediction.bbox[1]; 71 | // Draw the text last to ensure it's on top. 72 | ctx.fillStyle = "#000000"; 73 | ctx.fillText(prediction.class, x, y); 74 | }); 75 | }; 76 | 77 | render() { 78 | return ( 79 |
80 |
83 | ); 84 | } 85 | } 86 | 87 | const rootElement = document.getElementById("root"); 88 | ReactDOM.render(, rootElement); 89 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | #canvas { 2 | position: fixed; 3 | top: 0; 4 | left: 0; 5 | } 6 | 7 | #video { 8 | position: fixed; 9 | top: 0; 10 | left: 0; 11 | } 12 | 13 | .loading { 14 | position: fixed; 15 | top: 0; 16 | left: 0; 17 | opacity: 0.2; 18 | background-color: #ffffff; 19 | } 20 | --------------------------------------------------------------------------------