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();
}
相关推荐
繁依Fanyi18 分钟前
用 CodeBuddy 实现「IdeaSpark 每日灵感卡」:一场 UI 与灵感的极简之旅
开发语言·前端·游戏·ui·编辑器·codebuddy首席试玩官
来自星星的坤2 小时前
【Vue 3 + Vue Router 4】如何正确重置路由实例(resetRouter)——避免“VueRouter is not defined”错误
前端·javascript·vue.js
字节源流5 小时前
关于maven的依赖下不下来的问题
java·maven
pjx9876 小时前
服务间的“握手”:OpenFeign声明式调用与客户端负载均衡
java·运维·spring·负载均衡
prinrf('千寻)6 小时前
MyBatis-Plus 的 updateById 方法不更新 null 值属性的问题
java·开发语言·mybatis
香蕉可乐荷包蛋6 小时前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
老华带你飞6 小时前
实习记录小程序|基于SSM+Vue的实习记录小程序设计与实现(源码+数据库+文档)
java·数据库·spring boot·小程序·论文·毕设·实习记录小程序
在未来等你7 小时前
互联网大厂Java求职面试:AI与大模型应用集成及云原生挑战
java·微服务·ai·kubernetes·大模型·embedding·spring ai
未来之窗软件服务7 小时前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
源码技术栈7 小时前
SaaS基于云计算、大数据的Java云HIS平台信息化系统源码
java·大数据·云计算·云his·his系统·云医院·区域his