Hololens入门之拍照编辑
来源:互联网 发布:java 获取文件路径 编辑:程序博客网 时间:2024/06/05 11:38
Hololens入门之拍照编辑
在Hololens的使用过程中,可能会遇到以下场景,使用Hololens进行拍摄照片,然后对照片进行图像识别,但是由于初始拍摄的照片中干扰项太多,影响识别效果,这时就需要截取图片中的有效部分来对图片进行识别。
本项目使用Hololens进行拍照,然后对照片进行裁剪编辑,获取图片的有效区域。
完整代码可在GitHub上进行下载(https://github.com/adjacentech/HoloPhotoEditor)
裁剪过程中通过移动裁剪框的位置,以及改变裁剪框的大小来确定有效裁剪区域(关键代码如下)
using HoloToolkit.Unity.InputModule;using System.Collections;using System.Collections.Generic;using UnityEngine;using System;public class CropBoxManager : MonoBehaviour, INavigationHandler{ private Vector3 manipulationPreviousPosition; public GameObject imageObject = null; private float parentWidth = 0; private float parentHeight = 0; private Vector3 originalLocalPosition; private Vector2 originalSizeDelta; public float minWidth = 100; public float minHeight = 100; void Awake() { parentWidth = imageObject.GetComponent<RectTransform>().rect.width; parentHeight = imageObject.GetComponent<RectTransform>().rect.height; originalLocalPosition = gameObject.GetComponent<RectTransform>().localPosition; originalSizeDelta = gameObject.GetComponent<RectTransform>().sizeDelta; } private void Start() { } // Update is called once per frame void Update() { } /// <summary> /// 获取裁剪框的矩形区域 /// </summary> /// <returns></returns> public RectTransform GetCropBoxRectTransform() { return gameObject.GetComponent<RectTransform>(); } /// <summary> /// 获取父对象的大小 /// </summary> /// <returns></returns> public Vector2 GetParentSize() { return new Vector2(parentWidth, parentHeight); } /// <summary> /// 重置裁剪框的大小和位置 /// </summary> public void ResetCropBoxTransform() { gameObject.GetComponent<RectTransform>().localPosition = new Vector3(originalLocalPosition.x, originalLocalPosition.y, originalLocalPosition.z) ; gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(originalSizeDelta.x, originalSizeDelta.y); } /// <summary> /// Navigation手势取消事件 /// </summary> /// <param name="eventData"></param> public void OnNavigationCanceled(NavigationEventData eventData) { InputManager.Instance.ClearModalInputStack(); } /// <summary> /// Navigation手势完成事件 /// </summary> /// <param name="eventData"></param> public void OnNavigationCompleted(NavigationEventData eventData) { InputManager.Instance.ClearModalInputStack(); } /// <summary> /// Navigation手势开始事件 /// </summary> /// <param name="eventData"></param> public void OnNavigationStarted(NavigationEventData eventData) { if (ToolManager.Instance.selectedTool == null || ((ToolManager.Instance.selectedTool.type != ToolType.Resize) && (ToolManager.Instance.selectedTool.type != ToolType.Move)) /*|| (CapturePhotoManager.Instance.GetCurrentStatus() != CurrentStatus.EdittingPhoto)*/) { return; } InputManager.Instance.PushModalInputHandler(gameObject); } /// <summary> /// Navigation手势更新事件 /// </summary> /// <param name="eventData"></param> public void OnNavigationUpdated(NavigationEventData eventData) { if (ToolManager.Instance.selectedTool == null || ((ToolManager.Instance.selectedTool.type != ToolType.Resize) && (ToolManager.Instance.selectedTool.type != ToolType.Move)) /*|| (CapturePhotoManager.Instance.GetCurrentStatus() != CurrentStatus.EdittingPhoto)*/) { return; } switch (ToolManager.Instance.selectedTool.type) { case ToolType.Move: Move(eventData); break; case ToolType.Resize: Resize(eventData); break; default: break; } } /// <summary> /// 平移裁剪框 /// </summary> /// <param name="eventData"></param> private void Move(NavigationEventData eventData) { Vector3 moveVector = Vector3.one; float deltaX = 8 * eventData.CumulativeDelta.x; float deltaY = 8 * eventData.CumulativeDelta.y; if (Math.Abs(eventData.CumulativeDelta.x) >= Math.Abs(eventData.CumulativeDelta.y)) { //当水平移动分量大于垂直分量时,水平平移 moveVector = new Vector3(deltaX, 0, 0); } else { //当垂直移动分量大于水平分量时,垂直平移 moveVector = new Vector3(0, deltaY, 0); } //计算边界,重新调整位移 moveVector = RecalculateMoveVector(moveVector); RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); gameObject.GetComponent<RectTransform>().localPosition = new Vector3( rectTransform.localPosition.x + moveVector.x, rectTransform.localPosition.y + moveVector.y, rectTransform.localPosition.z + moveVector.z); } /// <summary> /// 调整裁剪框的大小 /// </summary> /// <param name="eventData"></param> private void Resize(NavigationEventData eventData) { if (Math.Abs(eventData.CumulativeDelta.x) >= Math.Abs(eventData.CumulativeDelta.y)) { //当水平移动分量大于垂直分量时,修改宽度 float deltaX = 10 * eventData.CumulativeDelta.x; Rect rect = gameObject.GetComponent<RectTransform>().rect; Rect newRect = new Rect((rect.width + deltaX) / 2, rect.height / 2, rect.width + deltaX, rect.height); newRect = RecalculateRectWidth(newRect); gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(newRect.width, newRect.height); } else { //当垂直移动分量大于水平分量时,修改高度 float deltaY = 10 * eventData.CumulativeDelta.y; Rect rect = gameObject.GetComponent<RectTransform>().rect; Rect newRect = new Rect(rect.width / 2, (rect.height + deltaY) / 2, rect.width, rect.height + deltaY); newRect = RecalculateRectHeight(newRect); gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(newRect.width, newRect.height); } } /// <summary> /// 重新计算位移 /// </summary> /// <param name="moveVector"></param> /// <returns></returns> private Vector3 RecalculateMoveVector(Vector3 moveVector) { RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); Rect rect = rectTransform.rect; //裁剪框移动不超出大图范围,需要满足以下条件 //-parentWidth / 2 + width / 2 <= x <= parentWidth / 2 - width / 2 //-parentHeight / 2 + height / 2 <= y <= parentHeight / 2 - height / 2 if (((rectTransform.localPosition.x + moveVector.x) >= (-parentWidth / 2 + rect.width / 2)) && ((rectTransform.localPosition.x + moveVector.x) <= (parentWidth / 2 - rect.width / 2)) && ((rectTransform.localPosition.y + moveVector.y) >= (-parentHeight / 2 + rect.height / 2)) && ((rectTransform.localPosition.y + moveVector.y) <= (parentHeight / 2 - rect.height / 2))) { return moveVector; } float newX = moveVector.x; float newY = moveVector.y; //当超出左边框,重新计算水平移动分量 if ((rectTransform.localPosition.x + moveVector.x) < (-parentWidth / 2 + rect.width / 2)) { newX = -parentWidth / 2 + rect.width / 2 - rectTransform.localPosition.x; } //当超出右边框,重新计算水平移动分量 if ((rectTransform.localPosition.x + moveVector.x) > (parentWidth / 2 - rect.width / 2)) { newX = parentWidth / 2 - rect.width / 2 - rectTransform.localPosition.x; } //当超出下边框,重新计算垂直移动分量 if ((rectTransform.localPosition.y + moveVector.y) < (-parentHeight / 2 + rect.height / 2)) { newY = -parentHeight / 2 + rect.height / 2 - rectTransform.localPosition.y; } //当超出上边框,重新计算垂直移动分量 if ((rectTransform.localPosition.y + moveVector.y) > (parentHeight / 2 - rect.height / 2)) { newY = parentHeight / 2 - rect.height / 2 - rectTransform.localPosition.y; } return new Vector3(newX, newY, moveVector.z); } /// <summary> /// 重新计算裁剪框的宽度 /// </summary> /// <param name="rect">矩形区域</param> /// <returns>返回矩形区域</returns> private Rect RecalculateRectWidth(Rect rect) { //当裁剪框高度小于最小宽度时,重新调整为最小宽度 if (rect.width < minWidth) { return new Rect(minWidth / 2, rect.y, minWidth, rect.height); } RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); //在大图范围内进行移动,需满足条件 -parentWidth / 2 + width / 2 <= x <= parentWidth / 2 - width / 2 if ((rectTransform.localPosition.x >= (-parentWidth / 2 + rect.width / 2)) && rectTransform.localPosition.x <= (parentWidth / 2 - rect.width / 2)) { return rect; } //当裁剪框超出左边框时,重新进行调整 if (rectTransform.localPosition.x < (-parentWidth / 2 + rect.width / 2)) { return new Rect(rectTransform.localPosition.x + parentWidth / 2, rect.y, 2 * rectTransform.localPosition.x + parentWidth, rect.height); } //当裁剪框超出右边框时,重新进行调整 if (rectTransform.localPosition.x > (parentWidth / 2 - rect.width / 2)) { return new Rect(parentWidth/2 - rectTransform.localPosition.x, rect.y, parentWidth- 2 * rectTransform.localPosition.x, rect.height); } return rect; } /// <summary> /// 重新计算裁剪框的高度 /// </summary> /// <param name="rect">矩形区域</param> /// <returns>返回矩形区域</returns> private Rect RecalculateRectHeight(Rect rect) { //当裁剪框高度小于最小高度时,重新调整为最小高度 if (rect.height < minHeight) { return new Rect(rect.x, minHeight / 2, rect.width, minHeight); } RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); //在大图范围内进行移动,需满足条件 -parentHeight / 2 + height / 2 <= y <= parentHeight / 2 - height / 2 if ((rectTransform.localPosition.y >= (-parentHeight / 2 + rect.height / 2)) && rectTransform.localPosition.y <= (parentHeight / 2 - rect.height / 2)) { return rect; } //当裁剪框超出下边框时,重新进行调整 if (rectTransform.localPosition.y < (-parentHeight / 2 + rect.height / 2)) { return new Rect(rect.x, rectTransform.localPosition.y + parentHeight / 2, rect.width, 2 * rectTransform.localPosition.y + parentHeight); } //当裁剪框超出上边框时,重新进行调整 if (rectTransform.localPosition.y > (parentHeight / 2 - rect.height / 2)) { return new Rect(rect.x, parentHeight / 2 - rectTransform.localPosition.y, rect.width, parentHeight - 2 * rectTransform.localPosition.y); } return rect; }}
运行测试
1、点击进行拍照,获取照片
2、选择“移动”选项,上下左右拖拽裁剪框,调整裁剪框的位置
3、选择“调整大小”选项,上下左右拖拽裁剪框,调整裁剪框的大小
4、当调整到合适的位置和大小时,点击确定按钮,最终裁剪出所需要的有效区域
阅读全文
2 0
- Hololens入门之拍照编辑
- Hololens入门之凝视
- Hololens入门之凝视
- vuforia之HoloLens 入门
- Hololens入门之凝视
- Hololens入门之凝视
- Hololens入门之空间映射
- Hololens入门之使用UGUI
- Hololens入门之使用Vuforia
- Hololens入门之手势识别(单击、双击)
- Hololens入门之语音识别(语音命令)
- Hololens入门之语音识别(语音听写)
- Hololens入门之空间映射(放置物体)
- Hololens开发之HoloLens简介
- Hololens入门之使用Unity开发一个简单的应用
- Hololens入门之手势识别(手检测反馈)
- Hololens入门之空间锚与场景保持
- Hololens入门之使用Unity开发一个简单的应用
- DevOps企业实践指南(6): 持续集成
- return 关键字
- 每天五分钟linux(12)-more
- C. Star sky Codeforces
- SD 模块的几个增强
- Hololens入门之拍照编辑
- 二分法求方程的根
- 火狐浏览器,改变你的浏览体验
- 博客开始打卡
- Spring MVC
- EXPRESS bodyParser
- CF835B-The number on the board
- jsp页面设置了IE版本Edge但是不生效
- Hi3519-pinctrl驱动开发②创建mapping table