UE5 MP4U动作识别的一些方法记录

MPLandmarkStruct.h:用与记录关键点XYZ

GetMPLandmarkComponent.h与GetMPLandmarkComponent.cpp:获取关键点数据与动作识别判断

MyUobjectClass.h与MyUobjectClass.cpp:创建委托负责消息中转,应为单例模式确保其他类中始终使用的是同一个实例

MyThreadClass.h与MyThreadClass.cpp:用于主线程之外的其他计算,避免阻塞主线程导致崩溃

MyActorClass.h与MyActorClass.cpp:动作识别后触发的响应类,触发某个事件

MPLandmarkStruct.h

cpp 复制代码
#pragma once
#include "CoreMinimal.h"
#include "MPLandmarkStruct.generated.h"

USTRUCT(BlueprintType)
struct FLandMarkStruct
{
	GENERATED_BODY()

	// 使用 UPROPERTY 宏定义结构体的成员变量
	UPROPERTY(BlueprintReadOnly, Category = "Landmark")
	float X;

	UPROPERTY(BlueprintReadOnly, Category = "Landmark")
	float Y;

	UPROPERTY(BlueprintReadOnly, Category = "Landmark")
	float Z;
	
	// 可以定义构造函数
	FLandMarkStruct()
		: X(0.0f), Y(0.0f), Z(0.0f) {}
};

GetMPLandmarkComponent.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "MediaPipeHolisticComponent.h"
#include "Components/ActorComponent.h"
#include "MPLandmarkStruct.h"
#include "MyUobjectClass.h"

#include "GetMPLandmarkComponent.generated.h"

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class MEDIAPIPE4UDEMO_API UGetMPLandmarkComponent : public UActorComponent
{
	GENERATED_BODY()

public:
	// Sets default values for this component's properties
	UGetMPLandmarkComponent();

protected:
	// Called when the game starts
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
	                           FActorComponentTickFunction* ThisTickFunction) override;

	UPROPERTY(VisibleAnywhere)
	UMediaPipeHolisticComponent* MediaPipeHolisticComponent;
	
	void OnPoseLandmarkDetected(const TSharedPtr<TArray<FMediaPipeLandmark,FDefaultAllocator>,ESPMode::ThreadSafe>& Landmarks,const FMediaPipeSourceInfo& SourceInfo);

	UPROPERTY(VisibleAnywhere)
	FLandMarkStruct LandMarkStruct;

	UMyUobjectClass* MyUobjectClass;
};

GetMPLandmarkComponent.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "GetMPLandmarkComponent.h"

#include "Engine/Engine.h"
#include "GameFramework/Actor.h"

UGetMPLandmarkComponent::UGetMPLandmarkComponent()
{	
	PrimaryComponentTick.bCanEverTick = true;

	MyUobjectClass = nullptr;
}

void UGetMPLandmarkComponent::BeginPlay()
{
	Super::BeginPlay();

	MyUobjectClass = UMyUobjectClass::GetInstance();

	// 获取父Actor上的MediaPipeHolisticComponent实例
	AActor* Owner = GetOwner();
	if (Owner)
	{
		MediaPipeHolisticComponent = Owner->FindComponentByClass<UMediaPipeHolisticComponent>();
		if (MediaPipeHolisticComponent)
		{
			// 订阅PoseLandmarksEventTrigger事件
			MediaPipeHolisticComponent->PoseLandmarksEventTrigger().AddUObject(this, &UGetMPLandmarkComponent::OnPoseLandmarkDetected);
		}
	}
	else
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("Owner is not valid"));
	}
}

void UGetMPLandmarkComponent::TickComponent(float DeltaTime, ELevelTick TickType,
                                            FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

void UGetMPLandmarkComponent::OnPoseLandmarkDetected(
	const TSharedPtr<TArray<FMediaPipeLandmark, FDefaultAllocator>, ESPMode::ThreadSafe>& Landmarks,
	const FMediaPipeSourceInfo& SourceInfo)
{
	if (Landmarks.IsValid())
	{
		// 解引用指针来访问 TArray
		const TArray<FMediaPipeLandmark>& LandmarkArray = *Landmarks;

		// 处理接收到的Landmarks数据
		for (const FMediaPipeLandmark& Landmark : LandmarkArray)
		{
			float X = Landmark.Pos.X;
			float Y = Landmark.Pos.Y;
			float Z = Landmark.Pos.Z;
		}
		const FMediaPipeLandmark& land123 = LandmarkArray[12];
		LandMarkStruct.X = land123.Pos.X;
		LandMarkStruct.Y = land123.Pos.Y;
		LandMarkStruct.Z = land123.Pos.Z;

		const FMediaPipeLandmark& leftwrist = LandmarkArray[15];
		const FMediaPipeLandmark& leftshoulder = LandmarkArray[11];
		if (!MyUobjectClass->bConditionTriggered)
		{
			if(leftwrist.Pos.Y < leftshoulder.Pos.Y)
			{			
				if (MyUobjectClass->LandMarkGet.IsBound())
				{
					MyUobjectClass->LandMarkGet.Broadcast();
					MyUobjectClass->bConditionTriggered = true;
				}
			}
		}
	}
	else
	{
		GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, TEXT("Landmarks pointer is not valid"));
	}
}

MyUobjectClass.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "MyUobjectClass.generated.h"

DECLARE_MULTICAST_DELEGATE(FLandMarkGet);
DECLARE_DELEGATE(FThreadMessage);

UCLASS()
class MEDIAPIPE4UDEMO_API UMyUobjectClass : public UObject
{
	GENERATED_BODY()

public:
	static UMyUobjectClass* GetInstance();

	FLandMarkGet LandMarkGet;
	FThreadMessage ThreadMessage;

	bool bConditionTriggered = false;
	
};

MyUobjectClass.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyUobjectClass.h"

UMyUobjectClass* UMyUobjectClass::GetInstance()
{
	static UMyUobjectClass* SingInstance = nullptr;
	if (!SingInstance)
	{
		SingInstance = NewObject<UMyUobjectClass>();
		SingInstance->AddToRoot();
	}
	return SingInstance;
}

MyThreadClass.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "MyUobjectClass.h"
#include "HAL/Runnable.h"


class MEDIAPIPE4UDEMO_API UMyThreadClass : public FRunnable
{
public:
	UMyThreadClass();
	~UMyThreadClass();

	virtual bool Init() override;
	virtual uint32 Run() override;
	virtual void Stop() override;
	virtual void Exit() override;

	UMyUobjectClass* MyUobjectClass;
};

MyThreadClass.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyThreadClass.h"

#include "Engine/Engine.h"
#include "Windows/WindowsPlatformProcess.h"

UMyThreadClass::UMyThreadClass()
{
	MyUobjectClass = nullptr;
}

UMyThreadClass::~UMyThreadClass()
{
	
}

bool UMyThreadClass::Init()
{
	MyUobjectClass = UMyUobjectClass::GetInstance();
	if (MyUobjectClass)
	{
		return true;
	}
	return false;
}

uint32 UMyThreadClass::Run()
{
	FPlatformProcess::Sleep(5.0f);
	
	MyUobjectClass->bConditionTriggered = false;
	GEngine->AddOnScreenDebugMessage(-1,1.0f,FColor::Red,TEXT("this sleep finished"));
	return 0;
}

void UMyThreadClass::Stop()
{
	FRunnable::Stop();
}

void UMyThreadClass::Exit()
{
	if (MyUobjectClass->ThreadMessage.IsBound())
	{
		MyUobjectClass->ThreadMessage.Execute();
		FRunnable::Exit();
	}
}

MyActorClass.h

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyThreadClass.h"
#include "HAL/RunnableThread.h"

#include "MyActorClass.generated.h"

UCLASS()
class MEDIAPIPE4UDEMO_API AMyActorClass : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	AMyActorClass();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UPROPERTY(VisibleAnywhere)
	USceneComponent* SceneComponent;
	UPROPERTY(VisibleAnywhere)
	UStaticMeshComponent* StaticMeshComponent;
	UPROPERTY(BlueprintReadWrite)
	UStaticMesh* StaticMesh;

	TUniquePtr<UMyThreadClass> MyThreadClass;
	TUniquePtr<FRunnableThread> ThreadRunnable;

	
	void TiaoCallBack();
	void deletthread();
};

MyActorClass.cpp

cpp 复制代码
// Fill out your copyright notice in the Description page of Project Settings.


#include "MyActorClass.h"

#include "Engine/StaticMesh.h"

#include "Components/StaticMeshComponent.h"

// Sets default values
AMyActorClass::AMyActorClass()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	
	SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
	RootComponent = SceneComponent;
	StaticMeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComponent"));
	StaticMeshComponent->SetupAttachment(SceneComponent);
	StaticMesh = LoadObject<UStaticMesh>(nullptr,TEXT("/Engine/BasicShapes/Sphere.Sphere"));
	StaticMeshComponent->SetStaticMesh(StaticMesh);
	
}

// Called when the game starts or when spawned
void AMyActorClass::BeginPlay()
{
	Super::BeginPlay();
	StaticMeshComponent->SetSimulatePhysics(true);
	StaticMeshComponent->SetMassOverrideInKg(EName::None,10.f);

	UMyUobjectClass* MyUobjectClass = UMyUobjectClass::GetInstance();
	if (MyUobjectClass)
	{
		MyUobjectClass->LandMarkGet.AddUObject(this,&AMyActorClass::TiaoCallBack);
		MyUobjectClass->ThreadMessage.BindUObject(this,&AMyActorClass::deletthread);
	}
		
}

// Called every frame
void AMyActorClass::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void AMyActorClass::TiaoCallBack()
{
	FVector force = FVector(0.0f,0.0f,5000.0f);
	StaticMeshComponent->AddImpulse(force,NAME_None);
	
	MyThreadClass = MakeUnique<UMyThreadClass>();
	ThreadRunnable = TUniquePtr<FRunnableThread>(FRunnableThread::Create(MyThreadClass.Get(), TEXT("sleep 5.0f")));

}

void AMyActorClass::deletthread()
{
	ThreadRunnable.Reset();
	MyThreadClass.Reset();
}
相关推荐
侠客行03176 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
蛇皮划水怪6 小时前
深入浅出LangChain4J
java·langchain·llm
子兮曰6 小时前
OpenClaw入门:从零开始搭建你的私有化AI助手
前端·架构·github
吴仰晖6 小时前
使用github copliot chat的源码学习之Chromium Compositor
前端
1024小神6 小时前
github发布pages的几种状态记录
前端
老毛肚7 小时前
MyBatis体系结构与工作原理 上篇
java·mybatis
风流倜傥唐伯虎8 小时前
Spring Boot Jar包生产级启停脚本
java·运维·spring boot
不像程序员的程序媛8 小时前
Nginx日志切分
服务器·前端·nginx
Yvonne爱编码8 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚8 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言