一款基于数据分析的智能饮食推荐

数据分析

  • 人体健康信息
    • 体重
    • 身高
    • 年龄
  • 菜品信息
    • 菜的名称
    • 卡路里
    • 蛋白质,脂肪等
    • 推荐的食用量
  • 某个人群对应的改善体质(减肥,塑性,增肌等)的方案
    • 菜谱
    • 运动方式

数据集和api

收集的资料

0、9种体质 //暂定
1、根据用户的体质来进行推荐菜谱与制定营养计划 —— 两种模式:9体模式和普通健身模式
2、用户可以随时输入自己当前吃的食物的名字与量 —— 随时记
3、动态爬虫——http://www.boohee.com/ 每种食材的卡路里等信息(优先kaggle)
4、卡路里累加器及其可视化、每天个人信息可视化
5、https://www.xinshipu.com/ 菜谱信息
6、通过照片提取出食物的卡路里等信息 百度api
7、http://www.zyyssl.com/cookbook.html //中药食材信息、药膳信息、9体、各种病针对的药膳
8、照片识菜帮
9、http://www.ttmeishi.com/CaiXi/YaoShan/ //病人对应的食谱
10、测算http://www.chinacaipu.com/zt/sccs.html 体质算法
11、http://www.chinacaipu.com/menu/jianya/ 特殊人群(压力之类的)

需求分析

  • 登陆、注册
  • 输入基本信息信息(身高、体重、性别、年龄)
    • 额外信息(工作、周均运动时间、睡眠段、九体、病史)
  • 针对没有填写额外信息的用户:选择减肥、增肌、塑形 、保持
  • 可视化(自己的信息和目标标准的比较、根据上述选择改变)每天的量(手环、手机计步器),近几天的曲线
  • 推荐菜谱:两个tab,一个定制菜谱,一个是随机智能推送
    • 单一菜推荐
    • 组合推荐
    • 一周大菜谱推荐(根据每日你自己加的一些信息动态改变)
    • 如果填了额外信息的,就是药膳推荐(一周药膳、周二普通、周三药膳。。。。)(注意可能不想减肥啥的)
  • 百度api->动态录入每顿饭的信息(防抖处理,这里吹牛逼算法,推测吃了多少卡路里),识别后把,动态改变一周定制计划
  • 做菜环节加入识菜帮所有功能,并加入详细食材信息卡路里等
  • 针对特殊人群,混到推荐里推送有利于健康的方法信息(敷黄瓜方法)
  • 特殊病人群体每日相关东西的摄取量的一个限定区间显示
  • ocr体检单信息录入
  • 针对照片中菜的数量分析吃了多少菜,包含多少卡路里
  • BMI小数
  • 需不需要为每个用户加一个用于存放一周定制的类
  • 模糊搜索
  • 食材对应menu

粉尘接触得多的 吃纤维素

  • 职业,某种病对各种物质的需求

病).xlsx

  • 修改职业,病(一些菜谱分类),体质 表

职业-菜谱.xlsx

职业.xlsx

  • 特殊职业(比如运动员)对身体素质(BMI)标准

职业 (bmi分类).xlsx

  • 早 中晚餐分类:
    • 早: 饼 粥 羹 面 奶

晚餐.xlsx
午餐.xlsx
早餐.xlsx

  • 加入季节方案(比如夏天就推荐防暑的,冬天推荐暖身的)
  • 补充菜谱: url补充缺失值,卡路里,热量,脂肪,蛋白质等
    1. - 爬卡路里时,原来的菜名是一列,新爬到的是一列,后面几列就是卡路里,脂肪等,注意数据规整
    2. - 爬不到就先空下,根据食材的信息计算
  • 浏览记录(post username和menuname和时间)

定制(蛋白质在100-200范围内的菜谱)

  • 体质表: 添加几列对某种物质的需求 √
  • 职业表: 添加几列对某种物质的需求,添加一列BMI的需求 √
  • user表: 添加综合对物质的需求 √
  • 菜单表:
    • 添加一列早/午晚餐,早为1,else为0. 根据 饼 粥 羹 面 奶 判断
    • 补充一下缺失的url,卡路里 √
    • 添加几列各种物质的需求 √
      • 有一部分数据是爬下的csv里面直接读取,一部分缺失的用food_material的组合来计算
  • 对接任务: 接口使用方法可以参考main函数里面的注释和数据库ER图

    • WebUtil改成了单例,一些方法注意一下
    • 注册: createUser.注意年龄应该让用户填出生年,获取年龄时每次都根据年份计算一下

      • 直接set设置用户的各种信息,不需要的就空着不用set,特殊的一点是病有多个值,要用一个List
    • 修改用户信息 changeUserInfo,注意username必须设置,其他的是需要改的值.修改会覆盖之前的内容.比如用户之前illness是健忘食谱,想增加一个高血压食谱, 就需要把之前的也写上,就是一起传 健忘食谱,高血压食谱这两个参数.写到List里面. 具体参考main函数里面的

    • 获取九体信息 getPhysique方法
    • 获取用户营养元素所需的量: 先getUser获取到用户的病/职业/体质名字,然后根据这些名字查询每个 病/职业/体质信息对应的元素需求,最后加权计算
    • 用户职业BMI分类 3多动,2中等,1少动 先 getUser获取到用户的职业名字.然后getOccupation获取到该职业的BMI分类
    • 动态改变用户已吃的营养元素的量: 在用户表添加element参数,每周自动清空一次

      • Map的可选参数: [calorie,carbohydrate,fat ,protein,cellulose,vitaminA,vitaminB1,vitaminB2,vitaminB6,vitaminC,vitaminE,carotene,cholesterol,Mg,Ca,Fe,Zn,Cu,Mn,K ,P ,Na,Se,niacin ,thiamine]

        1. public static void main(String[] args) {
        2. //只传入变动的参数就行.
        3. //比如 这顿饭摄入了100卡路里,10脂肪.就这样写.
        4. Map<String, Double> params = new HashMap<>();
        5. params.put("calorie", 100.0);
        6. params.put("fat", 10.0);
        7. //第一个参数是username,第二个参数是摄入的营养元素值.可以看函数的源码,有注释
        8. WebUtil.getInstance().eatenElements("test5", params, new Callback() {
        9. @Override
        10. public void onFailure(Call call, IOException e) {
        11. }
        12. @Override
        13. public void onResponse(Call call, Response response) throws IOException {
        14. System.out.println(new Gson().fromJson(response.body().string(), MyUser.class));
        15. }
        16. });
        17. }
    • 获取用户本周已摄入的营养元素的量: getUser得到当前用户的信息,解析后用MyUsergetEaten_elements()获取到Element对象.里面有各种元素信息

    • 根据多个食材组合来搜菜```java List materialList = new ArrayList<>(); materialList.add(“黄瓜”); materialList.add(“茄子”); // materialList.add(“鸡蛋”); WebUtil.getInstance().getMenusByMaterials(materialList, new Callback() {

      1. @Override
      2. public void onFailure(Call call, IOException e) {
      3. }
      4. @Override
      5. public void onResponse(Call call, Response response) throws IOException {
      6. //必须判断状态码,如果为200说明正常,如果为404,说明这几个食材组合查询不到可以做的菜
      7. if (response.code() == 200) {
      8. String json = response.body().string();
      9. FoodMenu[] menus = new Gson().fromJson(json, FoodMenu[].class);
      10. System.out.println(menus);
      11. for (FoodMenu menu : menus) {
      12. System.out.println(menu.getName());
      13. }
      14. } else {
      15. System.out.println("查不到组合食材可以做的菜");
      16. }
      17. }

      }); ```

    • 用户的浏览历史: 添加用户和菜谱的多对多关系```java //获取历史记录 传入username WebUtil.getInstance().getEatenHistory(“test5”, new Callback() {

      1. @Override
      2. public void onFailure(Call call, IOException e) {
      3. }
      4. @Override
      5. public void onResponse(Call call, Response response) throws IOException {
      6. String json = response.body().string();
      7. History[] histories = new Gson().fromJson(json, History[].class);
      8. System.out.println(Arrays.toString(histories));
      9. }

      }); //添加历史记录 传入username 和 Menu的名字 WebUtil.getInstance().addEatenHistory(“test5”, “多味茄子泥”, new Callback() {

      1. @Override
      2. public void onFailure(Call call, IOException e) {
      3. }
      4. @Override
      5. public void onResponse(Call call, Response response) throws IOException {
      6. String json = response.body().string();
      7. History history = new Gson().fromJson(json, History.class);
      8. System.out.println(history);
      9. }

      }); ```

    • 菜名搜索: getMenu方法,传入菜名(菜名通过其他的各种关联方式获取) (menu.calorie是直接爬到的卡路里值,营养元素里的menu.elements.calorie卡路里是根据每个食材的卡路里计算的,相对来说,menu.calorie的值更准确)

    • 功效搜菜 getMenuClassification传入分类(功效)参数,比如川菜.搜到所有的川菜名字.然后可以用菜名搜索搜某个菜的详细信息
    • 点赞或评论来影响推荐顺序
    • 晒图区域
    • 营养量搜菜 : 搜索某个营养量范围内的菜
      可选参数: `[calorie,carbohydrate,fat ,protein,cellulose,vitaminA,vitaminB1,vitaminB2,vitaminB6,vitaminC,vitaminE,carotene,cholesterol,Mg,Ca,Fe,Zn,Cu,Mn,K ,P ,Na,Se,niacin ,thiamine]````java public static void main(String[] args) { //首先构造一个Map, key是参数的名字,value是参数的值.用不到的参数不用写. //我在服务器端根据这些参数构造一个sql,就是 … WHERE key1 <= val1 AND …这样的.

      1. //所以你只传入需要作为搜索条件的参数就可以了.

      Map params = new HashMap<>(); params.put(“calorie”, 100.0); params.put(“fat”, 10.0); WebUtil.getInstance().getMenusByElements(params, new Callback() {

      1. @Override
      2. public void onFailure(Call call, IOException e) {
      3. }
      4. @Override
      5. public void onResponse(Call call, Response response) throws IOException {
      6. String json = response.body().string();
      7. System.out.println(json);
      8. //用轻量级的菜单类MenuLight解析json,这个类只有Menu的[名字,卡路里,元素对象的主码id]这三个域.想获取详细信息可以用getMenu方法获取
      9. //这样是为了查询更快
      10. FoodMenuLight[] foodMenuLights = new Gson().fromJson(json, FoodMenuLight[].class);
      11. System.out.println(Arrays.toString(foodMenuLights));
      12. }

      }); } ```

    • 季节搜菜

    • 小知识获取 : getRandomTricks

又想到的补充内容

  • 根据口味推荐,或者口味混合搭配推荐
  • 注意冬天不推荐夏天的菜谱

数据库设计

智能饮食推荐 - 图1

加下划线为主码,加粗为外码,默认not null

  • 菜谱(str菜名, nullable str体质_名称(对应最优菜谱的效果) ,int卡路里,int制作时间(分钟),str口味,str工艺,str做法,str图片url)
    • menu
  • 食材( str名称)
    • material
  • 体质(str体质名称,str体质特点,str运动调理方式)
    • physique
  • 体质性状(str性状名称)
    • Physical properties
  • 菜谱功能和分类( str分类名称)
    • menu classification
  • 用户( str用户名,str密码, nullable str 体质-名称,nullable str特殊职业)
    • User
  • 特殊职业( str职业名称)
    • Occupation
  • 菜谱功能分类可治愈的职业特殊职业( 特殊职业-str职业名称, 菜谱功能和分类-str分类名称)
  • 菜谱做菜食材 ( str菜谱-菜名,str食材-名称,int用量)
    • cook quantity
  • 食材效果体质( str食材-名称, nullable str体质-名称,int效果(1有利于,0不利于))
    • Material effect
  • 体质身体状态体质性状( str体质-名称, str体质性状-性状名称)
    • physical_state
  • 菜谱菜谱效果菜谱功能和分类( str菜谱-菜名, str菜谱功能和分类-分类名称)
    • menu_effect

服务器请求

说明 方法 请求示例 备注
查询菜单信息 GET http://120.77.182.38/menus/某菜名/ 不加菜名默认请求所有菜单(服务器可能扛不住)
查询食材信息 GET http://120.77.182.38/foodmaterial/西红柿/ 同上
查询用户信息 GET http://120.77.182.38/myuser/zhaolizhi/ 同上
新建用户信息 POST http://120.77.182.38/myuser/ 参数见下图
查询菜谱分类 GET http://120.77.182.38/menuclassification/糖尿病食谱/ 不加分类名默认请求所有分类(和对应的菜谱),响应时间较长
查询职业信息 GET http://120.77.182.38/occupation/电力工程师/ 不加职业名默认查询所有,响应较快 返回职业对应的菜单分类
查询体质信息 GET http://120.77.182.38/physique/气虚质/ 返回体质需要的食材
  • POST新建用户信息params示例
    • 1♂ 0♀
    • occupation_name,physical_name的值必须和数据库对应

智能饮食推荐 - 图2

代码

  • 优化了getRandomMenus方法,传入username参数.会根据user的体质,职业,病理推荐菜java public void getRandomMenus(int count, String username, Callback callback)
    这个方法之前的版本没有username参数,现在弃用原来的版本,原来的方法仍然可以调用,需要把项目的所有getRandomMenus方法调用加上一个username参数

问题

  • 连续识别,出现错误的,点一下消去 锐!
  • bug: 连续拍照后 点了一周定制 锐
  • 食材模糊识别 ok
  • 通过食材组合,搜索菜 ,菜要符合username的信息 蒋和锐 getMenusByMaterials
  • 卡路里不对
  • 早餐晚餐的搜索不随机 shuffle了一下.ok
    • get_menus_by_elements django随机一下
  • 周定制下面的两个按钮 锐
  • 搜菜如果搜不到 把name减一下再搜 ok
  • getRandomMenus的调用里面加上username参数 锐
  • 吃饭的时候没拍照,吃饭完了才想添加,但是菜图片没有了.需要输入添加 (王)
  • 口味信息采集
  • 历史记录
  • 社交功能: 点赞,晒图,评论

    时间安排

  • 周日上午答辩

  • 周五排练

需要演示的功能

  • 拍照 菜品识别 识别 烤鸭 土豆丝 鱼香肉丝 红烧肉 炒面 (动态调量,修改当天余额)
  • 拍照 食材识别 胡萝卜 白萝卜 姜 长条茄子 菜花 (根据用户的信息,并且是多搜索)
  • 周定制(最左边的fragment)