# garbage-classify **Repository Path**: suiboyu/garbage-classify ## Basic Information - **Project Name**: garbage-classify - **Description**: React+TensorFlow实现垃圾分类识别 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2020-10-09 - **Last Updated**: 2022-05-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # garbage-classify #### 介绍 React + TensorFlow 实现垃圾分类 #### 项目截图 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0303/085754_d8d8efef_5176171.png "20201008171139836.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0303/085811_9c976292_5176171.gif "20201008171235176.gif") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0303/085802_ccd0c23c_5176171.png "20201008171225628.png") #### 项目运行需要一定的环境,如何搭建环境 ``` npm install --global windows-build-tools(这个时间很漫长。。。) npm install @tensorflow/tfjs-node(这个时间很漫长。。。) ``` ###### python 环境 2.7 #### 下载好代码之后,记得在根目录下创建一个 垃圾分类文件夹,这个文件夹里面是图片 链接:https://pan.baidu.com/s/1A1hBxH4kz3W0wq8eWDRnhA 提取码:6v5q 具体步骤请看 (window10) 安装运行环境: npm install --global windows-build-tools(这个时间很漫长。。。) npm install @tensorflow/tfjs-node(这个时间很漫长。。。) 项目目录如下 train文件夹 index.js(入口文件) ```js const tf = require('@tensorflow/tfjs-node') const getData = require('./data') const TRAIN_DIR = '../垃圾分类/train' const OUTPUT_DIR = '../outputDir' const MOBILENET_URL = 'http://ai-sample.oss-cn-hangzhou.aliyuncs.com/pipcook/models/mobilenet/web_model/model.json' const main = async () => { // 加载数据 const { ds, classes} = await getData(TRAIN_DIR, OUTPUT_DIR) // 定义模型 const mobilenet = await tf.loadLayersModel(MOBILENET_URL) mobilenet.summary() // console.log(mobilenet.layers.map((l, i) => [l.name, i])) const model = tf.sequential() for (let i = 0; i <= 86; i += 1) { const layer = mobilenet.layers[i] layer.trainable = false model.add(layer) } model.add(tf.layers.flatten()) model.add(tf.layers.dense({ units: 10, activation: 'relu' })) model.add(tf.layers.dense({ units: classes.length, activation: 'softmax' })) // 训练模型 model.compile({ loss: 'sparseCategoricalCrossentropy', optimizer: tf.train.adam(), metrics: ['acc'] }) await model.fitDataset(ds, { epochs: 20 }) await model.save(`file://${process.cwd()}/${OUTPUT_DIR}`) } main() ``` data.js(处理数据) ```js const fs = require('fs') const tf = require('@tensorflow/tfjs-node') const img2x = (imgPath) => { const buffer = fs.readFileSync(imgPath) return tf.tidy(() => { const imgTs = tf.node.decodeImage(new Uint8Array(buffer)) const imgTsResized = tf.image.resizeBilinear(imgTs, [224, 224]) return imgTsResized.toFloat().sub(255/2).div(255/2).reshape([1, 224, 224, 3]) }) } const getData = async (trainDir, outputDir) => { const classes = fs.readdirSync(trainDir) fs.writeFileSync(`${outputDir}/classes.json`, JSON.stringify(classes)) const data = [] classes.forEach((dir, dirIndex) => { fs.readdirSync(`${trainDir}/${dir}`) .filter(n => n.match(/jpg$/)) .slice(0, 10) .forEach(filename => { console.log('读取', dir, filename) const imgPath = `${trainDir}/${dir}/${filename}` data.push({ imgPath, dirIndex }) }) }) tf.util.shuffle(data) const ds = tf.data.generator(function* () { const count = data.length const batchSize = 32 for (let start = 0; start < count; start += batchSize) { const end = Math.min(start + batchSize, count) yield tf.tidy(() => { const inputs = [] const labels = [] for (let j = start; j < end; j += 1) { const { imgPath, dirIndex } = data[j] const x = img2x(imgPath) inputs.push(x) labels.push(dirIndex) } const xs = tf.concat(inputs) const ys = tf.tensor(labels) return { xs, ys } }) } }) return { ds, classes } } module.exports = getData ``` 安装一些运行项目需要的插件 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0303/085705_e5b1410d_5176171.png "20201009120042295.png") app 文件夹 ```js import React, { PureComponent } from 'react' import { Button, Progress, Spin, Empty } from 'antd' import 'antd/dist/antd.css' import * as tf from '@tensorflow/tfjs' import { file2img, img2x } from './utils' import intro from './intro' const DATA_URL = 'http://127.0.0.1:8080/' class App extends PureComponent { state = {} async componentDidMount() { this.model = await tf.loadLayersModel(DATA_URL + '/model.json') // this.model.summary() this.CLASSES = await fetch(DATA_URL + '/classes.json').then(res => res.json()) } predict = async (file) => { const img = await file2img(file) this.setState({ imgSrc: img.src, isLoading: true }) setTimeout(() => { const pred = tf.tidy(() => { const x = img2x(img) return this.model.predict(x) }) const results = pred.arraySync()[0] .map((score, i) => ({score, label: this.CLASSES[i]})) .sort((a, b) => b.score - a.score) this.setState({ results, isLoading: false }) }, 0) } renderResult = (item) => { const finalScore = Math.round(item.score * 100) return ( {item.label} ) } render() { const { imgSrc, results, isLoading } = this.state const finalItem = results && {...results[0], ...intro[results[0].label]} return (
识别可能不准确 this.predict(e.target.files[0])} ref={el => {this.upload = el}} style={{ display: 'none' }} /> { !results && !imgSrc && } {imgSrc &&
} {finalItem &&
识别结果:
} {finalItem &&

{finalItem.label}

{finalItem.intro}
} { isLoading && } {results &&
{results.map(this.renderResult)}
类别 匹配度
}
) } } export default App ``` index.html ```js 垃圾分类
``` index.js ```js import React from 'react' import ReactDOM from 'react-dom' import App from './App' ReactDOM.render(, document.querySelector('#app')) ``` intro.js ```js export default { '可回收物': { icon: 'https://lajifenleiapp.com/static/svg/1_3F6BA8.svg', color: '#3f6ba8', intro: '是指在日常生活中或者为日常生活提供服务的活动中产生的,已经失去原有全部或者部分使用价值,回收后经过再加工可以成为生产原料或者经过整理可以再利用的物品,包括废纸类、塑料类、玻璃类、金属类、织物类等。' }, '有害垃圾': { icon: 'https://lajifenleiapp.com/static/svg/2v_B43953.svg', color: '#b43953', intro: '是指生活垃圾中对人体健康或者自然环境造成直接或者潜在危害的物质,包括废充电电池、废扣式电池、废灯管、弃置药品、废杀虫剂(容器)、废油漆(容器)、废日用化学品、废水银产品、废旧电器以及电子产品等。' }, '厨余垃圾': { icon: 'https://lajifenleiapp.com/static/svg/3v_48925B.svg', color: '#48925b', intro: '是指居民日常生活中产生的有机易腐垃圾,包括菜叶、剩菜、剩饭、果皮、蛋壳、茶渣、骨头等。' }, '其他垃圾': { icon: 'https://lajifenleiapp.com/static/svg/4_89918B.svg', color: '#89918b', intro: '是指除可回收物、有害垃圾和厨余垃圾之外的,混杂、污染、难分类的其他生活垃圾。' } } ``` utils.js ```js import * as tf from '@tensorflow/tfjs' export const file2img = async (f) => { return new Promise(reslove => { const reader = new FileReader() reader.readAsDataURL(f) reader.onload = (e) => { const img = document.createElement('img') img.src = e.target.result img.width = 224 img.height = 224 img.onload = () => { reslove(img) } } }) } export function img2x(imgEl) { return tf.tidy(() => { return tf.browser.fromPixels(imgEl) .toFloat().sub(255/2).div(255/2) .reshape([1, 224, 224, 3]) }) } ``` 运行项目代码之前,我们需要先在 train 目录下运行,node index.js,生成 model.json 以供识别系统使用。之后需要在根目录下运行 hs outputDir --cors, 使得生成的 model.json 运行在 http 环境下,之后才可以运行 npm start ,不然项目是会报错的。