张洋 1 месяц назад
Родитель
Сommit
7fb43526e8

BIN
bin/Win32/Debug/zhipuzi_pos_windows/ai/yolo26n-cls-zhipuzi-448.onnx


BIN
bin/Win32/Debug/zhipuzi_pos_windows/ai/yolo26s-cls-zhipuzi-448.onnx


BIN
bin/Win32/Release/zhipuzi_pos_windows/ai/yolo26n-cls-zhipuzi-448.onnx


BIN
bin/Win32/Release/zhipuzi_pos_windows/ai/yolo26s-cls-zhipuzi-448.onnx


BIN
res/ai/yolo26n-cls-zhipuzi-448.onnx


BIN
res/ai/yolo26s-cls-zhipuzi-448.onnx


+ 1 - 3
zhipuzi_pos_windows/ai/SQLiteVecManager.cpp

@@ -6,8 +6,6 @@
 #include <cmath>
 #include <algorithm>
 
-#include "../tool/debuglog.h"
-
 SQLiteVecManager::SQLiteVecManager()
 {
 	db = NULL;
@@ -59,7 +57,7 @@ bool SQLiteVecManager::initializeDatabase(int vectorDimension)
 		assert(rc == SQLITE_OK);
 
 		rc = sqlite3_step(stmt);
-		DEBUG_HELPER::debug_printf("sqlite_version=%s, vec_version=%s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));
+		CLewaimaiLog::OutputDebugMessageFormat("sqlite_version=%s, vec_version=%s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));
 		sqlite3_finalize(stmt);
 
 		std::cout << "使用sqlite-vec扩展进行向量存储和搜索" << std::endl;

+ 37 - 38
zhipuzi_pos_windows/ai/YoloFeatureManager.cpp

@@ -8,8 +8,6 @@
 #include <numeric>
 #include <sstream>
 
-#include "../tool/debuglog.h"
-
 #include "../worker/CVideoCaptureWorker.h"
 
 #include "YoloClassName.h"
@@ -46,7 +44,7 @@ void YoloFeatureManager::loadModel()
 	catch (const std::exception& e)
 	{
 		std::string aa = std::string(e.what());
-		DEBUG_LOG(("加载模型失败: " + std::string(e.what())).c_str());
+		CLewaimaiLog::OutputDebugMessage("加载模型失败: " + std::string(e.what()));
 		return;
 	}
 }
@@ -72,7 +70,7 @@ void YoloFeatureManager::loadModelForOpenVINO()
 	catch (const std::exception& e)
 	{
 		std::string aa = std::string(e.what());
-		DEBUG_LOG(("加载模型失败: " + std::string(e.what())).c_str());
+		CLewaimaiLog::OutputDebugMessage(("加载模型失败: " + std::string(e.what())).c_str());
 		return;
 	}
 }
@@ -152,12 +150,12 @@ std::vector<float> YoloFeatureManager::extractFeatures(cv::Mat& image)
 		}
 
 		float norm_before = cv::norm(featureMat, cv::NORM_L2);
-		DEBUG_HELPER::debug_printf("归一化前 norm:%.6f\n", norm_before);
+		CLewaimaiLog::OutputDebugMessageFormat("归一化前 norm:%.6f\n", norm_before);
 
 		cv::normalize(featureMat, featureMat, 1.0, 0.0, cv::NORM_L2); //L2归一化
 
 		float norm_after = cv::norm(featureMat, cv::NORM_L2);
-		DEBUG_HELPER::debug_printf("归一化后 norm:%.6f\n", norm_after);
+		CLewaimaiLog::OutputDebugMessageFormat("归一化后 norm:%.6f\n", norm_after);
 
 		// 将Mat格式的特征转换为vector<float>(方便后续计算/存储)
 		std::vector<float> feature_vector;
@@ -168,56 +166,54 @@ std::vector<float> YoloFeatureManager::extractFeatures(cv::Mat& image)
 
 		auto duration_1 = std::chrono::duration_cast<std::chrono::milliseconds>(time_2 - time_1);
 		std::wstring msg = L"图片处理耗时: " + std::to_wstring(duration_1.count()) + L" 毫秒";
-		DEBUG_LOG(msg.c_str());
+		CLewaimaiLog::OutputDebugMessage(msg.c_str());
 
 		auto duration_2 = std::chrono::duration_cast<std::chrono::milliseconds>(time_3 - time_2);
 		std::wstring msg2 = L"模型推理耗时: " + std::to_wstring(duration_2.count()) + L" 毫秒";
-		DEBUG_LOG(msg2.c_str());
+		CLewaimaiLog::OutputDebugMessage(msg2.c_str());
 
 		auto totalDuration = std::chrono::duration_cast<std::chrono::milliseconds>(time_3 - time_1);
 		std::wstring msg4 = L"总耗时: " + std::to_wstring(totalDuration.count()) + L" 毫秒";
-		DEBUG_LOG(msg4.c_str());
+		CLewaimaiLog::OutputDebugMessage(msg4.c_str());
 
 		return feature_vector;
 	}
 	catch (const std::exception& e)
 	{
 		std::string aa = std::string(e.what());
-		DEBUG_LOG(("提取特征失败: " + std::string(e.what())).c_str());
+		CLewaimaiLog::OutputDebugMessage("提取特征失败: " + std::string(e.what()));
 		return {};
 	}
 }
 
-namespace
+void YoloFeatureManager::DebugTopResults(const cv::Mat& output, int topK)
 {
-	void DebugTopResults(const cv::Mat& output, int topK = 10)
-	{
-		cv::Mat scores = output.reshape(1, 1);
-		const int count = scores.cols;
-		topK = std::min(topK, count);
-
-		std::vector<int> indices(count);
-		std::iota(indices.begin(), indices.end(), 0);
+	cv::Mat scores = output.reshape(1, 1);
+	const int count = scores.cols;
+	topK = std::min(topK, count);
 
-		std::partial_sort(indices.begin(), indices.begin() + topK, indices.end(),
-			[&scores](int left, int right)
-			{
-				return scores.at<float>(0, left) > scores.at<float>(0, right);
-			});
+	std::vector<int> indices(count);
+	std::iota(indices.begin(), indices.end(), 0);
 
-		std::string message = "YOLO分类 Top " + std::to_string(topK) + " 结果:";
-		for (int i = 0; i < topK; ++i)
+	std::partial_sort(indices.begin(), indices.begin() + topK, indices.end(),
+		[&scores](int left, int right)
 		{
-			const int classId = indices[i];
-			const float confidence = scores.at<float>(0, classId);
+			return scores.at<float>(0, left) > scores.at<float>(0, right);
+		});
 
-			message += "\nTop " + std::to_string(i + 1) +
-				": id=" + std::to_string(classId) +
-				", confidence=" + std::to_string(confidence);
-		}
+	std::string message = "YOLO分类 Top " + std::to_string(topK) + " 结果:";
+	for (int i = 0; i < topK; ++i)
+	{
+		const int classId = indices[i];
+		const float confidence = scores.at<float>(0, classId);
 
-		DEBUG_LOG(message.c_str());
+		message += "\nTop " + std::to_string(i + 1) +
+			": id=" + std::to_string(classId) +
+			": name=" + this->getClassName(classId) +
+			", confidence=" + std::to_string(confidence);
 	}
+
+	m_topResultMessage = message;
 }
 
 std::string YoloFeatureManager::Class(cv::Mat & image)
@@ -239,13 +235,16 @@ std::string YoloFeatureManager::Class(cv::Mat & image)
 		// ====================== 模型推理 ======================
 		cv::Mat output = net.forward(); // 输出形状:1x1000(对应ImageNet 1000类)
 
-		DebugTopResults(output);
+		this->DebugTopResults(output);
 
 		auto time_2 = std::chrono::high_resolution_clock::now();
-
 		auto totalDuration = std::chrono::duration_cast<std::chrono::milliseconds>(time_2 - time_1);
-		std::wstring msg = L"Class 总耗时: " + std::to_wstring(totalDuration.count()) + L" 毫秒";
-		DEBUG_LOG(msg.c_str());
+
+		std::wstring msg = L"Class 总耗时: " + std::to_wstring(totalDuration.count()) + L" 毫秒\r\n";
+		msg += CLewaimaiString::ANSIToUnicode(m_topResultMessage);
+
+		CLewaimaiLog::OutputDebugMessage(msg.c_str());
+		CLewaimaiLog::OutputMessageBox(msg.c_str());
 
 		// ====================== 解析结果 ======================
 		int topClassIdx = this->getTopClass(output);
@@ -264,7 +263,7 @@ std::string YoloFeatureManager::Class(cv::Mat & image)
 	}
 	catch (const std::exception& e)
 	{
-		DEBUG_LOG(("YOLO分类失败: " + std::string(e.what())).c_str());
+		CLewaimaiLog::OutputDebugMessage(("YOLO分类失败: " + std::string(e.what())).c_str());
 		return {};
 	}
 	

+ 9 - 0
zhipuzi_pos_windows/ai/YoloFeatureManager.h

@@ -33,6 +33,13 @@ public:
 
 	void loadModelForOpenVINO();
 
+	void DebugTopResults(const cv::Mat& output, int topK = 10);
+
+	std::string getTopResultMessage() const
+	{
+		return m_topResultMessage;
+	}
+
 	// 提取特征
 	std::vector<float> extractFeatures(const std::string & imagePath);
 
@@ -51,4 +58,6 @@ private:
 	void drawChineseText(cv::Mat & img, const wchar_t * text, cv::Point pos, cv::Scalar color, int fontSize);
 
 	std::mutex m_mutex; // 互斥锁,保护模型加载和推理过程
+
+	std::string m_topResultMessage; // 用于存储调试信息
 };

+ 4 - 0
zhipuzi_pos_windows/helper/CLewaimaiLog.cpp

@@ -1,6 +1,10 @@
 #include "../pch/pch.h"
 #include "CLewaimaiLog.h"
 
+#include <windows.h>
+#include <sstream>
+#include <cstdio>
+
 CLewaimaiLog::CLewaimaiLog()
 {
 	

+ 78 - 0
zhipuzi_pos_windows/helper/CLewaimaiLog.h

@@ -8,6 +8,9 @@
 /*
 日志库头文件
 */
+#include <Windows.h>
+#include <string>
+
 #include <log4cplus/logger.h>
 #include <log4cplus/fileappender.h>
 #include <log4cplus/layout.h>
@@ -25,5 +28,80 @@ public:
 	~CLewaimaiLog();
 
 	void Init();
+
+	//把消息输出到调试控制台(unicode版本)
+	static void OutputDebugMessage(const std::wstring& message)
+	{
+		std::wostringstream __oss;
+		__oss << L"[" << __func__ << L"]@" << __FILE__ << L":" << __LINE__ << L": " << message << L"\r\n";
+		::OutputDebugStringW(__oss.str().c_str());
+	}
+
+	//把消息输出到调试控制台(ansi版本)
+	static void OutputDebugMessage(const std::string& message)
+	{
+		std::ostringstream __oss;
+		__oss << "[" << __func__ << "]@" << __FILE__ << ":" << __LINE__ << ": " << message << "\r\n";
+		::OutputDebugStringA(__oss.str().c_str());
+	}
+
+	//把消息输出到调试控制台(格式化版本)
+	static void OutputDebugMessageFormat(const char* format, ...)
+	{
+		va_list args;
+		va_start(args, format);
+		vprintf(format, args); // 原生打印到控制台(或重定向的输出)
+		char buffer[1024]; // 创建一个足够大的缓冲区来存储格式化后的字符串(可选)
+		vsnprintf(buffer, sizeof(buffer), format, args); // 将格式化后的字符串存储到buffer中(可选)
+		va_end(args); // 清理变量参数列表(optional)
+
+		CLewaimaiLog::OutputDebugMessage(buffer);
+	}
+
+	//把消息输出到调试控制台(格式化版本)
+	static void OutputDebugMessageFormat(const wchar_t* format, ...)
+	{
+		va_list args;
+		va_start(args, format);
+
+		va_list consoleArgs;
+		va_copy(consoleArgs, args);
+		vwprintf(format, consoleArgs);
+		va_end(consoleArgs);
+
+		wchar_t buffer[1024];
+		va_list formatArgs;
+		va_copy(formatArgs, args);
+		vswprintf(buffer, _countof(buffer), format, formatArgs);
+		va_end(formatArgs);
+
+		va_end(args);
+
+		::OutputDebugStringW(buffer);
+	}
+
+	//把消息输出到消息框(unicode版本)
+	static void OutputMessageBox(const std::wstring& message)
+	{
+		::MessageBoxW(nullptr, message.c_str(), L"调试信息", MB_OK);
+	}
+
+	//把消息输出到消息框(ansi版本)
+	static void OutputMessageBox(const std::string& message)
+	{
+		::MessageBoxA(nullptr, message.c_str(), "调试信息", MB_OK);
+	}
+
+	//把消息输出到消息框(格式化版本)
+	static void OutputMessageBoxFormat(LPCTSTR lpFormat, ...)
+	{
+		TCHAR szBuffer[1024] = { 0 };
+		va_list argList;
+		va_start(argList, lpFormat);
+		_vstprintf_s(szBuffer, _countof(szBuffer), lpFormat, argList);
+		va_end(argList);
+
+		::MessageBox(nullptr, szBuffer, _T("日志信息"), MB_OK);
+	}
 };
 

+ 0 - 1
zhipuzi_pos_windows/pch/pch.h

@@ -69,7 +69,6 @@ using namespace rapidjson;
 #include "../helper/CLewaimaiTime.h"
 
 #include "../tool/CSetting.h"
-#include "../tool/debuglog.h"
 
 #include "../network/CZhipuziHttpClient.h"
 

+ 8 - 8
zhipuzi_pos_windows/tool/CAppEnv.cpp

@@ -92,32 +92,32 @@ void CAppEnv::Stop()
 	//必须等所有工作线程都退出了,才能走到这里,否则可能会有一些线程还在访问已经被销毁的资源,导致崩溃
 	while (m_worker_count > 0)
 	{
-		DEBUG_LOG(L"正在等待工作线程退出,剩余线程数:" + std::to_wstring(m_worker_count));
+		CLewaimaiLog::OutputDebugMessage(L"正在等待工作线程退出,剩余线程数:" + std::to_wstring(m_worker_count));
 		Sleep(30);
 	}
 
 	auto time_8 = std::chrono::high_resolution_clock::now();
 
 	auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(time_2 - time_1);
-	DEBUG_LOG(("打印任务耗时: " + std::to_string(duration1.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("打印任务耗时: " + std::to_string(duration1.count()) + " 毫秒").c_str());
 
 	auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(time_3 - time_2);
-	DEBUG_LOG(("称重任务耗时: " + std::to_string(duration2.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("称重任务耗时: " + std::to_string(duration2.count()) + " 毫秒").c_str());
 
 	auto duration3 = std::chrono::duration_cast<std::chrono::milliseconds>(time_4 - time_3);
-	DEBUG_LOG(("声音任务耗时: " + std::to_string(duration3.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("声音任务耗时: " + std::to_string(duration3.count()) + " 毫秒").c_str());
 
 	auto duration4 = std::chrono::duration_cast<std::chrono::milliseconds>(time_5 - time_4);
-	DEBUG_LOG(("摄像头任务耗时: " + std::to_string(duration4.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("摄像头任务耗时: " + std::to_string(duration4.count()) + " 毫秒").c_str());
 
 	auto duration5 = std::chrono::duration_cast<std::chrono::milliseconds>(time_6 - time_5);
-	DEBUG_LOG(("AI识别任务耗时: " + std::to_string(duration5.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("AI识别任务耗时: " + std::to_string(duration5.count()) + " 毫秒").c_str());
 
 	auto duration6 = std::chrono::duration_cast<std::chrono::milliseconds>(time_7 - time_6);
-	DEBUG_LOG(("通用任务耗时: " + std::to_string(duration6.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("通用任务耗时: " + std::to_string(duration6.count()) + " 毫秒").c_str());
 
 	auto duration7 = std::chrono::duration_cast<std::chrono::milliseconds>(time_8 - time_7);
-	DEBUG_LOG(("总耗时: " + std::to_string(duration7.count()) + " 毫秒").c_str());
+	CLewaimaiLog::OutputDebugMessage(("总耗时: " + std::to_string(duration7.count()) + " 毫秒").c_str());
 
 	int a = 1;
 }

+ 0 - 55
zhipuzi_pos_windows/tool/debuglog.h

@@ -1,55 +0,0 @@
-#pragma once
-#include <windows.h>
-#include <sstream>
-#include <cstdio>
-
-#define DEBUG_LOG_BUFFER_SIZE 1024
-
-#define DEBUG_LOG(msg) do { \
-    std::wostringstream __oss; \
-    __oss << L"[" << __func__ << L"]@" << __FILE__ << L":" << __LINE__ << L": " << msg << L"\n"; \
-    OutputDebugString(__oss.str().c_str()); \
-} while(0)
-
-#define DEBUG_LOG_VAR(msg, val) do { \
-    std::wostringstream __oss; \
-    __oss << L"[" << __func__ << L"]@" << __FILE__ << L":" << __LINE__ << L": " << msg << L": " << val << L"\n"; \
-    OutputDebugString(__oss.str().c_str()); \
-} while(0)
-
-#define DEBUG_LOG_FMT(format, ...) do { \
-    wchar __logbuf[DEBUG_LOG_BUFFER_SIZE]; \
-    std::swprintf(__logbuf, DEBUG_LOG_BUFFER_SIZE, format, ##__VA_ARGS__); \
-    wchar __fullmsg[DEBUG_LOG_BUFFER_SIZE + 128]; \
-    std::swprintf(__fullmsg, sizeof(__fullmsg), L"[%s]@%s:%d: %s\n", __func__, __FILE__, __LINE__, __logbuf); \
-    OutputDebugString(__fullmsg); \
-} while(0)
-
-class DEBUG_HELPER
-{
-public:
-    static void debug_printf(const char * format, ...)
-    {
-        va_list args;
-        va_start(args, format);
-        vprintf(format, args); // 原生打印到控制台(或重定向的输出)
-        char buffer[1024]; // 创建一个足够大的缓冲区来存储格式化后的字符串(可选)
-        vsnprintf(buffer, sizeof(buffer), format, args); // 将格式化后的字符串存储到buffer中(可选)
-        va_end(args); // 清理变量参数列表(optional)
-
-        DEBUG_LOG(buffer);
-    }
-
-	// 辅助日志函数(方便打印路径)
-	static void log_messagebox(LPCTSTR lpFormat, ...)
-	{
-		TCHAR szBuffer[1024] = { 0 };
-		va_list argList;
-		va_start(argList, lpFormat);
-		_vstprintf_s(szBuffer, _countof(szBuffer), lpFormat, argList);
-		va_end(argList);
-
-		// 方式1:弹出消息框(直观)
-		::MessageBox(nullptr, szBuffer, _T("日志信息"), MB_OK);
-	}
-};

+ 12 - 2
zhipuzi_pos_windows/worker/CChengzhongWorker.cpp

@@ -301,12 +301,12 @@ void CChengzhongWorker::UpdateShow(std::string new_weight)
 	if (m_weight != new_weight)
 	{
 		//说明重量有变化了
-
 		if (m_is_wending == true)
 		{
-			//说明目前是从稳定变为不稳定,并且重量在增加(代表放东西到秤上),并且当前重量大于10g,那么这里可以发起AI识别
+			//马上要从稳定变为不稳定
 			if (atof(new_weight.c_str()) > atof(m_weight.c_str()) && atof(new_weight.c_str()) > 0.01)
 			{
+				//说明目前是从稳定变为不稳定,并且重量在增加(代表放东西到秤上),并且当前重量大于10g,那么这里可以发起AI识别
 				CDiandanAIShibieWorker::GetInstance()->AddAIShibieTask();
 			}
 		}
@@ -318,6 +318,16 @@ void CChengzhongWorker::UpdateShow(std::string new_weight)
 	else
 	{
 		//重量没有变化了,说明稳定了
+		if (m_is_wending == false)
+		{
+			//马上要从不稳定变为稳定了
+			if (atof(new_weight.c_str()) < 0.01)
+			{
+				//说明马上要从不稳定变为稳定了,并且重量小于10g,那么这里可以发起AI识别清空
+				CDiandanAIShibieWorker::GetInstance()->ClearAIShibieFoodname();
+			}
+		}
+
 		m_is_wending = true;
 	}
 

+ 66 - 88
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -35,6 +35,23 @@ void CDiandanAIShibieWorker::StopWork()
 	m_is_work = false;
 }
 
+void CDiandanAIShibieWorker::AddAIShibieTask()
+{
+	std::lock_guard<std::mutex> lock(m_mutex);
+	m_queue_ai_shibie.push(1);
+}
+
+void CDiandanAIShibieWorker::ClearAIShibieFoodname()
+{
+	m_ai_shibie_foodname = "Unknown";
+
+	//主线程里面去处理界面刷新
+	if (m_hwnd != NULL)
+	{
+		::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
+	}
+}
+
 void CDiandanAIShibieWorker::DoAIShibie()
 {
 	try
@@ -42,12 +59,7 @@ void CDiandanAIShibieWorker::DoAIShibie()
 		if (m_is_ai_shibie == false)
 		{
 			//说明没开启AI识别
-			if (m_ai_shibie_foodname != "Unknown")
-			{
-				m_ai_shibie_foodname = "Unknown";
-
-				//AI识别都没开启,没必要更新界面了,直接返回就好了
-			}
+			this->ClearAIShibieFoodname();
 
 			return;
 		}
@@ -57,16 +69,7 @@ void CDiandanAIShibieWorker::DoAIShibie()
 		if (image.empty())
 		{
 			//从摄像头获取帧失败
-			if (m_ai_shibie_foodname != "Unknown")
-			{
-				m_ai_shibie_foodname = "Unknown";
-
-				//主线程里面去处理界面刷新
-				if (m_hwnd != NULL)
-				{
-					::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-				}
-			}
+			this->ClearAIShibieFoodname();
 
 			return;
 		}
@@ -74,6 +77,7 @@ void CDiandanAIShibieWorker::DoAIShibie()
 		m_ai_shibie_foodname = YoloFeatureManager::GetInstance()->Class(image);
 		if (m_ai_shibie_foodname != "Unknown")
 		{
+			//识别成功
 			std::cout << "检测到类别: " << m_ai_shibie_foodname << std::endl;
 
 			m_ai_shibie_foodname = CLewaimaiString::ANSIToUTF8(m_ai_shibie_foodname);
@@ -83,107 +87,81 @@ void CDiandanAIShibieWorker::DoAIShibie()
 			{
 				::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 			}
+
+			return;
 		}
-		else
+
+		//这里开始就是分类没识别成功,试着开始调用向量数据库检索
+		if (SQLiteVecManager::GetInstance()->getFeatureCount() > 0)
 		{
-			//开始调用向量数据库检索
-			if (SQLiteVecManager::GetInstance()->getFeatureCount() > 0)
-			{
-				std::vector<float> feature_vector = YoloFeatureManager::GetInstance()->extractFeatures(image);
-				std::vector<FeatureRecord> searchResults = SQLiteVecManager::GetInstance()->searchSimilarVectors(feature_vector, 5);
+			std::vector<float> feature_vector = YoloFeatureManager::GetInstance()->extractFeatures(image);
+			std::vector<FeatureRecord> searchResults = SQLiteVecManager::GetInstance()->searchSimilarVectors(feature_vector, 5);
 
-				if (!searchResults.empty())
+			if (!searchResults.empty())
+			{
+				std::cout << "向量数据库检索结果:" << std::endl;
+				for (const auto& result : searchResults)
 				{
-					std::cout << "向量数据库检索结果:" << std::endl;
-					for (const auto& result : searchResults)
-					{
-						std::string food_id = result.foodId;
-						std::string food_name = result.foodName;
-						std::string image_name = result.imageName;
-						std::string image_path = result.imagePath;
-						float similarity = result.similarity;
-
-						std::cout << "食品ID: " << food_id << ", 食品名称: " << food_name << ", 图片名称: " << image_name << ", 图片路径: " << image_path << ", 相似度: " << similarity << std::endl;
-
-						CSqlite3 sqlite;
+					std::string food_id = result.foodId;
+					std::string food_name = result.foodName;
+					std::string image_name = result.imageName;
+					std::string image_path = result.imagePath;
+					float similarity = result.similarity;
 
-						CFood newFood;
-						bool ret = sqlite.GetFoodById(food_id, newFood);
-						if (!ret)
-						{
-							std::cout << "该相似的商品已被删除" << std::endl;
+					std::cout << "食品ID: " << food_id << ", 食品名称: " << food_name << ", 图片名称: " << image_name << ", 图片路径: " << image_path << ", 相似度: " << similarity << std::endl;
 
-							//这个商品都被删除了,说明这个商品对应的图片也不应该在向量数据库里了,所以把这个图片对应的向量也删除掉
-							SQLiteVecManager::GetInstance()->DeleteFeatureVectorByImageName(image_name);
+					CSqlite3 sqlite;
 
-							continue;
-						}
-
-						//UTF8格式,sqlite里面存的都是UTF8格式的字符串
-						m_ai_shibie_foodname = newFood.name;
+					CFood newFood;
+					bool ret = sqlite.GetFoodById(food_id, newFood);
+					if (!ret)
+					{
+						std::cout << "该相似的商品已被删除" << std::endl;
 
-						//主线程里面去处理界面刷新
-						if (m_hwnd != NULL)
-						{
-							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-						}
+						//这个商品都被删除了,说明这个商品对应的图片也不应该在向量数据库里了,所以把这个图片对应的向量也删除掉
+						SQLiteVecManager::GetInstance()->DeleteFeatureVectorByImageName(image_name);
 
-						return;
+						continue;
 					}
 
-					//代码走到这里来,说明虽然向量数据库里有相似的特征,但是这些特征对应的商品都被删除了,所以最终的结果也是没有识别出来的					
-					if (m_ai_shibie_foodname != "Unknown")
-					{
-						m_ai_shibie_foodname = "Unknown";
+					//UTF8格式,sqlite里面存的都是UTF8格式的字符串
+					m_ai_shibie_foodname = newFood.name;
 
-						//主线程里面去处理界面刷新
-						if (m_hwnd != NULL)
-						{
-							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-						}
+					//主线程里面去处理界面刷新
+					if (m_hwnd != NULL)
+					{
+						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 					}
 
+					//找到最相似的一个就返回
 					return;
 				}
-				else
-				{
-					//向量数据库中没有相似的特征						
-					if (m_ai_shibie_foodname != "Unknown")
-					{
-						m_ai_shibie_foodname = "Unknown";
 
-						//主线程里面去处理界面刷新
-						if (m_hwnd != NULL)
-						{
-							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-						}
-					}
+				//代码走到这里来,说明虽然向量数据库里有相似的特征,但是这些特征对应的商品都被删除了,所以最终的结果也是没有识别出来的					
+				this->ClearAIShibieFoodname();
 
-					return;
-				}
+				return;
 			}
 			else
 			{
-				//向量数据库中没有任何特征	
-				if (m_ai_shibie_foodname != "Unknown")
-				{
-					m_ai_shibie_foodname = "Unknown";
-
-					//主线程里面去处理界面刷新
-					if (m_hwnd != NULL)
-					{
-						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-					}
-				}
+				//向量数据库中没有相似的特征						
+				this->ClearAIShibieFoodname();
 
 				return;
 			}
 		}
+		else
+		{
+			//向量数据库中没有任何特征	
+			this->ClearAIShibieFoodname();
+
+			return;
+		}
 	}
 	catch (const std::exception& e)
 	{
 		std::string aa = std::string(e.what());
-		DEBUG_LOG(("AI识别失败: " + std::string(e.what())).c_str());
+		CLewaimaiLog::OutputDebugMessage(("AI识别失败: " + std::string(e.what())).c_str());
 	}
 }
 

+ 6 - 5
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.h

@@ -42,11 +42,11 @@ public:
 		m_is_ai_shibie = false;
 	}
 
-	void AddAIShibieTask()
-	{
-		std::lock_guard<std::mutex> lock(m_mutex);
-		m_queue_ai_shibie.push(1);
-	}
+	//执行一次识别任务
+	void AddAIShibieTask();
+
+	//清空AI识别的结果
+	void ClearAIShibieFoodname();
 
 	//执行一次AI识别,包括从摄像头获取一帧,进行AI识别,调用界面刷新等一系列操作
 	void DoAIShibie();
@@ -61,6 +61,7 @@ private:
 private:
 	bool m_is_work = false;
 
+	//是否执行AI识别
 	bool m_is_ai_shibie = false;
 
 	std::string m_ai_shibie_foodname;

+ 1 - 1
zhipuzi_pos_windows/worker/CMqttClientWorker.cpp

@@ -89,7 +89,7 @@ void CMqttClientWorker::Run()
 	catch (const mqtt::exception & exc)
 	{
 		LOG_INFO(("disconnect error, exc:" + exc.get_message()).c_str());
-		DEBUG_LOG(("disconnect error, exc:" + exc.get_message()).c_str());
+		CLewaimaiLog::OutputDebugMessage(("disconnect error, exc:" + exc.get_message()).c_str());
 	}
 
 	//销毁客户端

+ 4 - 4
zhipuzi_pos_windows/worker/CVideoCaptureWorker.cpp

@@ -51,7 +51,7 @@ void CVideoCaptureWorker::HandleVideoCapture()
     int cameraIndex = findAvailableCamera();
     if (cameraIndex == -1)
     {
-        DEBUG_LOG("未找到任何可用摄像头!");
+		CLewaimaiLog::OutputDebugMessage("未找到任何可用摄像头!");
         return;
     }
 
@@ -59,12 +59,12 @@ void CVideoCaptureWorker::HandleVideoCapture()
     if (!cap.isOpened())
     {
         CSystem::my_sleep(1);
-        DEBUG_LOG("打开摄像头失败,正在重试...");
+		CLewaimaiLog::OutputDebugMessage("打开摄像头失败,正在重试...");
         
         return;
     }
 
-    DEBUG_LOG("摄像头打开成功!");
+	CLewaimaiLog::OutputDebugMessage("摄像头打开成功!");
 
     /*
     160×120(QQVGA):适用于低带宽或嵌入式场景,资源占用极低
@@ -95,7 +95,7 @@ void CVideoCaptureWorker::HandleVideoCapture()
 
         if (m_frame.empty())
         {
-            DEBUG_LOG("读取摄像头帧失败,正在重试...");
+			CLewaimaiLog::OutputDebugMessage("读取摄像头帧失败,正在重试...");
             CSystem::my_sleep(1);
             continue;
         }

+ 0 - 1
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj

@@ -254,7 +254,6 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="sqlite3\sqlite-vec.h" />
     <ClInclude Include="sqlite3\sqlite3.h" />
     <ClInclude Include="sqlite3\sqlite3ext.h" />
-    <ClInclude Include="tool\debuglog.h" />
     <ClInclude Include="worker\CMqttClientWorker.h" />
     <ClInclude Include="wnd\CHuiyuanInfoShowWnd.h" />
     <ClInclude Include="wnd\CHuiyuanBangkaWnd.h" />

+ 0 - 3
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj.filters

@@ -381,9 +381,6 @@
     <ClInclude Include="ai\SQLiteVecManager.h">
       <Filter>头文件</Filter>
     </ClInclude>
-    <ClInclude Include="tool\debuglog.h">
-      <Filter>头文件</Filter>
-    </ClInclude>
     <ClInclude Include="ai\YoloFeatureManager.h">
       <Filter>头文件</Filter>
     </ClInclude>