垃圾分类识别功能实现

功能需求与分析

需求

用户可选择拍照识别或者上传相册内图片,实现对照片中垃圾的识别。

分析

前端上传图片到后端,调用阿里云垃圾识别api,返回数据给前端呈现

代码实现部分

前端代码
所需要用到的组件与api
  1. uniapp camera 组件实现拍照功能
  2. uni.chooseImage api 实现从相册中选择图片
  3. uni.uploadFile api 实现图片上传
代码部分
总体代码
<template>
   <view>
   	<camera device-position="back" flash="auto" @error="error" style="width: 100%; height: 1000upx;">
   		<cover-image src="../../static/img/scan-frame/scan-img.png" class="scan-img"></cover-image>
   	</camera>
   	<view class="scan-text"><text>请将想识别的垃圾放置白色框内</text></view>
   	<!-- 		<button type="primary" @click="takePhoto">拍照</button> -->
   	<view style="margin-left: 611rpx;margin-top: 55rpx;">
   		<image src="../../static/img/garbage/photo.png" style="width: 100rpx;height: 80rpx;" @click="takeAlbum">
   		</image>
   		<view style="margin-left: 19rpx;">
   			<text style="color:#678D5D">相册</text>
   		</view>
   	</view>
   	<view class="uni-button-group">
   		<button class="uni-button" @click="takePhoto" :styles="{'borderColor':'#678D5D'}">确定</button>
   	</view>
   	<orange-fullloading :loadicon="loadicon" text="识别中,请稍等" :loadshow="loadshow"></orange-fullloading>
   	<orange-fullloading :loadicon="erricon" text="抱歉未能识别该物品" :loadshow="errshow"></orange-fullloading>
   </view>
</template>

<script>
   const app = getApp()
   export default {
   	data() {
   		return {
   			loadicon: '/static/img/garbage/xiaow.png',
   			erricon: '/static/img/garbage/xiaoerr.png',
   			src: "",
   			loadshow: false,
   			errshow: false,
   			garbageInfo: {},
   			header: {
   				'app-id': uni.getAccountInfoSync().miniProgram.appId,
   				'third-session': getApp().globalData.thirdSession != null ? getApp().globalData
   					.thirdSession : ''
   			},
   			path: app.globalData.config.basePath + '/weixin/api/ma/classify'
   		}
   	},
   	onShow() {
   		this.loadshow = false
   		this.errshow = false
   		//app.initPage().then((res) => {});
   	},
   	onLoad() {
   		this.loadshow = false
   		this.errshow = false
   		app.initPage().then((res) => {});
   	},
   	methods: {
   		//拍照上传
   		takePhoto() {
   			const ctx = uni.createCameraContext();
   			let that = this;
   			ctx.takePhoto({
   				quality: 'high',
   				success: (res) => {
   					console.log(res)
   					that.src = res.tempImagePath
   					console.log(that.src)
   					console.log(that.path)
   					//上传图片
   					that.loadshow = true
   					uni.uploadFile({
   						url: that.path, //图片上传接口
   						filePath: that.src,
   						name: 'file',
   						header: that.header,
   						success: (res) => {
   							console.log(result)
   							//that.garbageInfo = result.data[0]
   							//失败处理
   							let result = JSON.parse(res.data)
   							console.log(result)
   							if (result.code == 500 || result.data[0].category == "非生活垃圾" ||
   								result.data[0].rubbishScore == 0.0 || result.data[0]
   								.categoryScore == 0.0) {
   								that.loadshow = false
   								that.errshow = true
   								setTimeout(function() {
   									that.errshow = false
   									//跳转回页面
   									uni.redirectTo({
   										url: '/pages/identify/scan-frame'
   									});
   								}, 4000);
   							} else {
   								that.garbageInfo = result.data[0]
   								uni.navigateTo({
   									url: './detail?garbageInfo=' + encodeURIComponent(
   											JSON
   											.stringify(that.garbageInfo)) +
   										'&src=' + that.src
   								})
   							}
   						},
   						fail(err) {
   							console.log(err)
   							uni.showToast({
   								icon: 'error',
   								title: '抱歉未能识别该物品',
   								duration: 2000
   							})
   						}
   					});
   					//有路径

   					//返回调用页面并把图片URL传递过去
   					// let pages = getCurrentPages();
   					// let prevPage = pages[pages.length - 2]; 
   					// prevPage.setData({
   					// 	"image": that.src,
   					// })
   					// uni.navigateBack();

   					/* 调用页面获取图片URL方法 */
   					/* let pages = getCurrentPages();
   					let currPage = pages[pages.length-1];
   					if(typeof(currPage.data.image) != undefined && currPage.data.image != null){
   						console.log('获取图片:', currPage.data.image)
   					} */
   				}
   			});
   		},
   		error(e) {
   			console.log(e.detail);
   		},
   		//相册选择图片 一张
   		takeAlbum() {
   			let that = this;
   			that.loadshow = true
   			uni.chooseImage({
   				count: 1,
   				sourceType: ['album'], //从相册中获取
   				success: function(res) {
   					that.loadshow = true
   					console.log(res)
   					that.src = res.tempFilePaths[0]
   					// uni.showLoading({title: '加载中',mask:true})
   					console.log(that.src)
   					//上传图片
   					uni.uploadFile({
   						url: that.path, //图片上传接口
   						filePath: that.src,
   						name: 'file',
   						header: that.header,
   						success: (res) => {
   							console.log(res)
   							//返回的垃圾识别信息
   							
   							let result = JSON.parse(res.data)
   							console.log(result)

   							if (result.code == 500 || result.data[0].category == "非生活垃圾" ||
   								result.data[0].rubbishScore == 0.0 || result.data[0]
   								.categoryScore == 0.0) {
   								that.loadshow = false
   								that.errshow = true
   								setTimeout(function() {
   									that.errshow = false
   									//跳转回页面
   									uni.redirectTo({
   										url: '/pages/identify/scan-frame'
   									});
   								}, 4000);
   							} else {
   								that.garbageInfo = result.data[0]
   								uni.navigateTo({
   									url: './detail?garbageInfo=' + encodeURIComponent(
   											JSON
   											.stringify(that.garbageInfo)) +
   										'&src=' + that.src
   								})
   							}
   						},
   						fail(err) {
   							console.log(err)
   							uni.showToast({
   								icon: 'error',
   								title: '抱歉未能识别该物品',
   								duration: 2000
   							})

   						}
   					});
   					uni.hideLoading()
   				},
   				fail: function(err) {
   					that.loadshow = false
   					uni.showToast({
   						icon: 'error',
   						title: '图片上传错误',
   						duration: 2000
   					})
   				}
   			});
   		}
   	}
   }
</script>

<style>
   .scan-img {
   	opacity: 0.4;
   	width: 100%;
   	height: 1000upx;
   }

   .scan-text {
   	font-size: 16px;
   	text-align: center;
   	line-height: 60rpx;
   	font-weight: 700;
   	color: #678D5D;
   }

   .uni-button-group {
   	/* 		margin-top: 50px; */
   	/* #ifndef APP-NVUE */
   	display: flex;
   	/* #endif */
   	justify-content: center;
   	margin-top: -77rpx;;
   }

   .uni-button {
   	width: 287rpx;
   	padding: 12px 20px;
   	font-size: 43rpx;
   	border-radius: 12px;
   	line-height: 1;
   	margin: 0;
   	background-color: #678D5D;
   	color: white;

   }
</style>

1.使用到的属性
data() {
    return {
		//加载图片
        loadicon: '/static/img/garbage/xiaow.png',
		//加载失败图片
        erricon: '/static/img/garbage/xiaoerr.png',
        src: "",
		//加载中是否显示
        loadshow: false,
		//出现错误是否显示
        errshow: false,
		//后端返回的识别出的垃圾信息
        garbageInfo: {},
		//请求头
        header: {
            'app-id': uni.getAccountInfoSync().miniProgram.appId,
            'third-session': getApp().globalData.thirdSession != null ? getApp().globalData.thirdSession: ''
        },
		//上传接口
        path: app.globalData.config.basePath + '/weixin/api/ma/classify'
    }
},


2. 拍照上传部分
takePhoto() {
    const ctx = uni.createCameraContext();
    let that = this;
    ctx.takePhoto({
        quality: 'high',
        success: (res) = >{
            console.log(res) that.src = res.tempImagePath console.log(that.src) console.log(that.path)
            //上传图片
            that.loadshow = true uni.uploadFile({
                url: that.path,
                //图片上传接口
                filePath: that.src,
                name: 'file',
                header: that.header,
                success: (res) = >{
                    console.log(result)
                    //that.garbageInfo = result.data[0]
                    //失败处理
                    let result = JSON.parse(res.data) console.log(result) if (result.code == 500 || result.data[0].category == "非生活垃圾" || result.data[0].rubbishScore == 0.0 || result.data[0].categoryScore == 0.0) {
                        that.loadshow = false that.errshow = true setTimeout(function() {
                            that.errshow = false
                            //跳转回页面
                            uni.redirectTo({
                                url: '/pages/identify/scan-frame'
                            });
                        },
                        4000);
                    } else {
                        that.garbageInfo = result.data[0] uni.navigateTo({
                            url: './detail?garbageInfo=' + encodeURIComponent(JSON.stringify(that.garbageInfo)) + '&src=' + that.src
                        })
                    }
                },
                fail(err) {
                    console.log(err) uni.showToast({
                        icon: 'error',
                        title: '抱歉未能识别该物品',
                        duration: 2000
                    })
                }
            });

3. 从相册中选择图片并上传
//相册选择图片 一张
takeAlbum() {
    let that = this;
    that.loadshow = true uni.chooseImage({
		//最大选取数量
        count: 1,
        sourceType: ['album'],
        //从相册中获取
        success: function(res) {
			
            that.loadshow = true console.log(res) 
			//获取第一张图片src
			that.src = res.tempFilePaths[0]
            // uni.showLoading({title: '加载中',mask:true})
            console.log(that.src)
            //上传图片
            uni.uploadFile({
                url: that.path,
                //图片上传接口
                filePath: that.src,
                name: 'file',
                header: that.header,
                success: (res) = >{
                    console.log(res)
                    //返回的垃圾识别信息
                    let result = JSON.parse(res.data) 
					//失败处理
                    if (result.code == 500 || result.data[0].category == "非生活垃圾" || result.data[0].rubbishScore == 0.0 || result.data[0].categoryScore == 0.0) {
                        that.loadshow = false that.errshow = true setTimeout(function() {
                            that.errshow = false
                            //跳转回页面
                            uni.redirectTo({
                                url: '/pages/identify/scan-frame'
                            });
                        },
                        4000);
                    } else {
                        that.garbageInfo = result.data[0] uni.navigateTo({
                            url: './detail?garbageInfo=' + encodeURIComponent(JSON.stringify(that.garbageInfo)) + '&src=' + that.src
                        })
                    }
                },
                fail(err) {
                    console.log(err) uni.showToast({
                        icon: 'error',
                        title: '抱歉未能识别该物品',
                        duration: 2000
                    })

                }
            });
            uni.hideLoading()
        },
		//选择失败处理
        fail: function(err) {
            that.loadshow = false uni.showToast({
                icon: 'error',
                title: '请选择图片',
                duration: 2000
            })
        }
    });
后端代码
所用到的api
  1. 阿里云oss存储
  2. 阿里云opeanApi
代码部分
1.总体代码
package com.garbage.web.api;  
  
import com.alibaba.fastjson.JSONArray;  
import com.aliyun.imagerecog20190930.models.ClassifyingRubbishRequest;  
import com.aliyun.imagerecog20190930.models.ClassifyingRubbishResponse;  
import com.garbage.common.core.domain.AjaxResult;  
import com.garbage.common.utils.ClassifyingRubbish.ClassifyingRubbish;  
import com.garbage.mall.service.OssService;  
import com.sun.xml.internal.ws.client.ClientTransportException;  
import lombok.AllArgsConstructor;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.PostMapping;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  
import org.springframework.web.multipart.MultipartFile;  
  
import javax.websocket.server.PathParam;  
import java.io.IOException;  
import java.util.List;  
import java.util.Map;  
  
/**  
 * 垃圾分类识别  
 *  
 * @author SY  
 * @date 2022-04-16 15:21:22  
 */
@Slf4j  
@RestController  
@AllArgsConstructor  
@RequestMapping("/weixin/api/ma/classify")  
public class ClassifyingRubbishApi {  
   //上传oss工具  
 @Autowired  
 private OssService ossService;// AccessKey  
  
 private static String accessKey = your accessKey;  
 // AccessKeySecret  
 private static String accessKeySecret = your accessKeySecret;  
  
  
  
 @PostMapping  
 public AjaxResult classify(@PathParam(value = "file") MultipartFile file) {  
        try {  
            //上传到云桶  
 String url = ossService.uploadFile(file);  
 //创建代理  
 log.info("创建代理");  
 com.aliyun.imagerecog20190930.Client client = ClassifyingRubbish.createClient(accessKey, accessKeySecret);  
 ClassifyingRubbishRequest classifyingRubbishRequest = new ClassifyingRubbishRequest().setImageURL(url);  
 log.info("获取结果");  
 ClassifyingRubbishResponse resp = client.classifyingRubbish(classifyingRubbishRequest);  
 log.info(resp.toMap().toString());  
 System.out.println(resp.toMap());  
 log.info("创建代理oss");  
  
 //打印结果  
 log.info(client.classifyingRubbish(classifyingRubbishRequest).getBody().getData().toString());  
  
 //获取结果  
 log.info("获取返回值");  
 List list = client.classifyingRubbish(classifyingRubbishRequest).getBody().getData().getElements();  
 JSONArray jsonArray = (JSONArray) JSONArray.toJSON(list);   
  
 return AjaxResult.success(list);  
 } catch (ClientTransportException e) {  
            e.printStackTrace();  
 } catch (IOException e) {  
            e.printStackTrace();  
 } catch (Exception e) {  
            e.printStackTrace();  
 }  
        return AjaxResult.error();     
}  
  
  
}
实现oss上传
  1. 引入依赖
<!-- 阿里云oss依赖 -->  
<dependency>  
 <groupId>com.aliyun.oss</groupId>  
 <artifactId>aliyun-sdk-oss</artifactId>  
 <version>3.1.0</version>  
</dependency>  
<!-- 日期工具栏依赖 -->  
<dependency>  
 <groupId>joda-time</groupId>  
 <artifactId>joda-time</artifactId>  
 <version>2.10.1</version>  
</dependency>
  1. 在yml中写aliyun配置
# 阿里云oss配置  
aliyun:  
  oss:  
    file:  
      endpoint: your endpoint
      keyid: your key  
      keysecret: your secret 
      bucketname: your bucketname
  1. 写配置类
package com.garbage.mall.util;  
  
import org.springframework.beans.factory.InitializingBean;  
import org.springframework.beans.factory.annotation.Value;  
import org.springframework.stereotype.Component;  
  
/**  
 * 常量类,读取配置文件application.properties中的配置  
 */  
@Component  
//@PropertySource("classpath:application.properties")  
//InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。
public class ConstantPropertiesUtils implements InitializingBean {  
  //从yml文件中读取配置
    @Value("${aliyun.oss.file.endpoint}")  
    private String endpoint;  
  
 @Value("${aliyun.oss.file.keyid}")  
    private String keyId;  
  
 @Value("${aliyun.oss.file.keysecret}")  
    private String keySecret;  
  
  
 @Value("${aliyun.oss.file.bucketname}")  
    private String bucketName;  
  
 public static String END_POINT;  
 public static String ACCESS_KEY_ID;  
 public static String ACCESS_KEY_SECRET;  
 public static String BUCKET_NAME;  
 //@Value不能在static 字段上使用
//在初始化bean的时候为静态变量赋值
 @Override  
 public void afterPropertiesSet() throws Exception {  
 END_POINT = endpoint;  
 ACCESS_KEY_ID = keyId;  
 ACCESS_KEY_SECRET = keySecret;  
 BUCKET_NAME = bucketName;  
 }  
}
  1. Service类
public interface OssService {  
    //上传到oss
 String uploadFile(MultipartFile file);  
}
  1. ServiceImpl类
@Service  
public class OssServiceImpl implements OssService {  
    //上传图片到oss  
 @Override  
 public String uploadFile(MultipartFile file) {  
 // 工具类获取值  
 String endpoint = ConstantPropertiesUtils.END_POINT;  
 String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;  
 String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;  
 String bucketName = ConstantPropertiesUtils.BUCKET_NAME;  
  
 try {  
            // 创建OSS实例。  
 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);  
  
 //获取上传文件输入流  
 InputStream inputStream = file.getInputStream();  
 //获取文件名称  
 String fileName = file.getOriginalFilename();  
  
 //1 在文件名称里面添加随机唯一的值  
 String uuid = UUID.randomUUID().toString().replaceAll("-","");  
 
 fileName = uuid + fileName;  
  
 //2 把文件按照日期进行分类  
 //获取当前日期  
 String datePath = new DateTime().toString("yyyy/MM/dd");  
 //拼接  
 fileName = datePath+"/"+fileName;  
  
 //调用oss方法实现上传  
 //第一个参数 Bucket名称  
 //第二个参数  上传到oss文件路径和文件名称 aa/bb/1.jpg
 //第三个参数  上传文件输入流  
 ossClient.putObject(bucketName,fileName,inputStream);  
  
 // 关闭OSSClient
 ossClient.shutdown();  
  
 //把上传之后文件路径返回  
 //需要把上传到阿里云oss路径手动拼接出来  
 String url = "https://"+bucketName+"."+endpoint+"/"+fileName;  
 return url;  
 }catch(Exception e) {  
            e.printStackTrace();  
 return null; }  
    }

引入ClassifyingRubbish
/**  
 * 使用AK&SK初始化账号Client  
 * @param accessKeyId  
 * @param accessKeySecret  
 * @return Client  
 * @throws Exception  
 */public static com.aliyun.imagerecog20190930.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {  
    Config config = new Config()  
            // 您的AccessKey ID  
 .setAccessKeyId(accessKeyId)  
            // 您的AccessKey Secret  
 .setAccessKeySecret(accessKeySecret);  
 // 访问的域名  
 config.endpoint = "imagerecog.cn-shanghai.aliyuncs.com"; 
//返回创建好的识别类
 return new com.aliyun.imagerecog20190930.Client(config);  
}

  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值