• uniapp 小程序拍照上传,百度识别人体关键点,显示拖拽元素,生成海报


    需求是小程序这边先拍摄露出手腕的照片,然后传给后端,调百度识别的api,根据返回的手腕位置,显示手表的贴图(可以拖拽旋转之类的)最后可以生成海报,保存图片到手机。
    前端这边的技术点分别有

    1. 调起相机拍照
    2. 上传图片
    3. 图片拖拽功能
    4. 生成海报
      下面就来分别总结一下吧。
    • 调起相机拍照
      参考文档链接文档链接
      在这里插入图片描述
      用uniapp写就是
    <camera class="camera"></camera>
    <!-- 拍照按钮 -->
    <view class="takePhoto" @click="takePhoto">
    	<view class="inner"></view>
    </view>
    
    
    //js里面写
    		methods: {
    			// 拍照
    			takePhoto() {
    				const ctx = wx.createCameraContext()
    				ctx.takePhoto({
    					quality: 'high',
    					success: (res) => {
    						// console.log(res)
    						this.imagePath = res.tempImagePath//保存照片临时地址
    					}
    				})
    			},
    			}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 上传图片
      参考文档参考文档
      在这里插入图片描述
      将红框里面的url换成后端给你的上传接口就可以啦,记得一定要去小程序开发后台配一下uploadFile合法域名,不然死活传不上去的!!!
      在这里插入图片描述
      在这里插入图片描述

    • 图片拖拽功能

    • 生成海报
      这两个功能我使用了组件小程序组件-canvas拖拽组件 真的贼牛逼
      但是我们的需求是,根据接口返回的位置,在手腕那里直接显示手表的图片,所以还要调整一下。

    		<!-- canvas -->
    		<view class="result" v-show="imagePath&&(!showPoster)">
    			<button @click="saveImg">生成海报</button>
    			<button @click="again">重新拍摄</button>
    			<canvas-drag ref="canvasRef" id="canvas-drag" :graph="graph" :width="photoX" :height="photoY"
    				enableUndo="true">
    			</canvas-drag>
    
    		</view>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    首先要注意的是,一定要用v-show 而不是v-if 不然this.$refs取不到的
    然后还要注意,百度识别返回的手腕坐标,是手腕中心位置距离图片左上角的位置,单位是px。所以我们用的时候需要

    1. 单位转化为rpx 即px/2
    2. 手腕坐标减去手腕的宽高才是手腕起始位置的坐标,也就是贴图移动的left top值
    				uni.uploadFile({
    					url:'写后端给你的url',//返回位置和手掌大小
    					filePath: imagePath,
    					name: 'file',
    					formData: {
    						'user': 'test'
    					},
    					success: (res) => {
    						var jsarr = JSON.parse(res.data)
    						if (jsarr.code != 200) {
    							uni.showModal({
    								title: '提示',
    								content: '人体数据识别失败,请重新拍照',
    								showCancel: false,
    								success: (res) => {
    									if (res.confirm) {
    										console.log('用户点击确定');
    										this.imagePath = ''
    									}
    								}
    							});
    						} else {
    							console.log('xxxx',jsarr.data.wrist.x)
    							this.watchX = jsarr.data.location.width/2
    							this.watchY = this.watchX
    							//贴图初始位置
    							this.initialX = jsarr.data.wrist.x / 2 -this.watchX/2
    							this.initialY = jsarr.data.wrist.y / 2  -this.watchX/2
    							//控制贴图移动位置,我写死了
    							this.minX=this.initialX-this.watchX/30
    							this.maxX=this.initialX+this.watchX/10*9
    							this.minY=this.initialY-this.watchY/30
    							this.maxY=this.initialY+this.watchY/10*9
    							this.isBody = true
    							this.onChangeBgImage()
    							console.log("xy", this.initialX, this.initialY)
    						}
    					}
    				})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    			//展示图片背景
    			onChangeBgImage() {
    				this.$refs.canvasRef.changeBgImage(this.imagePath)
    				this.onAddWatch()
    			},
    			//显示手表
    			onAddWatch() {
    				this.setData({
    					graph: {
    						//贴图大小
    						w: this.watchX,
    						h: this.watchY,
    						//贴图坐标
    						x: this.initialX, 
    						y: this.initialY,
    						rotate: this.rotate,
    						//贴图位置限制
    						minX:this.minX, 
    						maxX:this.maxX,
    						minY:this.minY,
    						maxY:this.maxY,
    						type: 'image',
    						//贴图地址
    						url: "/static/images/watchPhoto.png"
    					}
    				});
    			},
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    组件里面需要加上对贴图移动的限制,找到move()

        move(e) {
          const {
            x,
            y
          } = e.touches[0];
          if (this.tempGraphArr && this.tempGraphArr.length > 0) {
            isMove = true; // 有选中元素,并且有移动时,设置移动标识
    
            const currentGraph = this.tempGraphArr[this.tempGraphArr.length - 1];
    
            if (currentGraph.action === 'move') {
    			
              currentGraph.centerX = this.currentGraph.centerX + (x - this.currentTouch.x);
              currentGraph.centerY = this.currentGraph.centerY + (y - this.currentTouch.y); // 使用中心点坐标计算位移,不使用 x,y 坐标,因为会受旋转影响。
    		  //控制图片移动位置
    		  if(currentGraph.centerX<=this.graph.minX){
    			  currentGraph.centerX=this.graph.minX
    		  }
    		  if(currentGraph.centerX>this.graph.maxX){
    			  currentGraph.centerX=this.graph.maxX
    		  }
    		  if(currentGraph.centerY<=this.graph.minY){
    			  currentGraph.centerY=this.graph.minY
    		  }
    		  if(currentGraph.centerY>this.graph.maxY){
    			  currentGraph.centerY=this.graph.maxY
    		  }
    
              if (currentGraph.type !== 'text') {
                currentGraph.x = currentGraph.centerX - this.currentGraph.w / 2;
                currentGraph.y = currentGraph.centerY - this.currentGraph.h / 2;
              }
            } else if (currentGraph.action === 'transform') {
    			console.log('图片缩放')
              currentGraph.transform(this.currentTouch.x, this.currentTouch.y, x, y, this.currentGraph);
            } // 更新4个坐标点(相对于画布的坐标系)
    
    
            currentGraph._rotateSquare();
    
            this.draw();
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    最后生成海报的功能,也是直接调组件的方法就可以了

    			/**
    			 * 导出当前画布为模板
    			 */
    			saveImg() {
    				uni.showLoading({
    					mask: true
    				})
    				this.$refs.canvasRef.exportFun().then(imgArr => {
    					console.log(JSON.stringify(imgArr));
    					this.showPoster = imgArr
    					uni.hideLoading()
    				}).catch(e => {
    					console.error(e);
    				});
    			},
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    请添加图片描述
    大概就是这样子啦

  • 相关阅读:
    【网路安全 --- Linux,window常用命令】网络安全领域,Linux和Windows常用命令,记住这些就够了,收藏起来学习吧!!
    使用 FastGPT 构建高质量 AI 知识库
    Shell 脚本循环遍历日志文件中的值进行求和并计算平均值,最大值和最小值
    windows10安装kali-linux指南(wsl),含kali桌面、中文
    【初赛题解】CSP-J 2022 入门级 第一轮 第16题
    【Linux】tail命令使用
    JavaWeb输入输出流
    生成对抗性网络简介
    基于C#+unity的2D跑酷闯关对战冒险游戏设计 课程报告+答辩PPT+源码
    Chain-of-Verification Reduces Hallucination in Lagrge Language Models阅读笔记
  • 原文地址:https://blog.csdn.net/bo_gu/article/details/127754656