张洋 2 天之前
父节点
当前提交
1ef7193118

+ 1 - 0
zhipuzi_pos_windows/ai/YoloFeatureManager.cpp

@@ -16,6 +16,7 @@
 
 YoloFeatureManager::YoloFeatureManager()
 {
+
 }
 
 void YoloFeatureManager::loadModel(const std::string & modelPath)

+ 23 - 58
zhipuzi_pos_windows/page/CDiandanPageUI.cpp

@@ -28,13 +28,10 @@
 
 #include "../tool/CShuangpingTool.h"
 
+#include "../worker/CDiandanAIShibieWorker.h"
+
 CDiandanPageUI::CDiandanPageUI()
 {
-	//默认先关闭
-	m_is_ai_shibie = false;
-
-	//创建一个新线程,专门处理AI识别的结果,避免因为AI识别的结果处理比较慢,导致界面卡顿
-	std::thread(&CDiandanPageUI::HandleDiandanAIShibie, this).detach();
 }
 
 
@@ -67,6 +64,17 @@ void CDiandanPageUI::InitShow()
 
 		m_is_zidingyizhifu_init = true;
 	}
+
+	//根据AI识别的设置,启动或者暂停AI识别【在进入点单页面的时候设置刚好合适】
+	std::string is_ai_shibie = CSetting::GetInstance()->GetParam("setting_is_ai_recognition_open");
+	if (is_ai_shibie == "1")
+	{
+		CDiandanAIShibieWorker::GetInstance()->StartAIShibie();
+	}
+	else
+	{
+		CDiandanAIShibieWorker::GetInstance()->StopAIShibie();
+	}
 }
 
 void CDiandanPageUI::RefreshShow()
@@ -94,23 +102,27 @@ void CDiandanPageUI::InitFoodtypeShow()
 	m_foodtypeLayout->RemoveAll();
 
 	std::string is_ai_shibie = CSetting::GetInstance()->GetParam("setting_is_ai_recognition_open");
+	if (is_ai_shibie == "1")
+	{
+		m_is_ai_shibie = true;
+	}
+	else
+	{
+		m_is_ai_shibie = false;
+	}
 
 	CSqlite3 sqlite;
 	m_nFoodpackageNum = sqlite.GetFoodpackageNum();
 	m_types = sqlite.GetFoodtypes(); //只包含收银机显示的分类
 
-	if (is_ai_shibie == "1")
+	if (m_is_ai_shibie == true)
 	{
 		m_cur_type_id = "ai";
-
-		m_is_ai_shibie = true;
 	}
 	else if (m_nFoodpackageNum > 0)
 	{
 		//默认选中的分类是商品套餐
 		m_cur_type_id = "taocan";
-
-		m_is_ai_shibie = false;
 	}
 	else
 	{
@@ -119,8 +131,6 @@ void CDiandanPageUI::InitFoodtypeShow()
 		{
 			m_cur_type_id = m_types[0].id;
 		}
-
-		m_is_ai_shibie = false;
 	}
 
 	m_curFoodtypeOption = NULL;
@@ -312,7 +322,7 @@ void CDiandanPageUI::InitFoodShow()
 	else if (m_cur_type_id == "ai")
 	{
 		//把AI识别的结果展示出来
-		std::string ai_name = m_ai_shibie_foodname;
+		std::string ai_name = CDiandanAIShibieWorker::GetInstance()->GetShibieFoodname();
 		if (ai_name == "Unknown" || ai_name == "")
 		{
 			return;
@@ -3978,51 +3988,6 @@ void CDiandanPageUI::XianshiYouhui()
 	UpdateJiesuanZhifuPos();
 }
 
-void CDiandanPageUI::HandleDiandanAIShibie()
-{
-	std::wstring wsExePath = CSystem::getExePath();
-	std::wstring wsProgramDir = CSystem::GetProgramDir();
-
-	std::filesystem::path mainDir = wsProgramDir;
-	std::string sMainDir = mainDir.string();
-
-	std::string modelPath = sMainDir + "/ai/best_448.onnx";           // YOLO2026模型路径
-	std::string databasePath = sMainDir + "/image_features.db";     // SQLite数据库路径
-
-	std::cout << "=== YOLO2026图像检索系统 (SQLite-Vec版本) ===" << std::endl;
-	std::cout << "模型路径: " << modelPath << std::endl;
-	std::cout << "数据库路径: " << databasePath << std::endl;
-	std::cout << "=========================================" << std::endl;
-
-	// 初始化特征提取器
-	std::cout << "正在初始化YOLO2026特征提取器..." << std::endl;
-
-	m_yoloFeatureManager.loadModel(modelPath);
-
-	while (true)
-	{
-		if (m_is_ai_shibie == false)
-		{
-			Sleep(1000);
-			continue;
-		}
-
-		m_ai_shibie_foodname = m_yoloFeatureManager.ClassFromVideoCapture();
-
-		if (m_ai_shibie_foodname != "Unknown")
-		{
-			std::cout << "检测到类别: " << m_ai_shibie_foodname << std::endl;
-		}
-		else
-		{
-			std::cout << "未检测到任何类别。" << std::endl;
-		}
-
-		//主线程里面去处理界面刷新
-		::SendMessage(m_pMainWnd->GetHWND(), WM_AI_RECOGNITION_SUCCESS, 0, 0);
-	}
-}
-
 void CDiandanPageUI::HandleDiandanAIShibieResult()
 {
 	if (m_cur_type_id == "ai")

+ 2 - 7
zhipuzi_pos_windows/page/CDiandanPageUI.h

@@ -12,8 +12,6 @@
 
 #include "../wnd/CModalWnd.h"
 
-#include "../ai/YoloFeatureManager.h"
-
 class CDiandanPageUI : public CBasePageUI
 {
 public:
@@ -204,18 +202,15 @@ private:
 	//用于支付完成后,获取用于打印的order
 	CDiandanOrder GetPrintOrderinfo(std::string take_food_code, std::string show_trade_no, std::string shoukuan_type, std::string balance, std::string member_number);
 
-	void HandleDiandanAIShibie();
-
 	void HandleDiandanAIShibieResult();
 
 private:
 	CTileLayoutUI* m_foodLayout;
 	CHorizontalLayoutUI* m_foodtypeLayout;
 
-	bool m_is_zidingyizhifu_init = false;
 	bool m_is_ai_shibie = false;
-	YoloFeatureManager m_yoloFeatureManager;
-	std::string m_ai_shibie_foodname;
+
+	bool m_is_zidingyizhifu_init = false;
 
 	//套餐商品数量
 	int m_nFoodpackageNum;

+ 7 - 0
zhipuzi_pos_windows/tool/CAppEnv.cpp

@@ -7,6 +7,7 @@
 #include "../worker/CCommonWorker.h"
 #include "../worker/CVoiceWorker.h"
 #include "../worker/CVideoCaptureWorker.h"
+#include "../worker/CDiandanAIShibieWorker.h"
 #include "CShuangpingTool.h"
 
 CAppEnv::CAppEnv()
@@ -38,6 +39,9 @@ void CAppEnv::Start()
 	//启动摄像头任务
 	CVideoCaptureWorker::GetInstance()->Start();
 
+	//启动AI识别任务
+	CDiandanAIShibieWorker::GetInstance()->StartWork();
+
 	//初始化副屏
 	CShuangpingTool::GetInstance()->Init();
 }
@@ -56,6 +60,9 @@ void CAppEnv::Stop()
 	//停止摄像头任务
 	CVideoCaptureWorker::GetInstance()->Stop();
 
+	//暂停AI识别任务
+	CDiandanAIShibieWorker::GetInstance()->StopWork();
+
 	//停止通用任务
 	CCommonWorker::GetInstance()->Stop();
 }

+ 5 - 0
zhipuzi_pos_windows/wnd/CMainWnd.cpp

@@ -14,6 +14,8 @@
 
 #include "../worker/CMqttClientWorker.h"
 
+#include "../worker/CDiandanAIShibieWorker.h"
+
 #include "../wnd/CImageAttentionWnd.h"
 
 #include "../tool/CSqlite3.h"
@@ -35,6 +37,9 @@ void CMainWnd::Init()
 	//启动消息推送
 	CMqttClientWorker::GetInstance()->Start();
 
+	//设置AI识别消息窗口
+	CDiandanAIShibieWorker::GetInstance()->SetHWND(GetHWND());
+
 	//初始化所有页面,先创建页面对象,避免切换页面的时候被释放了
 	CreatePages();
 

+ 84 - 0
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -0,0 +1,84 @@
+#include "../pch/pch.h"
+#include "CDiandanAIShibieWorker.h"
+#include "CChengzhongWorker.h"
+
+//启动工作线程
+void CDiandanAIShibieWorker::StartWork()
+{
+	//默认先关闭
+	m_is_work = true;
+
+	//创建一个新线程,专门处理AI识别的结果,避免因为AI识别的结果处理比较慢,导致界面卡顿
+	std::thread(&CDiandanAIShibieWorker::HandleDiandanAIShibie, this).detach();
+}
+
+//结束工作线程
+void CDiandanAIShibieWorker::StopWork()
+{
+	m_is_work = false;
+}
+
+
+void CDiandanAIShibieWorker::HandleDiandanAIShibie()
+{
+	std::wstring wsExePath = CSystem::getExePath();
+	std::wstring wsProgramDir = CSystem::GetProgramDir();
+
+	std::filesystem::path mainDir = wsProgramDir;
+	std::string sMainDir = mainDir.string();
+
+	std::string modelPath = sMainDir + "/ai/best_448.onnx";           // YOLO2026模型路径
+	std::string databasePath = sMainDir + "/image_features.db";     // SQLite数据库路径
+
+	std::cout << "=== 图像AI识别线程启动 ===" << std::endl;
+	std::cout << "模型路径: " << modelPath << std::endl;
+	std::cout << "数据库路径: " << databasePath << std::endl;
+	std::cout << "=========================================" << std::endl;
+
+	m_yoloFeatureManager.loadModel(modelPath);
+
+	while (m_is_work == true)
+	{
+		if (m_is_ai_shibie == false)
+		{
+			//说明没开启AI识别,就等着
+			Sleep(2000);
+
+			continue;
+		}
+
+		float weight = atof(CChengzhongWorker::GetInstance()->GetWeight().c_str());
+		if (weight < -0.01)
+		{
+			//说明没有重量,没放东西到秤上面,那么就不识别
+			Sleep(100);
+
+			continue;
+		}
+
+		//auto time_1 = std::chrono::high_resolution_clock::now();
+
+		m_ai_shibie_foodname = m_yoloFeatureManager.ClassFromVideoCapture();
+
+		if (m_ai_shibie_foodname != "Unknown")
+		{
+			std::cout << "检测到类别: " << m_ai_shibie_foodname << std::endl;
+		}
+		else
+		{
+			std::cout << "未检测到任何类别。" << std::endl;
+		}
+
+		//auto time_2 = std::chrono::high_resolution_clock::now();
+
+		//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());
+
+		//主线程里面去处理界面刷新
+		if (m_hwnd != NULL)
+		{
+			::SendMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
+		}		
+	}
+}

+ 57 - 0
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.h

@@ -0,0 +1,57 @@
+#pragma once
+
+#include "../ai/YoloFeatureManager.h"
+
+class CDiandanAIShibieWorker
+{
+
+public:
+	static CDiandanAIShibieWorker* GetInstance()
+	{
+		static CDiandanAIShibieWorker instance;
+
+		return &instance;
+	}
+
+	//启动工作线程
+	void StartWork();
+
+	//结束工作线程
+	void StopWork();
+
+	void SetHWND(HWND hwnd)
+	{
+		m_hwnd = hwnd;
+	}
+
+	std::string GetShibieFoodname()
+	{
+		return m_ai_shibie_foodname;
+	}
+
+	void StartAIShibie()
+	{
+		m_is_ai_shibie = true;
+	}
+
+	void StopAIShibie()
+	{
+		m_is_ai_shibie = false;
+	}
+
+private:
+	void HandleDiandanAIShibie();
+
+private:
+	bool m_is_work = false;
+
+	std::mutex m_worker_mutex;
+
+	bool m_is_ai_shibie = false;
+
+	YoloFeatureManager m_yoloFeatureManager;
+	std::string m_ai_shibie_foodname;
+
+	HWND m_hwnd = NULL;
+};
+

+ 3 - 31
zhipuzi_pos_windows/worker/CVideoCaptureWorker.cpp

@@ -62,8 +62,8 @@ void CVideoCaptureWorker::HandleVideoCapture()
     ‌1280×720‌(720p HD):标准高清分辨率,广泛用于人脸识别、目标检测等视觉任务
     ‌1920×1080‌(1080p Full HD):全高清分辨率,提供高质量图像,适用于高精度视觉分析
     */
-    int width = 1024;
-    int height = 768;
+    int width = 800;
+    int height = 600;
 
     cap.set(cv::CAP_PROP_FRAME_WIDTH, width);
     cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);
@@ -77,23 +77,16 @@ void CVideoCaptureWorker::HandleVideoCapture()
 
     while (m_is_work == true)
     {
-		m_worker_mutex.lock();
-
         // 读取摄像头帧
         cap >> m_frame;
+
         if (m_frame.empty())
         {
-            m_worker_mutex.unlock();
-
             DEBUG_LOG("读取摄像头帧失败,正在重试...");
             CSystem::my_sleep(1);
             continue;
         }
 
-        m_worker_mutex.unlock();
-
-		Sleep(20);
-
 		//什么都不用做,只需要把摄像头读取的帧放在成员变量里就行,后续其他地方需要用到摄像头数据的时候直接从成员变量里取就行了
         // 显示摄像头帧(可选)
         // cv::imshow("Camera", m_frame);
@@ -109,26 +102,5 @@ void CVideoCaptureWorker::HandleVideoCapture()
 
 void CVideoCaptureWorker::GetFrame(cv::Mat& frame)
 {
-	auto time_1 = std::chrono::high_resolution_clock::now();
-
-	m_worker_mutex.lock();
-
-	auto time_2 = std::chrono::high_resolution_clock::now();
-
     frame = m_frame.clone();
-
-	m_worker_mutex.unlock();
-
-	auto time_3 = std::chrono::high_resolution_clock::now();
-
-
-	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());
-
-	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());
-
-	int a = 1;
 }

+ 0 - 2
zhipuzi_pos_windows/worker/CVideoCaptureWorker.h

@@ -30,6 +30,4 @@ private:
 	bool m_is_work;
 
 	cv::Mat m_frame;
-
-	std::mutex m_worker_mutex;
 };

+ 2 - 0
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj

@@ -242,6 +242,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="ai\SQLiteVecManager.h" />
     <ClInclude Include="ai\YoloClassName.h" />
     <ClInclude Include="ai\YoloFeatureManager.h" />
+    <ClInclude Include="worker\CDiandanAIShibieWorker.h" />
     <ClInclude Include="worker\CVideoCaptureWorker.h" />
     <ClInclude Include="sqlite3\sqlite-vec.h" />
     <ClInclude Include="sqlite3\sqlite3.h" />
@@ -371,6 +372,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClCompile Include="ai\test.cpp" />
     <ClCompile Include="ai\test.h" />
     <ClCompile Include="ai\YoloFeatureManager.cpp" />
+    <ClCompile Include="worker\CDiandanAIShibieWorker.cpp" />
     <ClCompile Include="worker\CVideoCaptureWorker.cpp" />
     <ClCompile Include="sqlite3\shell.c" />
     <ClCompile Include="sqlite3\sqlite-vec.c" />

+ 6 - 0
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj.filters

@@ -393,6 +393,9 @@
     <ClInclude Include="ai\YoloClassName.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="worker\CDiandanAIShibieWorker.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="pch\pch.cpp">
@@ -746,6 +749,9 @@
     <ClCompile Include="worker\CVideoCaptureWorker.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="worker\CDiandanAIShibieWorker.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="resource\zhipuzi.ico">