延时优化完成
This commit is contained in:
@@ -70,38 +70,14 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L
|
|||||||
|
|
||||||
|
|
||||||
imageAnalyzer.setAnalyzer(backgroundExecutor, new ImageAnalysis.Analyzer() {
|
imageAnalyzer.setAnalyzer(backgroundExecutor, new ImageAnalysis.Analyzer() {
|
||||||
private long lastCaptureTime = 0;
|
|
||||||
private int frameCount = 0;
|
private int frameCount = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void analyze(@NonNull ImageProxy image) {
|
public void analyze(@NonNull ImageProxy image) {
|
||||||
frameCount++;
|
frameCount++;
|
||||||
long currentTime = System.currentTimeMillis();
|
|
||||||
try {
|
try {
|
||||||
long captureTimeNs = image.getImageInfo().getTimestamp();
|
|
||||||
long analyzeTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
// 简单直接的计算方法
|
|
||||||
long captureTimeMs = TimeUnit.NANOSECONDS.toMillis(captureTimeNs);
|
|
||||||
long latency = analyzeTime - captureTimeMs;
|
|
||||||
|
|
||||||
// 帧率计算
|
|
||||||
if (lastCaptureTime > 0) {
|
|
||||||
long frameInterval = captureTimeMs - lastCaptureTime;
|
|
||||||
double fps = 1000.0 / frameInterval;
|
|
||||||
|
|
||||||
if (frameCount % 10 == 0) { // 每30帧打印一次
|
|
||||||
Log.i("TimeLatency", String.format(
|
|
||||||
"Frame %d - Latency: %d ms, FPS: %.1f",
|
|
||||||
frameCount, latency, fps
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastCaptureTime = captureTimeMs;
|
|
||||||
|
|
||||||
processImageForVulkan(image);
|
processImageForVulkan(image);
|
||||||
if(frameCount %2 == 0)
|
if(frameCount %3 == 0)
|
||||||
{
|
{
|
||||||
detectFace(image);
|
detectFace(image);
|
||||||
}
|
}
|
||||||
@@ -186,7 +162,6 @@ public class FaceActivity extends GameActivity implements FaceLandmarkerHelper.L
|
|||||||
0.5f,
|
0.5f,
|
||||||
0.5f,
|
0.5f,
|
||||||
1,
|
1,
|
||||||
0,
|
|
||||||
RunningMode.LIVE_STREAM,
|
RunningMode.LIVE_STREAM,
|
||||||
FaceActivity.this,
|
FaceActivity.this,
|
||||||
FaceActivity.this
|
FaceActivity.this
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ class FaceLandmarkerHelper(
|
|||||||
var minFaceTrackingConfidence: Float = DEFAULT_FACE_TRACKING_CONFIDENCE,
|
var minFaceTrackingConfidence: Float = DEFAULT_FACE_TRACKING_CONFIDENCE,
|
||||||
var minFacePresenceConfidence: Float = DEFAULT_FACE_PRESENCE_CONFIDENCE,
|
var minFacePresenceConfidence: Float = DEFAULT_FACE_PRESENCE_CONFIDENCE,
|
||||||
var maxNumFaces: Int = DEFAULT_NUM_FACES,
|
var maxNumFaces: Int = DEFAULT_NUM_FACES,
|
||||||
var currentDelegate: Int = DELEGATE_CPU,
|
var runningMode: RunningMode = RunningMode.LIVE_STREAM,
|
||||||
var runningMode: RunningMode = RunningMode.IMAGE,
|
|
||||||
val context: Context,
|
val context: Context,
|
||||||
// this listener is only used when running in RunningMode.LIVE_STREAM
|
// this listener is only used when running in RunningMode.LIVE_STREAM
|
||||||
val faceLandmarkerHelperListener: LandmarkerListener? = null
|
val faceLandmarkerHelperListener: LandmarkerListener? = null
|
||||||
@@ -50,14 +49,7 @@ class FaceLandmarkerHelper(
|
|||||||
val baseOptionBuilder = BaseOptions.builder()
|
val baseOptionBuilder = BaseOptions.builder()
|
||||||
|
|
||||||
// Use the specified hardware for running the model. Default to CPU
|
// Use the specified hardware for running the model. Default to CPU
|
||||||
when (currentDelegate) {
|
baseOptionBuilder.setDelegate(Delegate.GPU)
|
||||||
DELEGATE_CPU -> {
|
|
||||||
baseOptionBuilder.setDelegate(Delegate.CPU)
|
|
||||||
}
|
|
||||||
DELEGATE_GPU -> {
|
|
||||||
baseOptionBuilder.setDelegate(Delegate.GPU)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
baseOptionBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)
|
baseOptionBuilder.setModelAssetPath(MP_FACE_LANDMARKER_TASK)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import android.os.Bundle;
|
|||||||
import com.hmwl.face_sdk.FaceActivity;
|
import com.hmwl.face_sdk.FaceActivity;
|
||||||
public class MainActivity extends FaceActivity{
|
public class MainActivity extends FaceActivity{
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState){
|
protected void onCreate(Bundle savedInstanceState)
|
||||||
|
{
|
||||||
|
SetInitArg("{\"action_fps\":3,\"motion\":{\"png_name\":\"demo\",\"png_num\":1,\"show_type\":\"direction\",\"step\":\"press2\",\"technique\":\"base_makeup\",\"type\":\"bottom_makeup\"},\"zoom\":1.5}");
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
//这个是设置接口的参数,采用json传递,可以保证接口灵活性
|
//这个是设置接口的参数,采用json传递,可以保证接口灵活性
|
||||||
|
|||||||
+104
-23
@@ -1,6 +1,9 @@
|
|||||||
#include "FaceApp.h"
|
#include "FaceApp.h"
|
||||||
#include "hardcode_data.h"
|
#include "hardcode_data.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -24,15 +27,89 @@ void ReceiveFacePoint(float* pos, int pointCount, int width, int height)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 定义帧数据结构
|
||||||
|
struct FrameData {
|
||||||
|
uint8_t* data;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int rowStride;
|
||||||
|
size_t dataSize;
|
||||||
|
|
||||||
|
FrameData(uint8_t* d, int w, int h, int rs, size_t ds)
|
||||||
|
: data(nullptr), width(w), height(h), rowStride(rs), dataSize(ds) {
|
||||||
|
// 深拷贝数据
|
||||||
|
if (d && ds > 0) {
|
||||||
|
data = new uint8_t[dataSize];
|
||||||
|
memcpy(data, d, dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~FrameData() {
|
||||||
|
if (data) {
|
||||||
|
delete[] data;
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁止拷贝构造和赋值(使用移动语义)
|
||||||
|
FrameData(const FrameData&) = delete;
|
||||||
|
FrameData& operator=(const FrameData&) = delete;
|
||||||
|
|
||||||
|
// 移动构造
|
||||||
|
FrameData(FrameData&& other) noexcept
|
||||||
|
: data(other.data), width(other.width), height(other.height),
|
||||||
|
rowStride(other.rowStride), dataSize(other.dataSize) {
|
||||||
|
other.data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动赋值
|
||||||
|
FrameData& operator=(FrameData&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
if (data) delete[] data;
|
||||||
|
data = other.data;
|
||||||
|
width = other.width;
|
||||||
|
height = other.height;
|
||||||
|
rowStride = other.rowStride;
|
||||||
|
dataSize = other.dataSize;
|
||||||
|
other.data = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 全局队列和互斥锁
|
||||||
|
std::queue<FrameData> frameQueue;
|
||||||
|
std::mutex queueMutex;
|
||||||
|
const int MAX_QUEUE_SIZE = 4;
|
||||||
|
|
||||||
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize)
|
void TextureLoadProcessWithVulkan(uint8_t* data, int width, int height, int rowStride, size_t dataSize)
|
||||||
{
|
{
|
||||||
if(FaceApp::Get()->isInited())
|
if (!FaceApp::Get()->isInited()) {
|
||||||
{
|
return;
|
||||||
Texture& tex_bg = FaceApp::Get()->tex_bg;
|
}
|
||||||
FaceApp::Get()->processWithVulkan(data, width, height, rowStride, dataSize, tex_bg, false);
|
|
||||||
}
|
std::lock_guard<std::mutex> lock(queueMutex);
|
||||||
|
|
||||||
|
// 添加新帧数据到队列
|
||||||
|
frameQueue.emplace(data, width, height, rowStride, dataSize);
|
||||||
|
|
||||||
|
// 如果队列大小达到阈值,开始处理最旧的一帧
|
||||||
|
if (frameQueue.size() >= MAX_QUEUE_SIZE) {
|
||||||
|
Texture& tex_bg = FaceApp::Get()->tex_bg;
|
||||||
|
FrameData& oldestFrame = frameQueue.front();
|
||||||
|
|
||||||
|
FaceApp::Get()->processWithVulkan(
|
||||||
|
oldestFrame.data,
|
||||||
|
oldestFrame.width,
|
||||||
|
oldestFrame.height,
|
||||||
|
oldestFrame.rowStride,
|
||||||
|
oldestFrame.dataSize,
|
||||||
|
tex_bg,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
frameQueue.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FaceApp::LoadOBJ(const std::string& filename,
|
bool FaceApp::LoadOBJ(const std::string& filename,
|
||||||
@@ -370,27 +447,31 @@ void FaceApp::create_face_pipelines()
|
|||||||
|
|
||||||
void FaceApp::setup_descriptor_pool()
|
void FaceApp::setup_descriptor_pool()
|
||||||
{
|
{
|
||||||
VkDescriptorPoolSize descriptor_pool_size{};
|
// 保守估计:假设每个描述符集可能有多个绑定
|
||||||
descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
const uint32_t setsCount = kMaxTexture;
|
||||||
descriptor_pool_size.descriptorCount = 2;
|
const uint32_t multiplier = 3; // 安全系数
|
||||||
|
|
||||||
VkDescriptorPoolSize descriptor_pool_image_size{};
|
std::vector<VkDescriptorPoolSize> pool_sizes = {
|
||||||
descriptor_pool_image_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
{
|
||||||
descriptor_pool_image_size.descriptorCount = kMaxTexture + 4;
|
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
.descriptorCount = setsCount * multiplier
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
.descriptorCount = setsCount * multiplier
|
||||||
|
},
|
||||||
|
// 如果需要其他类型的描述符,在这里添加
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDescriptorPoolCreateInfo descriptor_pool_info{};
|
||||||
|
descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
|
descriptor_pool_info.poolSizeCount = static_cast<uint32_t>(pool_sizes.size());
|
||||||
|
descriptor_pool_info.pPoolSizes = pool_sizes.data();
|
||||||
|
descriptor_pool_info.maxSets = setsCount * 2; // 额外预留一些集合
|
||||||
|
descriptor_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||||
|
|
||||||
std::vector<VkDescriptorPoolSize> pool_sizes;
|
VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool));
|
||||||
pool_sizes.push_back(descriptor_pool_size);
|
|
||||||
pool_sizes.push_back(descriptor_pool_image_size);
|
|
||||||
|
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo descriptor_pool_info{};
|
|
||||||
descriptor_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
||||||
descriptor_pool_info.poolSizeCount = pool_sizes.size();
|
|
||||||
descriptor_pool_info.pPoolSizes = pool_sizes.data();
|
|
||||||
descriptor_pool_info.maxSets = kMaxTexture + 4 + 2;
|
|
||||||
|
|
||||||
VK_CHECK(vkCreateDescriptorPool(device, &descriptor_pool_info, nullptr, &descriptor_pool));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1024,7 +1105,7 @@ void FaceApp::changeMotion(Motion& motion)
|
|||||||
loadTextureExample(path_name_ex, m_texs_ex[i], true);
|
loadTextureExample(path_name_ex, m_texs_ex[i], true);
|
||||||
#else
|
#else
|
||||||
loadTexture(path_name, m_texs[i], true);
|
loadTexture(path_name, m_texs[i], true);
|
||||||
loadTexture(path_name, path_name_ex[i], true);
|
loadTexture(path_name, m_texs_ex[i], true);
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user