使用paddlex,找到小猪佩奇

309 阅读3分钟

0、准备一个文件夹,文件夹要包含两个子文件夹

1)JPEGImages 尺寸一样的小猪佩奇图片

2)Annotations 这里是放置pascal-voc格式的xml文件的,该文件在第3步时会生成。

1、打开精灵标注,新建一个目标检测项目

由于这个示例只识别小猪佩奇,因此分类值只写 Peppa Pig。

2、逐个进行框选标注

要记住每次标注后,都要点击下面的蓝色对勾按钮,否则它不保存的(这里是坑)。

3、都标注完成后导出pascal-voc格式

4、在paddlex GUI中新建目标检测数据集

5、导入文件夹并切分数据集

6、在paddlex GUI中,新建一个目标检测项目。

7、输入参数启动训练

8、等训练完成后,点击模型评估

9、启动测试

测试是可以找到的

10、发布模型

也可以移动端发布

11、新建一个python脚本载入模型,进行测试

import paddlex as pdx
import cv2
model = pdx.deploy.Predictor('inference_model', use_gpu=False)
im = cv2.imread('test.jpg')
im = im.astype('float32')
result = model.predict(im)
print(result)

12、使用python开发一个web服务。

# coding: utf-8
import os
import uuid
import hashlib
from time import time
from flask import Flask, flash, request, redirect, url_for, render_template, jsonify, json
from flask_restful import Resource, Api
from werkzeug.utils import secure_filename
from flask_cors import CORS
from paddlex.cls import transforms
import paddlex
import cv2
import warnings
train_transforms = transforms.Compose([
    transforms.RandomCrop(crop_size=224),
    transforms.Normalize()
])


model = paddlex.load_model('./models/peppa/inference_model')#目标检测模型

UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}

app = Flask(import_name=__name__,
            static_url_path='/', # 配置静态文件的访问 url 前缀
            static_folder='public',    # 配置静态文件的文件夹
            template_folder='templates') # 配置模板文件的文件夹
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
api = Api(app)
CORS(app)


def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/')
def html():
    return render_template('index.html')


class Upload(Resource):
    def post(self):
        if 'file' not in request.files:
            return jsonify(err=True, msg='No file part')
        file = request.files['file']
        print(file)
        if file.filename == '':
            return jsonify(err=True, msg='No selected file')
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            arr = filename.split('.')
            extname = arr[len(arr)-1]

            # pdf = file.read()
            # file_md5 = hashlib.md5(file.read()).hexdigest()
            id = str(uuid.uuid4())
            newfilename = "{}.{}".format(id, extname)
            filepath = os.path.join(app.config['UPLOAD_FOLDER'], newfilename)
            file.save(filepath)
            im = cv2.imread(filepath)
            result = model.predict(im)
            arr = []
            for item in result:
                if item["score"]>0.1:
                    position = item["bbox"]
                    x = position[0]
                    y = position[1]
                    w = position[2]
                    h = position[3]
                    item["position"] = dict()
                    item["position"]["x"] = x
                    item["position"]["y"] = y
                    item["position"]["w"] = w
                    item["position"]["h"] = h
                    item["confidence"]=item["score"]
                    item["text"]=item["category"]
                    item.pop("bbox")
                    item.pop("score")
                    item.pop("category")
                    arr.append(item)
            # im.close()
            return jsonify(arr)
        return jsonify(err=True, msg='file type Not Allowed')
api.add_resource(Upload, '/api/upload')
app.run(port=8080, debug=True, host='0.0.0.0')

13、使用React开发一个web界面,实现拖拽并生成框框。

import React, { useState } from "react";
import Dropzone from "react-dropzone";
import ReactLoading from "react-loading";
import axios, { AxiosRequestConfig, AxiosInstance } from "axios";
import Snackbar from "@material-ui/core/Snackbar";
import Alert from "@material-ui/lab/Alert"
import "./App.css";
import { stat } from "fs";
enum MsgType {
  error = "error",
  warning = "warning",
  info = "info",
  success = "success"
}
interface Imsg {
  type: MsgType,
  text: string
}
interface IRect {
  text: string;
  confidence: number;
  position: {
    x: number;
    y: number;
    w: number;
    h: number;
  };
}
enum Status {
  ready,
  uploading,
  res_empty,
  res_ok,
  res_err,
  img_err,
}
const Text = ({
  text,
  x,
  y,
  w,
  h,
}: {
  text: string;
  x: number;
  y: number;
  w: number;
  h: number;
}) => {
  return (
    <div
      className="rect-text"
      style={{
        left: x + "px",
        top: y - 20 + "px",
        width: w + "px",
        height: "20px",
      }}
    >
      {text}
    </div>
  );
};
const Rect = ({
  text,
  x,
  y,
  w,
  h,
}: {
  text: string;
  x: number;
  y: number;
  w: number;
  h: number;
}) => {
  return (
    <div
      className="rect"
      style={{
        left: x + "px",
        top: y + "px",
        width: w + "px",
        height: h + "px",
      }}
    ></div>
  );
};
function App() {
  const [src, setSrc] = useState<string>("");
  const [msg, setMsg] = useState<Imsg>({
    type: MsgType.info,
    text: ""
  });
  const [status, setStatus] = useState<Status>(Status.ready);
  const [rects, setRects] = useState<IRect[]>([]);
  const onDrop = async (acceptedFiles: File[]) => {
    setRects([]);
    acceptedFiles.forEach(async (file: File) => {
      console.log(file);
      // reader.readAsArrayBuffer(file)
      if (file.type.includes("image")) {
        setStatus(Status.uploading);
        const reader = new FileReader();
        reader.onload = async () => {
          const base64Str: string = reader.result + "";
          setSrc(base64Str);
        };
        reader.readAsDataURL(file);
        const data = new FormData();
        data.append("file", file);
        console.log(data);
        try {
          const res = await axios.post("/api/upload", data);
          const arr: IRect[] = res.data;
          console.log(arr);
          if (arr.length > 0) {
            setStatus(Status.res_ok);
            setMsg({
              type: MsgType.success,
              text: `找到 ${arr.length} 个`
            })
          } else {
            setStatus(Status.res_empty);
            setMsg({
              type: MsgType.error,
              text: "not found"
            })
          }
          setRects(arr);
          setStatus(Status.res_empty)
        } catch (e) {
          setStatus(Status.res_err)
          setMsg({
            type: MsgType.error,
            text: (e as Error).message
          })
        }
      } else {
        setStatus(Status.img_err)
        setMsg({
          type: MsgType.error,
          text: "image type error"
        })
      }
    });
  };
  return (
    <div className="App">
      <header className="App-header">
        <Dropzone onDrop={onDrop}>
          {({ getRootProps, getInputProps }: any) => (
            <section>
              <div {...getRootProps()}>
                {/* <input {...getInputProps()} /> */}
                <div className="img-pan">
                  <img src={src} />
                  {rects.map((rect: IRect, index: number) => {
                    return (
                      <div key={index}>
                        <Rect
                          x={rect.position.x}
                          y={rect.position.y}
                          w={rect.position.w}
                          h={rect.position.h}
                          text={rect.text}
                        />
                        <Text
                          x={rect.position.x}
                          y={rect.position.y}
                          w={rect.position.w}
                          h={rect.position.h}
                          text={rect.text}
                        />
                      </div>
                    );
                  })}
                  <p></p>
                </div>
                {src === "" && <p>Drag 'n' drop some files here</p>}
              </div>
            </section>
          )}
        </Dropzone>
        {status === Status.uploading && (
          <div className="loading">
            <ReactLoading type={"bars"} color={"#fff"} />
          </div>
        )}
        <Snackbar open={status === Status.res_err || status === Status.img_err || status === Status.res_empty} autoHideDuration={6000} >
          <Alert severity={msg.type} onClose={() => {
            setStatus(Status.ready)
          }}>
            {msg.text}
          </Alert>
        </Snackbar>
      </header>
    </div>
  );
}
export default App;

相应css:

.img-pan{
  position: relative;
}
div[tabindex="0"]{
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading{
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100;
  right: 0;
  bottom: 0;
  background: #000;
  z-index: 999;
  opacity: 0.8;
  display: flex;
  align-items: center;
  justify-content: center;
}

最后效果:

git地址:

git.code.tencent.com/where-is-pe…