通用后台管理系统
该系统主要结合Element组件编辑前端,后端实现业务逻辑,组成一个简单的前后端分离项目。
该部分介绍调用讯飞星火大模型的图片识别API功能的实现
前言:讯飞开放平台提供了一些免费的api供学习使用,可以包装进该项目中。例如图像识别api,前端上传图片,调用讯飞的api,然后返回结果。
讯飞开放平台地址:https://www.xfyun.cn/
该项目使用图像识别中的物体识别api:http://tupapi.xfyun.cn/v1/currency
文档链接:https://www.xfyun.cn/doc/image/object-recg/API.html
文档中有调用示例,选择java语言,因为识别的类别有点多,可以将下载的详细对照表写进数据库中,然后取结果的时候进行sql查询
前端
页面效果
在卡片中设置了一个选择框,选择不同的模型;模型的不同,卡片的内容显示也不一样。(目前只做了星火大模型)
识别效果:点击上传->选择图片文件->上传完成展示图片信息->显示识别结果
因为星火模型的要求,上传的图片大小要小于800kb。
前端代码
页面部分
<template>
<div>
<!--左侧 -->
<el-col :span="8" style="padding-right: 10px; padding-left: 50px">
<el-card class="select-card">
<span style="color: #1fb1ec">选择模型:</span>
<!--选择模型框-->
<div>
<el-select v-model="value" placeholder="select your model" @change="selectChanged">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div id="recPicApi" style="display: none">
<!--上传照片部分-->
<div id="upPicId" style="padding-top: 30px">
<span style="color: #1fb1ec">上传需要识别的图片:</span>
<el-upload
class="upload-demo"
:action=uploadPath
:file-list="fileList"
:on-success="uploadSuccess"
list-type="picture"
style="padding-top: 10px">
<el-button @click='uploadMethod' size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过800kb</div>
</el-upload>
</div>
<!--显示结果部分-->
<div id="resPicId" style="top: 50vh; position: absolute">
<span style="color: #1fb1ec; margin-top: 50px">识别结果为:</span>
<span class="pic-res">{
{ xunfeiRes }}</span>
</div>
</div>
</el-card>
</el-col>
<!--右侧 -->
<el-col :span="16" style="padding-right: 10px">
</el-col>
</div>
</template>
模型选择框
options: [{
value: '选项1',
label: 'ChatGPT'
}, {
value: '选项2',
label: '星火大模型'
}, {
value: '选项3',
label: '通义千问'
}, {
value: '选项4',
label: '文心一言'
}],
上传地址:uploadPath
该参数写上传文件的接口地址
上传成功:上传完成的时候调用后端物体识别的接口
uploadSuccess(response, file) {
console.log(file)
if (response.message === 'success') {
this.picMessage.filename = file.name;
console.log(file.name)
recognizePic({
params: {
...this.picMessage}}).then(({
data}) => {
console.log(data)
this.xunfeiRes = data.data
})
}
},
div盒和选择框中的值关联
selectChanged(value) {
console.log(value)
if (value === '选项2') {
document.querySelector("#recPicApi").style.display = 'block';
} else {
document.querySelector("#recPicApi").style.display = 'none';
}
}
后端部分
前端使用的后端接口:import {recognizePic} from '@/api'
上传图片:
当前项目中是将图片上传到linux服务器上,并通过配置nginx服务来建立文件服务器。当处于局域网时,nginx配置中暴露的文件夹路径可以访问,所以上传完成时,通过将文件地址写入数据库中,这样物体识别接口直接查询数据库取该文件路径即可。
@PostMapping("/upload")
public ResultHelper uploadFolder(MultipartFile file) {
try {
byte[] bytes = file.getBytes();
String filename = file.getOriginalFilename();
FTPUtil.sshSftp(bytes, filename);
String filepath = visitPath + filename;
pictureMapper.addPicture(filename, filepath);
return ResultHelper.success("上传成功");
} catch (Exception e) {
e.printStackTrace();
}
return ResultHelper.fail("上传失败");
}
识别图片:
前端上传完图片后,给识别接口提供一个文件名,这样通过文件名在数据库中找到可访问的图片路径。
@GetMapping("/recognize")
public ResultHelper recognizePic(@RequestParam(value = "filename", required = false) String filename) throws IOException {
// 根据文件名查找数据库中该文件名对应的图片地址
String filepath = recognizePic.getPicPath(filename);
log.info("该图片地址为:" + filepath);
// 根据科大讯飞接口识别图片
Map<String, String> header = xfBuildHttpHeader.buildHttpHeader(filename);
byte[] imageByteArray = FileUtil.read(filepath);
String result = HttpUtil.doPost(URL.getContent(), header, imageByteArray);
JSONObject jsonObject = JSON.parseObject(result);
String labelId = jsonObject.getJSONObject("data").getJSONArray("fileList").getJSONObject(0).getString("label");
String CHNName = recognizePic.searchCategoryByLabelId(Integer.parseInt(labelId));
log.info("接口调用结果:" + result);
log.info(filename + ",该图片预测结果为:" + CHNName);
return ResultHelper.success(CHNName);
}
http header方法,其中API_KEY、APPID从讯飞的开放平台获取。
public Map<String, String> buildHttpHeader(String imageName) throws UnsupportedEncodingException {
String curTime = System.currentTimeMillis() / 1000L + "";
String param = "{\"image_name\":\"" + imageName + "\"}";
String paramBase64 = new String(Base64.encodeBase64(param.getBytes("UTF-8")));
String checkSum = DigestUtils.md5Hex(API_KEY.getContent() + curTime + paramBase64);
Map<String, String> header = new HashMap<String, String>();
header.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
header.put("X-Param", paramBase64);
header.put("X-CurTime", curTime);
header.put("X-CheckSum", checkSum);
header.put("X-Appid", APPID.getContent());
return header;
}
FileUtil.read()
方法中在读取本地路径时可以用讯飞提供的代码,若是读取url路径的文件,需要改一下:
public static byte[] read(String filePath) throws IOException {
URL url = new URL(filePath);
InputStream in =new BufferedInputStream(url.openStream());
// InputStream in = Files.newInputStream(Paths.get(filePath)); // 原代码
byte[] data = inputStream2ByteArray(in);
in.close();
return data;
}