transformers.js在react项目中的案例(一)- 创建项目

创建react项目

安装脚手架

npm i create-react-app -g

在合适的目录创建react项目my-app

npx create-react-app my-app

启动项目

cd my-app // 进入my-app目录

code . // 使用vscode打开,若未配置code命令,可以手动打开

npm i // 安装依赖

npm run start // 启动项目

初始化项目 src目录下保留index.js和app.js,其余文件全部删除即可

修改app.js文件名为app.jsx,内容修改如下:

import React from "react";

function App() {
  return (
    <div>
      test
    </div>
  );
}

export default App;

删减index.js文件如下:

import React from 'react';
import ReactDOM from 'react-dom/client';

import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

此时项目页面为:

此时先使用transformers.js中的remove-background-client中的代码测试一下:

1.安装@xenova/transformers:

npm i @xenova/transformers

2.在src下新建components目录,components目录下新建transformers目录,用于存放我们在官网复制的案例

3.在transformers目录下新建index.jsx代码

import React, { useRef } from "react";
import { useAsyncEffect } from "ahooks";
import { AutoModel, AutoProcessor, env, RawImage } from '@xenova/transformers';
import './index.css'

// Since we will download the model from the Hugging Face Hub, we can skip the local model check
env.allowLocalModels = false;
// Proxy the WASM backend to prevent the UI from freezing
env.backends.onnx.wasm.proxy = true;
// Constants
const EXAMPLE_URL = 'https://images.pexels.com/photos/5965592/pexels-photo-5965592.jpeg?auto=compress&cs=tinysrgb&w=1024';

const Transform = () => {
  const status = useRef();
  const fileUpload = useRef();
  const imageContainer = useRef();
  const example = useRef();
  useAsyncEffect(async () => {
    status.current.textContent = 'Loading model...';

    const model = await AutoModel.from_pretrained('briaai/RMBG-1.4', {
      // Do not require config.json to be present in the repository
      config: { model_type: 'custom' },
    });

    const processor = await AutoProcessor.from_pretrained('briaai/RMBG-1.4', {
      // Do not require config.json to be present in the repository
      config: {
        do_normalize: true,
        do_pad: false,
        do_rescale: true,
        do_resize: true,
        image_mean: [0.5, 0.5, 0.5],
        feature_extractor_type: "ImageFeatureExtractor",
        image_std: [1, 1, 1],
        resample: 2,
        rescale_factor: 0.00392156862745098,
        size: { width: 1024, height: 1024 },
      }
    });

    status.current.textContent = 'Ready';

    example.current.addEventListener('click', (e) => {
      e.preventDefault();
      predict(EXAMPLE_URL);
    });

    fileUpload.current.addEventListener('change', function (e) {
      const file = e.target.files[0];
      if (!file) {
        return;
      }

      const reader = new FileReader();

      // Set up a callback when the file is loaded
      reader.onload = e2 => predict(e2.target.result);

      reader.readAsDataURL(file);
    });

    // Predict foreground of the given image
    async function predict(url) {
      // Read image
      const image = await RawImage.fromURL(url);

      // Update UI
      imageContainer.current.innerHTML = '';
      imageContainer.current.style.backgroundImage = `url(${url})`;

      // Set container width and height depending on the image aspect ratio
      const ar = image.width / image.height;
      const [cw, ch] = (ar > 720 / 480) ? [720, 720 / ar] : [480 * ar, 480];
      imageContainer.current.style.width = `${cw}px`;
      imageContainer.current.style.height = `${ch}px`;

      status.current.textContent = 'Analysing...';

      // Preprocess image
      const { pixel_values } = await processor(image);

      // Predict alpha matte
      const { output } = await model({ input: pixel_values });

      // Resize mask back to original size
      const mask = await RawImage.fromTensor(output[0].mul(255).to('uint8')).resize(image.width, image.height);

      // Create new canvas
      const canvas = document.createElement('canvas');
      canvas.width = image.width;
      canvas.height = image.height;
      const ctx = canvas.getContext('2d');

      // Draw original image output to canvas
      ctx.drawImage(image.toCanvas(), 0, 0);

      // Update alpha channel
      const pixelData = ctx.getImageData(0, 0, image.width, image.height);
      for (let i = 0; i < mask.data.length; ++i) {
        pixelData.data[4 * i + 3] = mask.data[i];
      }
      ctx.putImageData(pixelData, 0, 0);

      // Update UI
      imageContainer.current.append(canvas);
      imageContainer.current.style.removeProperty('background-image');
      imageContainer.current.style.background = `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAGUExURb+/v5nD/3QAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAUSURBVBjTYwABQSCglEENMxgYGAAynwRB8BEAgQAAAABJRU5ErkJggg==")`;
      status.current.textContent = 'Done!';
    }

  }, [])


  return <div className="transform">
    <div id="container" ref={imageContainer}>
      <label id="upload-button" htmlFor="upload">
        Click to upload image
        <label id="example" ref={example}>(or try example)</label>
      </label>
    </div>
    <label id="status" ref={status}></label>
    <input id="upload" ref={fileUpload} type="file" accept="image/*" />
  </div>
}

export default Transform;

4.在transformers目录下新建index.css代码

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  font-family: sans-serif;
}

html,
body {
  height: 100%;
}

body {
  padding: 16px 32px;
}

body,
#container,
#upload-button {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

h1,
h4 {
  text-align: center;
}

h4 {
  margin-top: 0.5rem;
}

#container {
  position: relative;
  width: 720px;
  height: 480px;
  max-width: 100%;
  max-height: 100%;
  border: 2px dashed #D1D5DB;
  border-radius: 0.75rem;
  overflow: hidden;
  margin-top: 1rem;
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}

#upload-button {
  gap: 0.4rem;
  font-size: 18px;
  cursor: pointer;
}

#upload {
  display: none;
}

svg {
  pointer-events: none;
}

#example {
  font-size: 14px;
  text-decoration: underline;
  cursor: pointer;
}

#example:hover {
  color: #2563EB;
}

canvas {
  position: absolute;
  width: 100%;
  height: 100%;
}

#status {
  min-height: 16px;
  margin: 8px 0;
}

5.修改App.jsx

import React from "react";
import Transform from "./components/transform";

function App() {
  return (
    <div>
      <Transform></Transform>
    </div>
  );
}

export default App;

此时可以自行测试是否可用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值