【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】

  • 【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】
    • 电子相册搭建(表情、场景识别)
      • 一、项目介绍
      • 二、新建项目
          • 1.新建spring boot项目
          • 2.目录结构
      • 三、项目实现
          • (一)前端index.html
          • (二)控制层AlbumController
            • (1)upload
            • (2)getList
            • (3)getCates
            • (4)getPhotosByCateAndLabel
            • (5)getPhotosByCate
          • (三)ResourceService资源管理器
            • (一)ResourceService类
            • (二)LabelModel类
    • 加入高校计划
    • 加入高校计划

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】

电子相册搭建(表情、场景识别)

一、项目介绍

通过三个部分,实现上传照片、已上传照片轮播、照片根据表情和场景分类。本次算法进行了表情识别和场景识别,这些都是对阿里云的外部api调用而实现。

通过点击照片可以查看该照片的分类,通过点击已知分类可以查看该分类下的照片,从而达到一个电子相册的功能。

二、新建项目

1.新建spring boot项目

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第1张图片

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第2张图片

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第3张图片

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第4张图片
【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第5张图片

2.目录结构

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第6张图片
【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第7张图片

  • Application:启动的入口函数,
  • common:一般就是存放公共的类或者常量,或者枚举值
  • config:装载或者是数据库的配置,我们都会放在 config 下面
  • WebAppConfig 是对我们的静态资源,比如说 css、js 还有一些图片,做了一个映射,比如说 static,然后我们把它映射到 classpath:/static 目录下
  • Controller:我们接收外部的请求,比如参数校验,之后通过接口调用或得到的数据返回给前端
  • Service: 把不同的请求 , 不同的服务把它抽象成一个 service,本项目有两个service,也可以认为是两个模块
  • Utils: 存放公共的类或者工具函数

三、项目实现

(一)前端index.html

前端的实现是基于vue网页框架实现的,下面是scriipt.js中的一个例子

let customEvent = new Vue();//定义一个空的Vue实例

let tagIns = new Vue({
    el: "#my-custom-tags",
    data() {
        return {
            "tags": {}
        }

    },
    beforeMount() {
        this.getTags();

    },

    mounted() {
        customEvent.$on('refreshTag',success => {
            this.getTags();//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
        })
    },
    methods: {
        getBgcNo: function() {
            return Math.ceil(Math.random() * 10) - 1
        },

        getTags: async function() {
            let res = await axios.get("http://127.0.0.1:8080/album/v1/allCates")
            this.tags = res.data
        },
    }
});
(二)控制层AlbumController

控制层主要包括下面几个部分:

  • visionService、resourceService两个私有成员
  • getList
  • getCates
  • getPhotosByCateAndLabel
  • getPhotosByCate
  • upload
(1)upload

为了避免重名,将文件名转换为MD5值,并返回,里面调用了Md5CaculateUtil

@PostMapping("/upload")
    public Object upload(@RequestParam("file") MultipartFile file) throws Exception {
        //计算上传文件的md5值,作为文件名
        byte[] bytes = file.getBytes();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        String md5Str = Md5CaculateUtil.getMD5(inputStream);
        inputStream.reset();
        inputStream.mark(0);

        String fileName = file.getOriginalFilename();
        String fType = fileName.substring(fileName.lastIndexOf("."));
        fileName = String.format("%s%s", md5Str, fType);
        resourceService.saveAndRecognizeImage(fileName, inputStream);
        return fileName;
    }
(2)getList

获取全部图片,里面调用了getAllPhotos方法

@RequestMapping(value = "/list", method = RequestMethod.GET)
    public Object getList() throws Exception {
        return resourceService.getAllPhotos();
    }
(3)getCates

获取分类,里面调用了getAllCates方法

@RequestMapping(value = "/allCates", method = RequestMethod.GET)
    public Object getCates() throws Exception {
        return resourceService.getAllCates();
    }
(4)getPhotosByCateAndLabel

通过分类和标签获取图片

@RequestMapping(value = "/getPhotosByCateAndLabel", method = RequestMethod.GET)
    public Object getPhotosByCateAndLabel(@RequestParam(name="cate") String cate, @RequestParam(name="tag") String tag) throws Exception {
        return resourceService.getPhotosByCateAndLabel(cate, tag);
    }
(5)getPhotosByCate

通过分类获取图片

@RequestMapping(value = "/getPhotosByCate", method = RequestMethod.GET)
    public Object getPhotosByCate(@RequestParam(name="cate") String cate) throws Exception {
        return resourceService.getPhotosByCate(cate);
    }
(三)ResourceService资源管理器

主要包含以下几个部分:

  • ResourceService类:
    • 五个私有成员
    • loadMetaData
    • saveMetaData
    • getPhotosByCateAndLabel
    • getPhotosByCate
    • getAllPhotos
    • getAllCates
    • getAccessPath
    • saveAndRecognizeImage
  • LabelModel类:
    • 五个私有成员和三个静态属性
    • LabelModel
    • getAllImg
    • getImgByCate
    • getImgByCateAndLabel
    • addImg
    • removeImg
(一)ResourceService类
public class ResourceService {
    private String scene;
    @Value("${data.storage.path}")
    private String storagePath;

    @Value("${img.storage.path}")
    private String imagePath;

    static final String fileName = "data.json";
    private LabelModel labelModel;

    @Autowired
    private VisionService visionService;

    @PostConstruct
    public void loadMetaData() {
        log.info("load");
        try {
            InputStream inputStream = new FileInputStream(storagePath + fileName);
            labelModel = JSONObject.parseObject(inputStream, LabelModel.class);
        } catch (IOException e) {
            log.error(e.toString());
            labelModel = new LabelModel();
        }
    }

    @PreDestroy
    public void saveMetaData() {
        log.info("save");
        try {
            System.out.println(JSON.toJSONString(labelModel));
            OutputStream outputStream = new FileOutputStream(storagePath + fileName);
            outputStream.write(JSON.toJSONBytes(labelModel));
            outputStream.close();
        } catch (Exception e) {
            log.error(e.toString());
        }
    }



    public List<String> getPhotosByCateAndLabel(String cate, String label) {
        return getAccessPath(labelModel.getImgByCateAndLabel(cate, label));
    }

    public List<String> getPhotosByCate(String cate) {
        return getAccessPath(labelModel.getImgByCate(cate));
    }

    public List<String> getAllPhotos()  {
        return getAccessPath(labelModel.getAllImg());
    }

    public Object getAllCates() {
        return labelModel.cateMap;
    }

    private List<String> getAccessPath(List<String> imgs) {
        List<String> result = new ArrayList<>();
        imgs.stream().forEach(img-> {
            result.add(String.format("/img/%s", img));
        });
        return  result;
    }

    public void saveAndRecognizeImage(String filename, InputStream inputStream) {
        log.info("saveImage");
        try {

            //识别场景
            inputStream.reset();
            inputStream.mark(0);
            List<String> scenes = visionService.recognizeScene(inputStream);
            labelModel.addImg(LabelModel.SCENE, filename, scenes);

            inputStream.reset();
            inputStream.mark(0);
            List<String> expressions = visionService.recognizeExpression(inputStream);
            labelModel.addImg(LabelModel.EXPRESSION, filename, expressions);

            //重复使用InputStream需要reset、mark操作
            inputStream.reset();
            inputStream.mark(0);
            //保存文件
            System.out.println(imagePath+filename);
            OutputStream outputStream = new FileOutputStream(imagePath + filename);
            IOUtils.copy(inputStream, outputStream);

            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.toString());
        }
    }
(二)LabelModel类
@Data
    static class LabelModel {
        static final String SCENE = "scene";
        static final String EXPRESSION = "expression";
        static final String STYLE = "style";
        //保存不同场景标签包含的图片
        private Map<String, Set<String>> sceneMap;
        //保存不同表情表情包含的图片
        private Map<String, Set<String>> expressionMap;

        //保存不同风格包含的图片
        private Map<String, Set<String>> styleMap;
        private Map<String, Set<String>> cateMap;


        //图片中包含的标签
        //key:图片地址
        //value: Set中value值为: {[scene|expression|style]}_{label},例如:style_怀旧
        private Map<String, Set<String>> imgLabels;

        public LabelModel(){
           this.imgLabels = new HashMap<>();
           this.sceneMap = new HashMap<>();
           this.expressionMap = new HashMap<>();
           this.styleMap = new HashMap<>();
           this.cateMap = new HashMap<>();
        }

        public List<String> getAllImg() {
            List<String> result = new ArrayList<>();
            imgLabels.forEach((k, v)-> {
                result.add(k);
            });

            return result.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        }

        public List<String> getImgByCate(String cate) {
            Map<String, Set<String>> data = new HashMap<>();
            switch (cate) {
                case SCENE: {
                    data = sceneMap;
                    break;
                }
                case EXPRESSION: {
                    data = expressionMap;
                    break;
                }
                case STYLE: {
                    data = styleMap;
                    break;
                }
            }

            Set<String> result = new HashSet<>();
            data.forEach((k, d)-> {
                result.addAll(d);
            });


            return  result.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        }

        public List<String> getImgByCateAndLabel(String cate, String label) {
            System.out.println(cate);
            System.out.println(label);
            String key = String.format("%s_%s", cate, label);

            Set<String> result = new HashSet<>();
            switch (cate) {
                case SCENE: {
                    result = sceneMap.get(key);
                    break;
                }
                case EXPRESSION: {
                    result = expressionMap.get(key);
                    break;
                }
                case STYLE: {
                    result = styleMap.get(key);
                    break;
                }
            }

            return result.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        }

        void addImg(String cate, String img, List<String> labels) {
            for (String label : labels) {
                String item = String.format("%s_%s", cate, label);
                Set<String> imgSet = imgLabels.getOrDefault(img, new HashSet<>());
                imgSet.add(item);
                imgLabels.put(img, imgSet);
                switch (cate) {
                    case SCENE: {
                        Set<String> sceneSet = sceneMap.getOrDefault(item, new HashSet<>());
                        sceneSet.add(img);
                        sceneMap.put(item, sceneSet);
                        Set<String> cateSet = cateMap.getOrDefault(cate, new HashSet<>());
                        cateSet.add(label);
                        cateMap.put(cate, cateSet);
                        break;
                    }
                    case EXPRESSION: {
                        Set<String> expressionSet = expressionMap.getOrDefault(item, new HashSet<>());
                        expressionSet.add(img);
                        expressionMap.put(item, expressionSet);
                        Set<String> cateSet = cateMap.getOrDefault(cate, new HashSet<>());
                        cateSet.add(label);
                        cateMap.put(cate, cateSet);
                        break;
                    }
                    case STYLE: {
                        Set<String> styleSet = styleMap.getOrDefault(item, new HashSet<>());
                        styleSet.add(img);
                        styleMap.put(item, styleSet);
                        Set<String> cateSet = cateMap.getOrDefault(cate, new HashSet<>());
                        cateSet.add(label);
                        cateMap.put(cate, cateSet);
                        break;
                    }
                }
            }
        }

        void removeImg(String img) {
            Set<String> labels = imgLabels.remove(img);
            labels.stream().forEach(label -> {
                String[] segs = label.split("_");
                String cate = segs[0];
                String labelKey = segs[1];
                switch (cate) {
                    case SCENE: {
                        sceneMap.get(labelKey).remove(img);
                        break;
                    }
                    case EXPRESSION: {
                        expressionMap.get(labelKey).remove(img);
                        break;
                    }
                    case STYLE: {
                        styleMap.get(labelKey).remove(img);
                        break;
                    }
                }
            });
        }
    }

加入高校计划

源代码在改了配置和地址的情况下,可以跑起来,但是网页控制台会报错。

同时也传入图片也没有响应。

今天已经是第三天,自己的技术还是不够,在前后端结合的地方还得抓紧学习。

源示例代码如下:

https://github.com/aliyun/alibabacloud-viapi-demo

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第8张图片

加入高校计划

本人是参加的达摩院特别版-视觉AI训练营第二期
训练营里面的小哥哥小姐姐说话超级好听,也有超多大佬,我超喜欢这里!

【阿里云高校计划】基于阿里云表情、场景识别的电子相册搭建 day3 【一见如故】_第9张图片

你可能感兴趣的:(阿里云,视觉,AI)