微信小程序——简单饮食推荐(一)

·  阅读 625
微信小程序——简单饮食推荐(一)

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

一、总体界面效果

图片标题 图片标题

图片标题 图片标题

二、功能实现

(一)拍照识别模块

1、模块简介

该模块主要调用了百度AI菜品识别的接口,项目可根据用户上传的图片来判断图片中菜品的名称和菜品的热量。 在wxml页面中,为了使得菜品图片呈现的更鲜艳,加了一个具有小圆点边框的背景,这里使用css样式来实现;中间部分是两个图片按钮,分别链接到选择图片或拍照函数和菜品识别函数,考虑到如果直接使用按钮样式不太好看,这里使用的是图片加文字的样式来呈现;最下方是根据用户的选择利用一个区域来呈现菜品的详情,当用户确认要查看菜品详情时就会在下方显示出来。

2、构思创意

在该模块中,创意点如下: 创意点一是调用了百度大脑的图片识别接口,具体调用的就是百度AI菜品识别的API接口。 创意点二是为了显示界面的美观,在图片显示的周围增添了一圈小圆点的背景。在你上传完图片并识别完成后,校小圆点会有规律的闪烁。

3、设计思路分析

要想完成该模块并实现菜品识别的相应功能,必须要解决下面的这几个问题:

  • 选择哪个图片识别的API
  • API接口的连接
  • 如何上传图片
  • 图片转码问题
  • API调用成功后返回数据的处理
  • 整体界面设计

4、实现过程

4.1 图片识别API平台

经查找相关的资料,了解到的可以提供图片识别API的平台有百度智能云,腾讯AI发放平台,华为HiAI能力开放平台,旷世 Face++。

4.2 各个图片识别API平台的相关介绍

4.2.1百度智能云

百度智能云作为中国AI的先行者,百度在深度学习、自然语言处理、语音技术和视觉技术等核心AI技术领域优势明显,百度大脑、飞桨深度学习平台则是AI产业基础设施。 百度全球AI专利申请量位列中国第一,并在语音识别、自然语言处理、知识图谱和自动驾驶四个细分领域排名国内第一,展示出AI新基建领军者深厚的技术底蕴和敏捷的创新能力。 百度大脑AI大生产平台已对外开放250+项核心AI能力,日调用1万亿次,服务190万+开发者;作为AI大生产平台的基础底座,飞桨深度学习平台定制化训练平台上服务企业8.4万家,发布模型数量23万+个。

4.2.2腾讯AI开放平台

接口包含OCR、人体与人脸识别、物体识别、图片特效、图片识别、敏感信息审核、闲聊机器人、基础文本分析、语义解析、语音识别 等等,有 PHP 参考例程。

4.2.3华为HiAI能力开放平台

接口包含人脸识别、人体识别、图片识别、图像分辨率、场景识别、文档检测矫正、人像分割、视频语音等等。有详细的开发指南,但是其针对的是 Android 手机平台的开发。

4.2.4旷世 Face++

旷世Face++的API包括人脸识别,人体识别,人像处理,文字识别,图像识别。

4.3图片识别API平台选择

综合考虑,最终选择百度智能云作为图像识别API的平台。 在图像识别方面的有如下的接口:

接口名称接口能力简要描述
图像主体检测识别图像中的主体具体坐标位置。
通用物体和场景识别高级版识别图片中的场景及物体标签,支持10w+标签类型。
菜品识别检测用户上传的菜品图片,返回具体的菜名、卡路里、置信度信息。
自定义菜品识别入库自定义的单菜品图,实现上传多菜品图的精准识别,返回具体的菜名、位置、置信度
logo商标识别识别图片中包含的商品LOGO信息,返回LOGO品牌名称、在图片中的位置、置信度。
动物识别检测用户上传的动物图片,返回动物名称、置信度信息。
植物识别检测用户上传的植物图片,返回植物名称、置信度信息。
果蔬食材识别检测用户上传的果蔬类图片,返回果蔬名称、置信度信息。
地标识别检测用户上传的地标图片,返回地标名称。
红酒识别识别图像中的红酒标签,返回红酒名称、国家、产区、酒庄、类型、糖分、葡萄品种等信息。
货币识别识别图像中的货币类型,返回货币名称、代码、面值、年份信息,可识别百余种国内外常见货币。

在这里可以很明显的看到有一个在我们小程序的菜品识别模块完全可以利用的API,就是菜品识别API,官网显示该接口可以检测用户上传的菜品图片,返回具体的菜名、卡路里、置信度信息,这正式我们想要的功能。

4.4搭建菜品识别的API接口

4.4.1注册百度AI开放平台

登入百度智能云后,同意相关的条款,然后在管理中心创建应用。 image.png 创建完应用后如下图所示: image.png

这里的API Key,Secret Key在后面进行API连接调用的时候会用得到。

4.2.2API调用

官方给出的API的调用有两种方式:

image.png

image.png

(注:这里我使用的方式一) 用户access_token的获取。 官方文档已经给出了比较详细的说明,我们需要提供client_id和client_secret来进行获取,将这两个数据传递到官方给的api中,就可以获取到access_token,它的有效期为一个月,我们可以每次重新获取,也可以获取之后将其设置为常量,不再调用获取方法。

image.png 获取access_token的关键代码如下:

1.	getToken: function (callback) {  
2.	    wx.request({  
3.	      url: 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=j8k8rz1EqXdPIfwjwQdEbwMG&client_secret=Tttbs1hLDQw0nKG6ecy5znFBGdv7sWGT',  
4.	      data: {},  
5.	      header: {  
6.	        'content-type': 'application/x-www-form-urlencoded'  
7.	      },  
8.	      success(res) {  
9.	        var token = res.data.access_token;  
10.	          
11.	        return callback(token);  
12.	      }  
13.	    });  
14.	  },  

复制代码

在这里的url填写如下:

image.png 这里的事件函数利用了wx.request方法,请求百度菜品识别服务地址url,请求的方式是通过POST发送请求的。

4.5图片上传与识别

用户上传图片要进行处理为base64格式编码,这样才可以传递给百度AI的API进行处理,用户上传图片可以直接使用wx.chooseImage()方法,图片上传成功之后可以获取到图片的临时路径,而临时路径的图片必须获取到才能处理为base64格式编码,这里使用wx.getFileSystemManager().readFile()方法,通过提供图片路径和编码格式来获取图片base64格式编码,这样就可以将编码之后的数据传递到百度ai的菜品api中进行处理。 这部分的代码实现如下: js代码:

1.	chooseImg: function () {//图片上传处理函数  
2.	    that.setData({  
3.	      ishow: false,  
4.	      content: ''  
5.	    });  
6.	    wx.chooseImage({  
7.	      count: 1,  
8.	      sizeType: ['original', 'compressed'],  
9.	      sourceType: ['album', 'camera'],  
10.	      success(res) {  
11.	        const tempFilePaths = res.tempFilePaths[0];  
12.	        that.getB64ByUrl(tempFilePaths);  
13.	        that.setData({  
14.	          img: tempFilePaths  
15.	        });  
16.	      }  
17.	    })  
18.	  }  

复制代码

在wxml中设置“拍照/选取图片”图片按钮绑定该函数:

1.	<image style="margin-left:100rpx" class="buttonimage" src="../../images/1.png" mode="aspectFit"  
2.	bindtap="chooseImg">

复制代码

在wxml中设置“识别菜品”图片按钮绑定函数foodTap:

1.	<image style="margin-right:0rpx" class="buttonimage" src="../../images/2.png" mode="aspectFit" bindtap="foodTap">  
2.	      </image>  

复制代码

foodTap函数:

1.	foodTap: function (e) {  
2.	    const imgB64 = that.data.imgB64;  
3.	    if (!imgB64) {  
4.	      wx.showToast({  
5.	        title: '请上传图片',  
6.	      })  
7.	      return;  
8.	    };  
9.	    that.twinkle()  
10.	    that.getToken(function (token) {  
11.	      that.getResult(token);  
12.	    });  
13.	  }  

复制代码

4.6从API接口中获取菜品信息

获取菜品的名称,卡路里,还有置信度,同时用console设置调试器的输出值,在运行后的调试窗口输出名称,卡路里,还有置信度。 getResult函数:

1.	getResult: function (token) {  
2.	    wx.request({  
3.	      url: 'https://aip.baidubce.com/rest/2.0/image-classify/v2/dish?access_token=' + token,  
4.	      method: "POST",  
5.	      data: {  
6.	        image: that.data.imgB64,  
7.	        baike_num: 1,  
8.	        top_num: 1  
9.	      },  
10.	      header: {  
11.	        'content-type': 'application/x-www-form-urlencoded' // 默认值  
12.	      },  
13.	      success(res) {  
14.	        console.log(res.data.result[0].baike_info);  
15.	        that.setData({  
16.	          dishName: res.data.result[0].name,  
17.	          calorie: res.data.result[0].calorie,  
18.	          probability: res.data.result[0].probability,  
19.	        });  
20.	        console.log('***************SUCCESS***********')  
21.	        console.log('菜名:'+that.data.dishName);  
22.	        console.log('卡路里:'+that.data.calorie);  
23.	        console.log('置信度:'+that.data.probability);  
24.	        console.log(res.data);  
25.	        wx.showModal({  
26.	          title: '菜品为' +that.data.dishName,  
27.	          content: '热量为' + that.data.calorie+'是否查看详情',  
28.	          success(res){  
29.	            if (res.confirm) {  
30.	              that.setData({ishow:true})   
31.	            }  
32.	            else{  
33.	              return  
34.	            }  
35.	          }  
36.	            
37.	        })  
38.	         
39.	      }  
40.	    });  
41.	  } 

复制代码

4.7小圆点边框代码的实现

闪点效果的实现,这里是参考一个大转盘抽奖的效果,圆点的位置是存储到数组中,wxml中对数组进行遍历渲染,圆点闪现利用了计时器setInterval的方法,每隔0.5秒更换一下圆点的背景色来实现。 js代码实现:

1.	onLoad: function (options) {  
2.	    that = this;  
3.	    var leftCircle = 7.5;  
4.	    var topCircle = 7.5;  
5.	    var circleList = [];  
6.	    for (var i = 0; i < 24; i++) {  
7.	      if (i == 0) {  
8.	        topCircle = 15;  
9.	        leftCircle =  
10.	 15;  
11.	      } else if (i < 6) {  
12.	        topCircle = 7.5;  
13.	        leftCircle = leftCircle + 102.5;  
14.	      } else if (i == 6) {  
15.	        topCircle = 15  
16.	        leftCircle = 620;  
17.	      } else if (i < 12) {  
18.	        topCircle = topCircle + 94;  
19.	        leftCircle = 620;  
20.	      } else if (i == 12) {  
21.	        topCircle = 565;  
22.	        leftCircle = 620;  
23.	      } else if (i < 18) {  
24.	        topCircle = 570;  
25.	        leftCircle = leftCircle - 102.5;  
26.	      } else if (i == 18) {  
27.	        topCircle = 565;  
28.	        leftCircle = 15;  
29.	      } else if (i < 24) {  
30.	        topCircle = topCircle - 94;  
31.	        leftCircle = 7.5;  
32.	      } else {  
33.	        return  
34.	      }  
35.	      circleList.push({ topCircle: topCircle, leftCircle: leftCircle });  
36.	    }  
37.	    that.setData({  
38.	      circleList: circleList  
39.	    })  
40.	  },  
41.	  twinkle:function(){//设置一个定时器  
42.	    setInterval(function () {  
43.	      if (that.data.colorCircleFirst == '#FFDF2F') {  
44.	        that.setData({  
45.	          colorCircleFirst: '#FE4D32',  
46.	          colorCircleSecond: '#FFDF2F',  
47.	        })  
48.	      } else {  
49.	        that.setData({  
50.	          colorCircleFirst: '#FFDF2F',  
51.	          colorCircleSecond: '#FE4D32',  
52.	        })  
53.	      }  
54.	    }, 500)  
55.	  }  

复制代码

wxml:

1.	<view class="box">  
2.	  <view class="container-out">  
3.	    <view class="circle" wx:for="{{circleList}}" wx:key="key"  
4.	      style="top:{{item.topCircle}}rpx;left:{{item.leftCircle}}rpx;background-color: {{(index%2==0)?colorCircleFirst:colorCircleSecond}};">  
5.	    </view>  
6.	    <view class="container-in">  
7.	      <image class="image" src="{{img}}" mode='aspectFit' />  
8.	    </view>  
9.	  </view>  

复制代码

5、外观设计

5.1存放图片的外框设计:

这部分的wxml关键代码啊如下 image.png 这部分的最外层view的wxss属性设置如下 image.png

这样这部分的实现效果就如下图所示

image.png

5.2图片按钮的添加

这部分的wxml关键代码如下

image.png

其中的图标的获取是从阿里巴巴矢量图标库获取的。 然后在wxss中设置对应的view属性,实现的效果如下

image.png

6、运行效果

点击“拍照/选取按钮”,选择实现存储好的测试图片。

image.png

点击“识别菜品”按钮:

image.png

识别出菜品为“宫保鸡丁”:

image.png

点击“确定”,将菜品详情在下面显示出来:

image.png

查看调试器的console输出值:

image.png

7、其他模块实现以及各个部分的关系

通过菜品识别这一模块可以获取到某一个菜品的名称、热量。获取到这些数据之后可以和在“个人数据”界面的数据进行汇总运算,从而得出当天你还可以摄入的食物热量。

(二)订餐模块实现

点击链接跳转:juejin.cn/post/712827…

(三)转盘选餐模块

待更新...

(四)个人数据模块

待更新...

小程序功能关系图:

image.png

三、小程序体验版二维码

image.png

分类:
前端
收藏成功!
已添加到「」, 点击更改