张洋 1 day ago
parent
commit
b1e658357c

+ 24 - 4
zhipuzi_pos_windows/ai/YoloFeatureManager.cpp

@@ -19,6 +19,11 @@ YoloFeatureManager::YoloFeatureManager()
 
 
 }
 }
 
 
+YoloFeatureManager::~YoloFeatureManager()
+{
+	
+}
+
 void YoloFeatureManager::loadModel(const std::string & modelPath)
 void YoloFeatureManager::loadModel(const std::string & modelPath)
 {
 {
 	inputWidth = 448;
 	inputWidth = 448;
@@ -32,6 +37,22 @@ void YoloFeatureManager::loadModel(const std::string & modelPath)
 	FRUIT_VEGETABLE_COUNT = sizeof(FRUIT_VEGETABLE_NAMES) / sizeof(FRUIT_VEGETABLE_NAMES[0]);
 	FRUIT_VEGETABLE_COUNT = sizeof(FRUIT_VEGETABLE_NAMES) / sizeof(FRUIT_VEGETABLE_NAMES[0]);
 }
 }
 
 
+// 寻找置信度最高的类别
+int YoloFeatureManager::getTopClass(const cv::Mat& output)
+{
+	// 将输出展平为一维数组
+	cv::Mat flatOutput = output.reshape(1, 1);
+
+	double maxVal;
+
+	cv::Point maxLoc;
+
+	// 找到最大值的位置(即最高置信度类别索引)
+	cv::minMaxLoc(flatOutput, nullptr, &maxVal, nullptr, &maxLoc);
+
+	return maxLoc.x;
+}
+
 //	获取类别名称
 //	获取类别名称
 std::string YoloFeatureManager::getClassName(std::size_t classId) const
 std::string YoloFeatureManager::getClassName(std::size_t classId) const
 {
 {
@@ -279,16 +300,15 @@ std::string YoloFeatureManager::Class(cv::Mat & image)
 	if (topConfidence > 0.8)
 	if (topConfidence > 0.8)
 	{
 	{
 		className = this->getClassName(topClassIdx);
 		className = this->getClassName(topClassIdx);
-
-		// 在画面上绘制分类结果
-		std::wstring resultText = CLewaimaiString::ANSIToUnicode(className) + L" : " + std::to_wstring(round(topConfidence * 10000) / 100) + L"%";
-		this->drawChineseText(image, resultText.c_str(), cv::Point(20, 50), cv::Scalar(0, 255, 0), 24);
 	}
 	}
 	else
 	else
 	{
 	{
 		className = "Unknown";
 		className = "Unknown";
 	}
 	}
 
 
+	// 在画面上绘制分类结果
+	//std::wstring resultText = CLewaimaiString::ANSIToUnicode(className) + L" : " + std::to_wstring(round(topConfidence * 10000) / 100) + L"%";
+	//this->drawChineseText(image, resultText.c_str(), cv::Point(20, 50), cv::Scalar(0, 255, 0), 24);
 	//cv::imshow("YOLOv8s-cls 实时图像分类", image);
 	//cv::imshow("YOLOv8s-cls 实时图像分类", image);
 	//if (cv::waitKey(30) >= 0); // 按任意键退出
 	//if (cv::waitKey(30) >= 0); // 按任意键退出
 
 

+ 3 - 16
zhipuzi_pos_windows/ai/YoloFeatureManager.h

@@ -19,7 +19,7 @@ private:
 
 
 public:
 public:
 	YoloFeatureManager();
 	YoloFeatureManager();
-	~YoloFeatureManager() = default;
+	~YoloFeatureManager();
 
 
 	// 重新加载模型
 	// 重新加载模型
 	void loadModel(const std::string & modelPath);
 	void loadModel(const std::string & modelPath);
@@ -41,23 +41,10 @@ public:
 
 
 private:
 private:
 	// 寻找置信度最高的类别
 	// 寻找置信度最高的类别
-	int getTopClass(const cv::Mat & output)
-	{
-		// 将输出展平为一维数组
-		cv::Mat flatOutput = output.reshape(1, 1);
-
-		double maxVal;
-
-		cv::Point maxLoc;
-
-		// 找到最大值的位置(即最高置信度类别索引)
-		cv::minMaxLoc(flatOutput, nullptr, &maxVal, nullptr, &maxLoc);
-
-		return maxLoc.x;
-	}
+	int getTopClass(const cv::Mat& output);
 
 
 	//	获取类别名称
 	//	获取类别名称
 	std::string getClassName(std::size_t classId) const;
 	std::string getClassName(std::size_t classId) const;
 
 
 	void drawChineseText(cv::Mat & img, const wchar_t * text, cv::Point pos, cv::Scalar color, int fontSize);
 	void drawChineseText(cv::Mat & img, const wchar_t * text, cv::Point pos, cv::Scalar color, int fontSize);
-};
+};

+ 28 - 4
zhipuzi_pos_windows/tool/CAppEnv.cpp

@@ -12,6 +12,7 @@
 
 
 CAppEnv::CAppEnv()
 CAppEnv::CAppEnv()
 {
 {
+	m_worker_count = 0;
 }
 }
 
 
 
 
@@ -33,14 +34,16 @@ void CAppEnv::Start()
 	//启动声音任务
 	//启动声音任务
 	CVoiceWorker::GetInstance()->Start();
 	CVoiceWorker::GetInstance()->Start();
 
 
-	//启动通用任务
-	CCommonWorker::GetInstance()->Start();
-
 	//启动摄像头任务
 	//启动摄像头任务
 	CVideoCaptureWorker::GetInstance()->Start();
 	CVideoCaptureWorker::GetInstance()->Start();
+	AddWorkerNum();
 
 
 	//启动AI识别任务
 	//启动AI识别任务
 	CDiandanAIShibieWorker::GetInstance()->StartWork();
 	CDiandanAIShibieWorker::GetInstance()->StartWork();
+	AddWorkerNum();
+
+	//启动通用任务
+	CCommonWorker::GetInstance()->Start();
 
 
 	//初始化副屏
 	//初始化副屏
 	CShuangpingTool::GetInstance()->Init();
 	CShuangpingTool::GetInstance()->Init();
@@ -65,4 +68,25 @@ void CAppEnv::Stop()
 
 
 	//停止通用任务
 	//停止通用任务
 	CCommonWorker::GetInstance()->Stop();
 	CCommonWorker::GetInstance()->Stop();
-}
+
+	//必须等所有工作线程都退出了,才能走到这里,否则可能会有一些线程还在访问已经被销毁的资源,导致崩溃
+	while (m_worker_count > 0)
+	{
+		DEBUG_LOG(L"正在等待工作线程退出,剩余线程数:" + std::to_wstring(m_worker_count));
+		Sleep(30);
+	}
+
+	int a = 1;
+}
+
+void CAppEnv::AddWorkerNum()
+{
+	std::lock_guard<std::mutex> lock(m_mutex);
+	m_worker_count++;
+}
+
+void CAppEnv::DelWorkerNum()
+{
+	std::lock_guard<std::mutex> lock(m_mutex);
+	m_worker_count--;
+}

+ 13 - 0
zhipuzi_pos_windows/tool/CAppEnv.h

@@ -7,9 +7,22 @@ public:
 	CAppEnv();
 	CAppEnv();
 	~CAppEnv();
 	~CAppEnv();
 
 
+	static CAppEnv* GetInstance()
+	{
+		static CAppEnv instance;
+
+		return &instance;
+	}
+
 	void Start();
 	void Start();
 	void Stop();
 	void Stop();
 
 
+	void AddWorkerNum();
+	void DelWorkerNum();
+
 private:
 private:
+	int m_worker_count;
+
+	std::mutex m_mutex;
 };
 };
 
 

+ 62 - 37
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -1,6 +1,17 @@
 #include "../pch/pch.h"
 #include "../pch/pch.h"
 #include "CDiandanAIShibieWorker.h"
 #include "CDiandanAIShibieWorker.h"
 #include "CChengzhongWorker.h"
 #include "CChengzhongWorker.h"
+#include "../tool/CAppEnv.h"
+
+CDiandanAIShibieWorker::CDiandanAIShibieWorker()
+{
+
+}
+
+CDiandanAIShibieWorker::~CDiandanAIShibieWorker()
+{
+	
+}
 
 
 //启动工作线程
 //启动工作线程
 void CDiandanAIShibieWorker::StartWork()
 void CDiandanAIShibieWorker::StartWork()
@@ -39,46 +50,60 @@ void CDiandanAIShibieWorker::HandleDiandanAIShibie()
 
 
 	while (m_is_work == true)
 	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)
+		try
 		{
 		{
-			//说明没有重量,没放东西到秤上面,那么就不识别
-			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;
+			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);
+			}
 		}
 		}
-		else
+		catch (const std::exception& e)
 		{
 		{
-			std::cout << "未检测到任何类别。" << std::endl;
-		}
-
-		//auto time_2 = std::chrono::high_resolution_clock::now();
+			std::string aa = std::string(e.what());
+			DEBUG_LOG(("提取特征失败: " + std::string(e.what())).c_str());
+			return;
+		}	
+	}
 
 
-		//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());
+	//走到这里说明线程要退出了,做一些清理工作
+	CAppEnv::GetInstance()->DelWorkerNum();
 
 
-		//主线程里面去处理界面刷新
-		if (m_hwnd != NULL)
-		{
-			::SendMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-		}		
-	}
+	int b = 1;
 }
 }

+ 3 - 0
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.h

@@ -6,6 +6,9 @@ class CDiandanAIShibieWorker
 {
 {
 
 
 public:
 public:
+	CDiandanAIShibieWorker();
+	~CDiandanAIShibieWorker();
+
 	static CDiandanAIShibieWorker* GetInstance()
 	static CDiandanAIShibieWorker* GetInstance()
 	{
 	{
 		static CDiandanAIShibieWorker instance;
 		static CDiandanAIShibieWorker instance;

+ 1 - 0
zhipuzi_pos_windows/worker/CMqttClientWorker.cpp

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

+ 17 - 2
zhipuzi_pos_windows/worker/CVideoCaptureWorker.cpp

@@ -1,5 +1,16 @@
 #include "../pch/pch.h"
 #include "../pch/pch.h"
 #include "CVideoCaptureWorker.h"
 #include "CVideoCaptureWorker.h"
+#include "../tool/CAppEnv.h"
+
+CVideoCaptureWorker::CVideoCaptureWorker()
+{
+
+}
+
+CVideoCaptureWorker::~CVideoCaptureWorker()
+{
+	
+}
 
 
 //开始工作
 //开始工作
 void CVideoCaptureWorker::Start()
 void CVideoCaptureWorker::Start()
@@ -21,7 +32,8 @@ void CVideoCaptureWorker::Stop()
 int CVideoCaptureWorker::findAvailableCamera()
 int CVideoCaptureWorker::findAvailableCamera()
 {
 {
     for (int i = 0; i < 10; i++)
     for (int i = 0; i < 10; i++)
-    { // 检测前10个索引
+    { 
+		// 检测前10个索引
         cv::VideoCapture tempCap(i, cv::CAP_DSHOW);
         cv::VideoCapture tempCap(i, cv::CAP_DSHOW);
         if (tempCap.isOpened())
         if (tempCap.isOpened())
         {
         {
@@ -41,8 +53,8 @@ void CVideoCaptureWorker::HandleVideoCapture()
         DEBUG_LOG("未找到任何可用摄像头!");
         DEBUG_LOG("未找到任何可用摄像头!");
         return;
         return;
     }
     }
-    cv::VideoCapture cap(cameraIndex, cv::CAP_DSHOW);
 
 
+    cv::VideoCapture cap(cameraIndex, cv::CAP_DSHOW);
     if (!cap.isOpened())
     if (!cap.isOpened())
     {
     {
         CSystem::my_sleep(1);
         CSystem::my_sleep(1);
@@ -97,6 +109,9 @@ void CVideoCaptureWorker::HandleVideoCapture()
     cap.release();
     cap.release();
     cv::destroyAllWindows();
     cv::destroyAllWindows();
 
 
+	//走到这里说明线程要退出了,做一些清理工作
+	CAppEnv::GetInstance()->DelWorkerNum();
+
     return;
     return;
 }
 }
 
 

+ 3 - 0
zhipuzi_pos_windows/worker/CVideoCaptureWorker.h

@@ -7,6 +7,9 @@
 class CVideoCaptureWorker
 class CVideoCaptureWorker
 {
 {
 public:
 public:
+	CVideoCaptureWorker();
+	~CVideoCaptureWorker();
+
 	static CVideoCaptureWorker * GetInstance()
 	static CVideoCaptureWorker * GetInstance()
 	{
 	{
 		static CVideoCaptureWorker instance;
 		static CVideoCaptureWorker instance;

+ 2 - 3
zhipuzi_pos_windows/zhipuzi_pos_windows.cpp

@@ -30,8 +30,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
 	log.Init();
 	log.Init();
 
 
 	//初始化所有配置,启动所有异步worker
 	//初始化所有配置,启动所有异步worker
-	CAppEnv app;
-	app.Start();
+	CAppEnv::GetInstance()->Start();
 
 
 	//AITest();
 	//AITest();
 
 
@@ -100,7 +99,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
     ::CoUninitialize();
     ::CoUninitialize();
 
 
 	//销毁一些环境
 	//销毁一些环境
-	app.Stop();
+	CAppEnv::GetInstance()->Stop();
 
 
     return 0;
     return 0;
 }
 }