如何利用React实现图片识别App


Posted in Javascript onFebruary 18, 2022

先把效果图给大家放上来

如何利用React实现图片识别App

如何利用React实现图片识别App

如何利用React实现图片识别App

个人觉得效果还行。识别不太准确是因为这个 app学习图片的时间太短(电脑太卡)。

(笔者是 window10) 安装运行环境:

  • npm install --global windows-build-tools(这个时间很漫长。。。)
  • npm install @tensorflow/tfjs-node(这个时间很漫长。。。)

项目目录如下 如何利用React实现图片识别App

train文件夹 index.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(处理数据)

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

安装一些运行项目需要的插件 如何利用React实现图片识别App

app 文件夹

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 (
      <tr key={item.label}>
        <td style={{ width: 80, padding: '5px 0' }}>{item.label}</td>
        <td>
          <Progress percent={finalScore} status={finalScore === 100 ? 'success' : 'normal'} />
        </td>
      </tr>
    )
  }

  render() {
    const { imgSrc, results, isLoading } = this.state
    const finalItem = results && {...results[0], ...intro[results[0].label]}

    return (
      <div style={{padding: 20}}>
        <span
          style={{ color: '#cccccc', textAlign: 'center', fontSize: 12, display: 'block' }}
        >识别可能不准确</span>
        <Button
          type="primary"
          size="large"
          style={{width: '100%'}}
          onClick={() => this.upload.click()}
        >
          选择图片识别
        </Button>
        <input
          type="file"
          onChange={e => this.predict(e.target.files[0])}
          ref={el => {this.upload = el}}
          style={{ display: 'none' }}
        />
        {
          !results && !imgSrc && <Empty style={{ marginTop: 40 }} />
        }
        {imgSrc && <div style={{ marginTop: 20, textAlign: 'center' }}>
          <img src={imgSrc} style={{ maxWidth: '100%' }} />
        </div>}
        {finalItem && <div style={{marginTop: 20}}>识别结果: </div>}
        {finalItem && <div style={{display: 'flex', alignItems: 'flex-start', marginTop: 20}}>
          <img
            src={finalItem.icon}
            width={120}
          />
          <div>
            <h2 style={{color: finalItem.color}}>
              {finalItem.label}
            </h2>
            <div style={{color: finalItem.color}}>
              {finalItem.intro}
            </div>
          </div>
        </div>}
        {
          isLoading && <Spin size="large" style={{display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: 40 }} />
        }
        {results && <div style={{ marginTop: 20 }}>
          <table style={{width: '100%'}}>
            <tbody>
              <tr>
                <td>类别</td>
                <td>匹配度</td>
              </tr>
              {results.map(this.renderResult)}
            </tbody>
          </table>
        </div>}
      </div>
    )
  }
}

export default App

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>垃圾分类</title>
    <meta name="viewport" content="width=device-width, inital-scale=1">
  </head>
  <body>
    <div id="app"></div>
    <script src="./index.js"></script>
  </body>
</html>

index.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

ReactDOM.render(<App />, document.querySelector('#app'))

intro.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

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 ,不然项目是会报错的。

主要的代码就是上面这些。前面笔者也说了。自己对这方面完全不懂,所以也无法解说其中的代码。各位感兴趣就自己研究一下。代码地址奉上。

gitee.com/suiboyu/gar…

总结

到此这篇关于如何利用React实现图片识别App的文章就介绍到这了,更多相关React图片识别App内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
IE与firefox下Dhtml的一些区别小结
Dec 02 Javascript
Javascript load Page,load css,load js实现代码
Mar 31 Javascript
js关闭父窗口时关闭子窗口
Apr 01 Javascript
jquery特效 点击展示与隐藏全文
Dec 09 Javascript
详解js的事件代理(委托)
Dec 22 Javascript
JS在浏览器中解析Base64编码图像
Feb 09 Javascript
ES6新特性七:数组的扩充详解
Apr 21 Javascript
JavaScript实现左侧菜单效果
Dec 14 Javascript
Vue一次性简洁明了引入所有公共组件的方法
Nov 28 Javascript
vue中将html字符串转换成html后遇到的问题小结
Dec 10 Javascript
JS将时间秒转换成天小时分钟秒的字符串
Jul 10 Javascript
vue 使用rules对表单字段进行校验的步骤
Dec 25 Vue.js
JavaScript展开运算符和剩余运算符的区别详解
Feb 18 #Javascript
微信小程序中使用vant框架的具体步骤
Vue elementUI表单嵌套表格并对每行进行校验详解
Feb 18 #Vue.js
微信小程序中wxs文件的一些妙用分享
Feb 18 #Javascript
vue项目支付功能代码详解
Feb 18 #Vue.js
JavaScript的Set数据结构详解
Feb 18 #Javascript
JS封装cavans多种滤镜组件
You might like
PHP 和 COM
2006/10/09 PHP
php像数组一样存取和修改字符串字符
2014/03/21 PHP
在php中设置session用memcache来存储的方法总结
2016/01/14 PHP
PHP设计模式之适配器模式定义与用法详解
2018/04/03 PHP
从Ajax到JQuery Ajax学习
2007/02/14 Javascript
jQuery的强大选择器小结
2009/12/27 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
js实现Form栏显示全格式时间时钟效果代码
2015/08/19 Javascript
简单实现兼容各大浏览器的js复制内容到剪切板
2015/09/09 Javascript
JS实现适合于后台使用的动画折叠菜单效果
2015/09/21 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
在Swiper内如何制作CSS3动画效果示例代码
2017/12/07 Javascript
angular4 获取wifi列表中文显示乱码问题的解决
2018/10/20 Javascript
Vue动态创建注册component的实例代码
2019/06/14 Javascript
微信小程序实现日期格式化和倒计时
2020/11/01 Javascript
javascript实现函数柯里化与反柯里化过程解析
2019/10/08 Javascript
微信小程序之左右布局的实现代码
2019/12/13 Javascript
webpack打包html里面img后src为“[object Module]”问题
2019/12/22 Javascript
[05:26]2014DOTA2西雅图国际邀请赛 iG战队巡礼
2014/07/07 DOTA
python中引用与复制用法实例分析
2015/06/04 Python
Pycharm学习教程(6) Pycharm作为Vim编辑器使用
2017/05/03 Python
Python使用matplotlib的pie函数绘制饼状图功能示例
2018/01/08 Python
django中send_mail功能实现详解
2018/02/06 Python
Python发送邮件功能示例【使用QQ邮箱】
2018/12/04 Python
Python3.5多进程原理与用法实例分析
2019/04/05 Python
django中related_name的用法说明
2020/05/20 Python
通过HTML5 Canvas API绘制弧线和圆形的教程
2016/03/14 HTML / CSS
计算机专业推荐信范文
2013/11/20 职场文书
网络工程师职业规划
2014/02/10 职场文书
剪彩仪式主持词
2014/03/19 职场文书
家长会演讲稿
2014/04/26 职场文书
2014客服代表实习自我鉴定
2014/09/18 职场文书
会计工作能力自我评价
2015/03/05 职场文书
实习班主任自我评价
2015/03/11 职场文书
2015年英语教师工作总结
2015/05/20 职场文书
一文搞懂PHP中的抽象类和接口
2022/05/25 PHP