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

🐱前言

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

🤔️技术选择

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

具体费用如下:

💻百度控制台创建应用

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

创建完毕后我们就拥有调用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;
      },
    );
  });

👀效果展示

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

🧐预览地址

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


相关推荐
qq229511650211 分钟前
微信小程序的汽车维修预约管理系统
微信小程序·小程序·汽车
我要洋人死25 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人36 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人37 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR42 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香44 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍