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();
}
相关推荐
有梦想的刺儿11 分钟前
webWorker基本用法
前端·javascript·vue.js
P.H. Infinity15 分钟前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天19 分钟前
java的threadlocal为何内存泄漏
java
caridle31 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
cy玩具31 分钟前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
^velpro^36 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋340 分钟前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花44 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端1 小时前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan1 小时前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava