반응형



1. Webcam
OpticalFlowPyrLK 함수를 쓰기위해서 현재 프레임과 이전프레임이 필요
using System; using OpenCvSharp; using UnityEngine; public class WebCam : MonoBehaviour { public Material mat; WebCamTexture webCamTexture; private OpenCVUnity Convert = new OpenCVUnity(); IplImage prev; IplImage curr; IplImage dst; private Texture2D dstTexture; // 계산 결과를 담을 텍스쳐 public CvPoint2D32f[] cornersPrev; public CvPoint2D32f[] cornersCurr; public sbyte[] status; public BufferGenerator bufferGenerator; private void Start() { WebCamDevice device = WebCamTexture.devices[0]; webCamTexture = new WebCamTexture(device.name); webCamTexture.Play(); dstTexture = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false); curr = WebcamTex2Ipl(webCamTexture); } private void Update() { if (curr != null) prev = curr; if (webCamTexture.didUpdateThisFrame) { curr = WebcamTex2Ipl(webCamTexture); dst = Convert.OpticalFlowPyrLK(prev, curr, out cornersPrev, out cornersCurr, out status); // 광학흐름 계산 결과 이미지 확인용 dstTexture.LoadRawTextureData(dst.ImageData, webCamTexture.width * webCamTexture.height * 4); dstTexture.Apply(); mat.mainTexture = dstTexture; } bufferGenerator.UpdateBuffer(); } IplImage WebcamTex2Ipl(WebCamTexture wct) { Color32[] camTex32 = wct.GetPixels32(); CvSize size = new CvSize(wct.width, wct.height); return Convert.FlipImage(IplImage.FromPixelData(size, BitDepth.U8, 4, camTex32)); } private void OnDestroy() { curr.Dispose(); dst.Dispose(); prev.Dispose(); } }
2. OpenCVSharp2 OpticalFlowPyrLK 함수 사용
(OpenCVSharp 강의의 예제 코드 활용)
https://076923.github.io/posts/C-opencv-59/
public IplImage OpticalFlowPyrLK(IplImage previous, IplImage current, out CvPoint2D32f[] corners, out CvPoint2D32f[] corners2, out sbyte[] status)
out 키워드를 써서 코너데이터 배열과 움직임이 있는지 유무를 저장한 배열을 받아옴
3. Graphic 버퍼
버퍼 생성
검출한 corner 데이터와 status 데이터를 버퍼로 변환
using System; using System.Collections; using System.Collections.Generic; using OpenCvSharp; using UnityEditorInternal; using UnityEngine; public class BufferGenerator : MonoBehaviour { public WebCam webcam; public GraphicsBuffer cornersPrev; public GraphicsBuffer cornersCurr; public GraphicsBuffer cornersStatus; int cornerCount = 300; private void Start() { cornersPrev = new GraphicsBuffer(GraphicsBuffer.Target.Structured, cornerCount, sizeof(float) * 2); cornersCurr = new GraphicsBuffer(GraphicsBuffer.Target.Structured, cornerCount, sizeof(float) * 2); cornersStatus = new GraphicsBuffer(GraphicsBuffer.Target.Structured, cornerCount, sizeof(int)); } public void UpdateBuffer() { var prev = new Vector2[cornerCount]; var curr = new Vector2[cornerCount]; var status = new int[cornerCount]; for (int i = 0; i < cornerCount; i++) { prev[i] = new Vector2(webcam.cornersPrev[i].X, webcam.cornersPrev[i].Y); curr[i] = new Vector2(webcam.cornersCurr[i].X, webcam.cornersCurr[i].Y); status[i] = (int) webcam.status[i]; } cornersPrev.SetData(prev); cornersCurr.SetData(curr); cornersStatus.SetData(status); } public void OnDestroy() { if (cornersPrev != null) cornersPrev.Release(); if (cornersCurr != null) cornersCurr.Release(); if (cornersStatus != null) cornersStatus.Release(); } }
vfxgraph의 프로퍼티 바인딩 코드를 작성
using UnityEngine; using UnityEngine.VFX; using UnityEngine.VFX.Utility; [VFXBinder(nameof(BufferBinder))] public class BufferBinder : VFXBinderBase { public BufferGenerator bufferGenerator; [SerializeField, VFXPropertyBinding(nameof(UnityEngine.GraphicsBuffer))] private ExposedProperty corners1BufferName = "cornersPrev"; [SerializeField, VFXPropertyBinding(nameof(UnityEngine.GraphicsBuffer))] private ExposedProperty corners2BufferName = "cornersCurr"; [SerializeField, VFXPropertyBinding(nameof(UnityEngine.GraphicsBuffer))] private ExposedProperty statusBufferName = "statusBuffer"; [SerializeField, VFXPropertyBinding(nameof(UnityEngine.Vector2))] private ExposedProperty webcamResolutionName = "webcamResolution"; [SerializeField, VFXPropertyBinding(nameof(System.Single))] private ExposedProperty reductionMagnificationName = "reductionMagnification"; [SerializeField, VFXPropertyBinding(nameof(UnityEngine.Vector3))] private ExposedProperty displayPositionName = "displayPosition"; public Vector2 webcamResolution; public float reductionMagnification; public Transform displayPosition; public override bool IsValid(VisualEffect component) { return bufferGenerator != null && component.HasGraphicsBuffer(corners1BufferName) && component.HasGraphicsBuffer(corners2BufferName) && component.HasGraphicsBuffer(statusBufferName) && component.HasVector2(webcamResolutionName) && component.HasFloat(reductionMagnificationName) && component.HasVector3(displayPositionName); } public override void UpdateBinding(VisualEffect component) { if (!Application.isPlaying) return; component.SetGraphicsBuffer(corners1BufferName, bufferGenerator.cornersPrev); component.SetGraphicsBuffer(corners2BufferName, bufferGenerator.cornersCurr); component.SetGraphicsBuffer(statusBufferName, bufferGenerator.cornersStatus); component.SetVector2(webcamResolutionName, webcamResolution); component.SetFloat(reductionMagnificationName, reductionMagnification); component.SetVector3(displayPositionName, displayPosition.position); } }
4. Visual Effect Graph



반응형
'programming | development > unity' 카테고리의 다른 글
Unity + Realsense F200 (0) | 2022.06.14 |
---|---|
HDRP Raytracing 세팅 (0) | 2022.03.14 |
Component Inspector 항목들 (0) | 2022.02.26 |
Visual Effect Graph Attributes (0) | 2022.02.25 |
Strip Particle System (0) | 2022.02.23 |
댓글