一个小猪咪🐱品种鉴定小工具

🐱前言

今日突发奇想给自家小猪咪做一个品种血统鉴定小工具看看猪咪继承了哪些血统,毕竟小猪咪到家这么久了都不知道他继承了那只猪咪的基因~~

🤔️技术选择

目前调研了多个图片识别,感觉只有百度的做的最好,所以我们将使用百度的图像识别对小猪咪进行血统鉴定

具体费用如下:

💻百度控制台创建应用

首先创建一个应用,由于我们只使用了动物识别功能所以只需要选择动物识别即可

创建完毕后我们就拥有调用api的接口的key了

🙏调试

之后有需要的话,我们可以在控制台中对接口进行在线调试

✍️代码编写

接下来我们开始编写api接口的代码,用于前端的调用

接口说明

百度接口api限制图片最大只能是4m,所以我们在调用接口的时候需要先对图片进行压缩处理到4M以内,所以我们直接使用下面的SDK即可。

对于SDK使用的话就是直接把图片转为base64然后再调用SDK即可

使用Sharp压缩图片

由于我们使用的是 Nestjs ,所以相对来说简单一点,安装sharp ,推荐使用pnpm安装避免版本出错

pnpm install sharp

具体接口逻辑代码如下:

js 复制代码
import { Injectable } from '@nestjs/common';
import { InjectEntityManager } from '@nestjs/typeorm';
import { EntityManager } from 'typeorm';
import { IdentificationDto } from './dto/identification.dto';
import { imageClassify } from 'baidu-aip-sdk';
import fetch from 'node-fetch';
import { Identification } from './entities/identification.entity';
import * as dayjs from 'dayjs';
import { GetIdentificationDto } from './dto/getIdentification.dto';
import * as sharp from 'sharp';

@Injectable()
export class AnimalService {
  constructor() {
    // 设置APPID/AK/SK
    const APP_ID = 'xxxxxxxx';
    const API_KEY = 'xxxxxxxx';
    const SECRET_KEY = 'xxxxxxxx';

    // 新建一个对象,建议只保存一个对象调用服务接口
    this.client = new imageClassify(APP_ID, API_KEY, SECRET_KEY);
  }

  client: any;

  @InjectEntityManager()
  private entityManager: EntityManager;

  // 图片转buffer
  private async getImageBuffer(url: string): Promise<Buffer> {
    const response = await fetch(url);

    const buffer = Buffer.from(await response.arrayBuffer());

    return buffer;
  }

  // 压缩图片
  private async resizeImageIfNeeded(
    buffer: Buffer,
    maxSize: number,
  ): Promise<Buffer> {
    const originalSize = buffer.length;

    // 小于4m
    if (originalSize <= maxSize) {
      return buffer;
    }

    // 压缩图片
    const compressedImageBuffer = await sharp(buffer)
      .resize({
        // 图片宽
        width: 500,
        // 图片
        height: 500,
        // 保留纵横比,将图像大小调整为尽可能大,同时确保其尺寸小于或等于指定的尺寸
        fit: 'inside',
        // 不放大
        withoutEnlargement: true,
      })
      .toBuffer();

    return compressedImageBuffer;
  }

  // url转base64
  async urlToBase64(url: string): Promise<string> {
    const imageBuffer = await this.getImageBuffer(url);

    // 是否需要压缩
    const resizedBuffer = await this.resizeImageIfNeeded(imageBuffer, 2 * 1024);
    const base64String = resizedBuffer.toString('base64');

    return base64String;
  }

  // 动物识别
  async identification(data: IdentificationDto, userId: number) {
    // url转base64
    const image = await this.urlToBase64(data.url);

    // 如果有可选参数
    const options = {};
    // 返回预测得分top结果数,默认为6,相当于返回多少条结果
    options['top_num'] = '4';
    // 用于控制返回结果是否带有百科信息,若不输入此参数,则默认不返回百科结果;若输入此参数,会根据输入的整数返回相应个数的百科信息
    options['baike_num'] = '1';

    // 带参数调用动物识别
    try {
      const res = await this.client.animalDetect(image, options);

      if (!res.result) {
        return {
          code: -1,
          msg: '上传照片非动物',
        };
      }

      const result = res.result[0];

      if (result.name === '非动物') {
        return {
          code: -1,
          msg: '上传照片非动物',
        };
      }

      return {
        data: {
          list: res.result,
        },
      };
    } catch (error) {
      throw error;
    }
  }

接口入参代码如下:

js 复制代码
import { WINSTON_LOGGER_TOKEN } from 'src/winston/winston.module';
import {
  Controller,
  HttpStatus,
  HttpCode,
  HttpException,
  Inject,
  UseInterceptors,
  Post,
  Body,
  UseGuards,
  Headers,
} from '@nestjs/common';
import { InvokeRecordInterceptor } from 'src/invoke-record.interceptor';
import { AnimalService } from './animal.service';
import { IdentificationDto } from './dto/identification.dto';
import { LoginGuard } from 'src/login.guard';
import { RedisService } from '../redis/redis.service';

@Controller('animal')
@UseInterceptors(InvokeRecordInterceptor)
export class AnimalController {
  constructor(private readonly animalService: AnimalService) {}

  @Inject(WINSTON_LOGGER_TOKEN)
  private logger;

  @Inject(RedisService)
  private redisService: RedisService;

  // 动物识别
  @Post('identification')
  @UseGuards(LoginGuard)
  @HttpCode(HttpStatus.OK)
  async identification(
    @Body() data: IdentificationDto,
    @Headers() headers: Record<string, string>,
  ) {
    try {
      const token = headers.authorization.split(' ')[1];

      const redisToken = await this.redisService.get(token);
      const _redisToken = JSON.parse(redisToken);

      const res = await this.animalService.identification(data, _redisToken.id);

      return {
        data: {},
        ...res,
      };
    } catch (e) {
      this.logger.error(e, '动物识别错误');

      throw new HttpException(`服务器错误`, HttpStatus.BAD_REQUEST);
    }
  }
}

以上代码写完后就可以到前端进行接入了

✍️前端接入

前端直传到腾讯云cos,然后把url传入上面写的Nestjs接口

js 复制代码
 wx.chooseMedia({
    count: 1,
    mediaType: ['image'],
    sourceType: ['album', 'camera'],
    sizeType: ['compressed'],
    camera: 'back',
  }).then(async ({ tempFiles }) => {
    const file = tempFiles[0];

    loading.value = true;

    // uploadFile
    await uploadFile(
      {
        url: file.tempFilePath,
        type: 'animal',
        noMediaCheck: true,
      },
      async (url) => {
        const res = await identification({
          url: url,
        });

        if (res.code === 0) {
          identificationStore.setIdentification({
            cover: url,
            ...res.data,
          });
        }

        loading.value = false;
      },
      () => {
        loading.value = false;
      },
    );
  });

👀效果展示

以上代码写完后,最终的代码效果显示如下:

🧐预览地址

掘友们可扫描一下二维码可进行体验,进入小程序后点击小工具即可使用~~


相关推荐
cnsxjean2 小时前
SpringBoot集成Minio实现上传凭证、分片上传、秒传和断点续传
java·前端·spring boot·分布式·后端·中间件·架构
ZL_5673 小时前
uniapp中使用uni-forms实现表单管理,验证表单
前端·javascript·uni-app
沉浮yu大海3 小时前
Vue.js 组件开发:构建可重用且高效的 UI 块
前端·vue.js·ui
代码欢乐豆3 小时前
软件工程第13章小测
服务器·前端·数据库·软件工程
莘薪4 小时前
JQuery -- 第九课
前端·javascript·jquery
好青崧4 小时前
CSS 样式入门:属性全知晓
前端·css·tensorflow
尘浮生4 小时前
Java项目实战II基于Java+Spring Boot+MySQL的智能停车计费系统(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·mysql·微信小程序·maven
光头程序员4 小时前
工程化开发谷歌插件到底有爽
前端·react·工程化·前端工程化·谷歌插件
蒜蓉大猩猩4 小时前
Vue.js --- Vue3中其他组合式API
前端·javascript·vue.js·前端框架·node.js·html
铅华尽5 小时前
前端---HTML(一)
前端