From 4febb5fb7f489725e09e1e28b590e20e31fbbb2b Mon Sep 17 00:00:00 2001 From: luocai Date: Wed, 5 Jun 2024 12:13:10 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=8A=A0=E5=85=A5note=20id=E5=A4=84=E7=90=86?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Analyser/ModuleCommunication.cpp | 56 ++++++++++++++++++++++++++++++-- Analyser/ModuleCommunication.h | 26 +++++++++++++++ Analyser/Widget.cpp | 33 +++++++++++++++++++ Analyser/Widget.h | 8 +++++ Readme.md | 7 +++- 5 files changed, 126 insertions(+), 4 deletions(-) diff --git a/Analyser/ModuleCommunication.cpp b/Analyser/ModuleCommunication.cpp index e1fc86c..9197e43 100644 --- a/Analyser/ModuleCommunication.cpp +++ b/Analyser/ModuleCommunication.cpp @@ -58,6 +58,18 @@ void ModuleCommunication::enroll(const std::string &username, uint8_t timeout) { LOG_CAT(info, GUI) << Separator; } +void ModuleCommunication::enrollEx(const std::string &username, uint8_t timeout) { + EnrollData data = {0}; + data.timeout = timeout; + strncpy(reinterpret_cast(data.username), username.c_str(), sizeof(data.username)); + auto [frameData, frameSize] = generateFrame(EnrollGetImage, reinterpret_cast(&data), sizeof(data)); + m_serialPort->write(reinterpret_cast(frameData), frameSize); + + LOG_CAT(info, GUI) << "发送注册指令: " << protocolDataFormatString(frameData, frameSize); + LOG_CAT(info, GUI) << "用户名: " << username << ", 超时时间: " << static_cast(timeout) << "s"; + LOG_CAT(info, GUI) << Separator; +} + void ModuleCommunication::deleteUser(uint16_t userid) { uint16_t n = htons(userid); auto [frameData, frameSize] = generateFrame(DeleteUser, reinterpret_cast(&n), sizeof(n)); @@ -74,6 +86,17 @@ void ModuleCommunication::deleteAll() { LOG_CAT(info, GUI) << Separator; } +void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) { + ImageSliceRequest request; + request.offset = htonl(offset); + request.size = htonl(size); + auto [data, frameSize] = + generateFrame(GetEnrolledImage, reinterpret_cast(&request), sizeof(request)); + m_serialPort->write(reinterpret_cast(data), frameSize); + LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize); + LOG_CAT(info, GUI) << Separator; +} + void ModuleCommunication::requestPalmFeature(uint16_t userid) { uint16_t n = htons(userid); auto [frameData, frameSize] = generateFrame(RequestPalmFeature, reinterpret_cast(&n), sizeof(n)); @@ -151,6 +174,28 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } + case EnrollGetImage: { + LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); + if (result == Success) { + auto info = reinterpret_cast(data + 7); + uint16_t lineSize = ntohs(info->lineSize); + uint16_t height = ntohs(info->height); + LOG_CAT(info, GUI) << "图片大小: " << ntohs(info->width) << "x" << height + << ", line size: " << lineSize; + emit newEnrolledImageInfo(lineSize * height, info->md5); + } + LOG_CAT(info, GUI) << Separator; + break; + } + case GetEnrolledImage: { + // LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); + if (result == Success) { + auto info = reinterpret_cast(data + 7); + emit newImageSliceData(std::vector(info->data, info->data + ntohl(info->size))); + } + // LOG_CAT(info, GUI) << Separator; + break; + } case DeleteUser: { if (result == Success) { LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); @@ -180,8 +225,7 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { << ", 特征值长度: " << ntohs(info->featureTotalSize); PalmFeature feature; feature.username = std::string_view(reinterpret_cast(info->username)); - const uint8_t *start = data + 7 + sizeof(PalmFeatureHeader); - feature.feature = std::vector(start, start + ntohs(info->featureTotalSize)); + feature.feature = std::vector(info->feature, info->feature + ntohs(info->featureTotalSize)); emit newPalmFeature(feature); } LOG_CAT(info, GUI) << Separator; @@ -211,11 +255,17 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } - case 0x01: { // 模组返回的数据为当前帧的手掌状态 + case PalmState: { // 模组返回的数据为当前帧的手掌状态 auto info = reinterpret_cast(data + 7); LOG(info) << info->state; break; } + case UnknownError: { + LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); + LOG_CAT(info, GUI) << "未知错误。"; + LOG_CAT(info, GUI) << Separator; + break; + } default: LOG(warning) << "unknown note command: 0x" << (static_cast(noteId) & 0xff) << ", data: " << protocolDataFormatString(data, size); diff --git a/Analyser/ModuleCommunication.h b/Analyser/ModuleCommunication.h index 7cb5059..1c033d3 100644 --- a/Analyser/ModuleCommunication.h +++ b/Analyser/ModuleCommunication.h @@ -19,6 +19,8 @@ public: Reset = 0x10, Verify = 0x12, EnrollSingle = 0x1D, + EnrollGetImage = 0x1E, + GetEnrolledImage = 0x1F, DeleteUser = 0x20, DeleteAll = 0x21, RegisterPalmFeature = 0xF9, @@ -27,6 +29,8 @@ public: enum NoteId : uint8_t { Ready = 0x00, + PalmState = 0x01, + UnknownError = 0x02, }; enum MessageStatus : uint8_t { Success = 0, @@ -77,6 +81,23 @@ public: uint8_t face_direction; // depleted, user ignore this field }; + struct EnrolledImageReply { + uint16_t width; + uint16_t lineSize; + uint16_t height; + uint8_t md5[16]; + }; + + struct ImageSliceRequest { + uint32_t offset; + uint32_t size; + }; + + struct ImageSliceReply { + uint32_t size; + uint8_t data[0]; + }; + struct VerifyDataReply { uint16_t userid; uint8_t username[UsernameSize]; // 32Bytes uint8_t admin; @@ -89,6 +110,7 @@ public: uint8_t admin; // 是否管理员,YES:1 NO:0 uint8_t featureDataMd5[16]; // 整体特征数据的MD5值 uint16_t featureTotalSize; // 特征数据总长度 + uint8_t feature[0]; }; #pragma pack() @@ -98,13 +120,17 @@ public: void reset(); void enroll(const std::string &username, uint8_t timeout); + void enrollEx(const std::string &username, uint8_t timeout); void deleteUser(uint16_t userid); void deleteAll(); + void requestEnrolledImage(uint32_t offset, uint32_t size); void requestPalmFeature(uint16_t userid); void enrollPalmFeature(uint16_t userid, const PalmFeature &feature); signals: void newPalmFeature(const PalmFeature &feature); + void newEnrolledImageInfo(uint32_t size, const uint8_t *md5); + void newImageSliceData(const std::vector &data); protected: void processPackage(const uint8_t *data, uint16_t size); diff --git a/Analyser/Widget.cpp b/Analyser/Widget.cpp index 1748775..0723d84 100644 --- a/Analyser/Widget.cpp +++ b/Analyser/Widget.cpp @@ -128,6 +128,10 @@ QGroupBox *Widget::initializeEnrollGroupBox() { connect(m_enrollButton, &QPushButton::clicked, this, &Widget::onEnrollButtonClicked); layout->addRow("", m_enrollButton); + auto enrollExButton = new QPushButton("注册(EX)"); + connect(enrollExButton, &QPushButton::clicked, this, &Widget::onEnrollExButtonClicked); + layout->addRow("", enrollExButton); + ret->setLayout(layout); return ret; } @@ -211,6 +215,26 @@ void Widget::onNewPalmFeature(const PalmFeature &feature) { } } +void Widget::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) { + m_enrolledImageSize = size; + m_receivedImageSize = 0; + m_communication->requestEnrolledImage(0, 1024); + m_ofs = std::make_shared("palm.yuv", std::ofstream::binary); +} + +void Widget::onNewImageSliceData(const std::vector &data) { + m_receivedImageSize += data.size(); + LOG(info) << "onNewImageSliceData:" << data.size() << ", already received: " << m_receivedImageSize + << ", total size: " << m_enrolledImageSize; + m_ofs->write(reinterpret_cast(data.data()), data.size()); + if (m_receivedImageSize < m_enrolledImageSize) { + m_communication->requestEnrolledImage(m_receivedImageSize, 1024); + } else { + LOG(info) << "request finished."; + m_ofs.reset(); + } +} + void Widget::onSerialConnectButtonClicked() { auto button = dynamic_cast(sender()); if (button == nullptr) return; @@ -219,6 +243,9 @@ void Widget::onSerialConnectButtonClicked() { auto portName = m_serialComboBox->currentText(); m_communication = std::make_shared(); connect(m_communication.get(), &ModuleCommunication::newPalmFeature, this, &Widget::onNewPalmFeature); + connect(m_communication.get(), &ModuleCommunication::newEnrolledImageInfo, this, + &Widget::onNewEnrolledImageInfo); + connect(m_communication.get(), &ModuleCommunication::newImageSliceData, this, &Widget::onNewImageSliceData); bool status = m_communication->open(portName); if (status) { m_commandGroupBox->setEnabled(true); @@ -248,6 +275,12 @@ void Widget::onEnrollButtonClicked() { m_communication->enroll(name.toStdString(), timeout); } +void Widget::onEnrollExButtonClicked() { + auto name = m_enrollNameEdit->text(); + auto timeout = m_enrollTimeoutEdit->text().toInt(); + m_communication->enrollEx(name.toStdString(), timeout); +} + void Widget::onVerifyButtonClicked() { if (!m_communication) return; auto timeout = m_verifyTimeoutEdit->text().toInt(); diff --git a/Analyser/Widget.h b/Analyser/Widget.h index f56ce83..02a454b 100644 --- a/Analyser/Widget.h +++ b/Analyser/Widget.h @@ -3,6 +3,7 @@ #include "DataStructure.h" #include +#include class QPushButton; class QTextBrowser; @@ -29,6 +30,7 @@ protected: void onUvcRefreshButtonClicked(); void onEnrollButtonClicked(); + void onEnrollExButtonClicked(); void onVerifyButtonClicked(); void onDeleteAllButtonClicked(); void onDeleteButtonClicked(); @@ -44,6 +46,8 @@ protected: QGroupBox *initializeUvcGroupBox(); void onNewPalmFeature(const PalmFeature &feature); + void onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5); + void onNewImageSliceData(const std::vector &data); private: QComboBox *m_serialComboBox = nullptr; @@ -69,6 +73,10 @@ private: PalmFeatureTableModel *m_featureModel = nullptr; QTableView *m_featureTableView = nullptr; + + uint32_t m_enrolledImageSize = 0; + uint32_t m_receivedImageSize = 0; + std::shared_ptr m_ofs; }; #endif // WIDGET_H diff --git a/Readme.md b/Readme.md index 00a1d6d..3206df0 100644 --- a/Readme.md +++ b/Readme.md @@ -11,7 +11,12 @@ palmDetectionProcess facePalmDetectionProcess # 处理每帧,在MPP的回调函数里面 uart_msg_proc() -> cmd_exec()执行串口协议命令 -sock_cmd_exec() 这个函数是干啥的? +sock_cmd_exec() 内部线程逻辑之间通信 + +线程函数frame_proc_task() +algo_cb()->onFacePalmDetectionPassed()->app_server_alive()->sock_cmd_exec:SOCK_CMD__ALIVE_PALM + +ST__PlamRegister()->__PalmRegister() -> PalmFeatureExtract() -> spv2_get_feature() ```