Просмотр исходного кода

完成对图片的处理与采集

张洋 3 недель назад
Родитель
Сommit
7a9d174891

+ 3 - 2
bin/Win32/Debug/zhipuzi_pos_windows/skin/aixuexi_page.xml

@@ -27,8 +27,9 @@
 
 					<HorizontalLayout height="50" padding="0,20,0,0">
 						<Control></Control>
-							<Button name="aixuexi_page_paishe_btn" width="150" height="50" text="拍摄并学习" textcolor="#FFFFFFFF" normalimage="file='btn_green_zhengchang.png' corner='5,5,5,5'" hotimage="file='btn_green_xuanfu.png' corner='5,5,5,5'" pushedimage="file='btn_green_dianji.png' corner='5,5,5,5'" />
-							<Button name="aixuexi_page_test_btn" width="150" height="50" padding="15,0,0,0" text="AI识别测试" textcolor="#FFFFFFFF" normalimage="file='btn_green_zhengchang.png' corner='5,5,5,5'" hotimage="file='btn_green_xuanfu.png' corner='5,5,5,5'" pushedimage="file='btn_green_dianji.png' corner='5,5,5,5'" />
+							<Button name="aixuexi_page_paishe_btn" width="120" height="50" text="拍摄并学习" textcolor="#FFFFFFFF" normalimage="file='btn_green_zhengchang.png' corner='5,5,5,5'" hotimage="file='btn_green_xuanfu.png' corner='5,5,5,5'" pushedimage="file='btn_green_dianji.png' corner='5,5,5,5'" />
+							<Button name="aixuexi_page_test_btn" width="120" height="50" padding="15,0,0,0" text="AI识别测试" textcolor="#FFFFFFFF" normalimage="file='btn_green_zhengchang.png' corner='5,5,5,5'" hotimage="file='btn_green_xuanfu.png' corner='5,5,5,5'" pushedimage="file='btn_green_dianji.png' corner='5,5,5,5'" />
+							<Button name="aixuexi_page_caiji_btn" width="120" height="50" padding="15,0,0,0" text="采集图片" textcolor="#FFFFFFFF" normalimage="file='btn_green_zhengchang.png' corner='5,5,5,5'" hotimage="file='btn_green_xuanfu.png' corner='5,5,5,5'" pushedimage="file='btn_green_dianji.png' corner='5,5,5,5'" />
 						<Control></Control>
 					</HorizontalLayout>
 

+ 2 - 0
zhipuzi_pos_windows/control/CFoodXuexiImageItemUI.h

@@ -23,6 +23,8 @@ public:
 
 private:
 	std::string m_imageName;
+
+	//utf-8格式的路径
 	std::string m_imagePath;
 };
 

+ 48 - 19
zhipuzi_pos_windows/page/CAIxuexiPageUI.cpp

@@ -366,6 +366,10 @@ void CAIxuexiPageUI::HandleClickMsg(TNotifyUI& msg)
 	{
 		CDiandanAIShibieWorker::GetInstance()->AddAIShibieTask();
 	}
+	else if (name == L"aixuexi_page_caiji_btn")
+	{
+		this->DoCaiji();
+	}
 	else if (name == L"aixuexi_page_food_image_delete")
 	{
 		CFoodXuexiImageItemUI* m_pImageItem = static_cast<CFoodXuexiImageItemUI*>(msg.pSender->GetParent());
@@ -632,30 +636,21 @@ void CAIxuexiPageUI::DoXuexi()
 	}
 
 	//第一步先把当前帧保存为图片
-	std::wstring save_path = CSystem::GetTmpDir() + L"\\ai_xuexi_image";
-	if (!CSystem::IsPathExist(save_path))
-	{
-		CSystem::CreateMultiLevel(CLewaimaiString::UnicodeToUTF8(save_path));
-	}
-
-	std::string filename = CLewaimaiString::generateRandomStr(32);
-	std::wstring file_save_path = save_path + L"\\" + CLewaimaiString::UTF8ToUnicode(filename) + L".jpg";
-	std::string s_file_save_path = CLewaimaiString::UnicodeToUTF8(file_save_path);
-
-	cv::Mat img;
-	CVideoCapture::GetInstance()->GetFrame(img);
-	if (img.empty())
+	std::wstring file_save_path = this->DoCaiji();
+	if (file_save_path == L"")
 	{
+		m_pMainWnd->ShowToast(L"拍摄图片失败,请检查摄像头");
 		return;
 	}
 
-	if (img.type() != CV_8UC3)
-	{
-		// 仅支持 3 通道彩色图像
-		cvtColor(img, img, cv::COLOR_GRAY2BGR);
-	}
+	std::filesystem::path filePath = file_save_path;
+	std::string filename = filePath.filename().string();
 
-	cv::imwrite(CLewaimaiString::UnicodeToUTF8(file_save_path), img);
+	std::string s_file_save_path = CLewaimaiString::UnicodeToUTF8(file_save_path);
+	cv::Mat img = cv::imread(s_file_save_path.c_str(), cv::IMREAD_COLOR);
+
+	//走到这里已经是裁减过的图片了,直接开始缩放和填充
+	CVideoCapture::GetInstance()->HandleResizeAndPaddingFrame(img, img);	
 
 	//第二步把这个图片的特征向量提取出来,保存到数据库里,关联到当前选中的商品上
 	std::cout << "开始提取图库图片特征..." << std::endl;
@@ -682,4 +677,38 @@ void CAIxuexiPageUI::DoXuexi()
 	pItem->SetImagePath(imagePath);
 
 	pXuexiScrollLayout->Add(pItem);
+}
+
+std::wstring CAIxuexiPageUI::DoCaiji()
+{
+	std::wstring save_path = CSystem::GetTmpDir() + L"\\ai_xuexi_image";
+	if (!CSystem::IsPathExist(save_path))
+	{
+		CSystem::CreateMultiLevel(CLewaimaiString::UnicodeToUTF8(save_path));
+	}
+
+	std::string filename = CLewaimaiString::generateRandomStr(32);
+	std::wstring file_save_path = save_path + L"\\" + CLewaimaiString::UTF8ToUnicode(filename) + L".jpg";
+	std::string s_file_save_path = CLewaimaiString::UnicodeToUTF8(file_save_path);
+
+	cv::Mat img;
+	CVideoCapture::GetInstance()->GetFrame(img);
+	if (img.empty())
+	{
+		return L"";
+	}
+
+	if (img.type() != CV_8UC3)
+	{
+		// 仅支持 3 通道彩色图像
+		cvtColor(img, img, cv::COLOR_GRAY2BGR);
+	}
+
+	//摄像头拍摄的默认是800*800,对采集的图片进行处理,根据设置的裁减区域进行裁减
+	CVideoCapture::GetInstance()->HandleCutFrame(img, img);
+
+	//这里存本地的文件,存裁减以后的原图,不进行缩放和填充,用于生成训练集数据,后续训练的时候会进行缩放和填充
+	cv::imwrite(CLewaimaiString::UnicodeToUTF8(file_save_path), img);
+
+	return file_save_path;
 }

+ 3 - 0
zhipuzi_pos_windows/page/CAIxuexiPageUI.h

@@ -74,6 +74,9 @@ public:
 	//点击拍摄并学习按钮之后的处理逻辑
 	void DoXuexi();
 
+	//采集摄像头拍摄的图片,并进行裁减,然后保存到本地,返回裁减后的图片路径,注意这里只进行裁减,不进行缩放和填充,方便采集原始图片当数据集
+	std::wstring DoCaiji();
+
 private:
 	bool m_is_video_thread_run = false;
 	HBITMAP m_hBitmap;

+ 25 - 65
zhipuzi_pos_windows/page/CSettingPageUI.cpp

@@ -21,19 +21,6 @@ using boost::asio::ip::tcp;
 #include "../tool/CAppEnv.h"
 #include "../tool/CVideoCapture.h"
 
-namespace
-{
-	//摄像头拍摄的图片的原始尺寸,本系统里面默认为800*600
-	const int kVideoWidth = 800;
-	const int kVideoHeight = 600;
-
-	//红色边框的最小尺寸
-	const int kVideoBorderMinWidth = 400;
-	const int kVideoBorderMinHeight = 300;
-
-	const int kVideoGripSize = 8;
-}
-
 CSettingPageUI::CSettingPageUI()
 {
 
@@ -3626,42 +3613,7 @@ void CSettingPageUI::StopVideoThread()
 
 void CSettingPageUI::LoadVideoBorderRect()
 {
-	if (m_videoBorderLoaded)
-	{
-		return;
-	}
-
-	auto readInt = [](const std::string& value, int defaultValue) -> int
-		{
-			if (value.empty())
-			{
-				return defaultValue;
-			}
-
-			return atoi(value.c_str());
-		};
-
-	int x = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_x"), 0);
-	int y = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_y"), 0);
-	int w = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_w"), kVideoWidth);
-	int h = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_h"), kVideoHeight);
-
-	if (w < kVideoBorderMinWidth) w = kVideoBorderMinWidth;
-	if (h < kVideoBorderMinHeight) h = kVideoBorderMinHeight;
-	if (w > kVideoWidth) w = kVideoWidth;
-	if (h > kVideoHeight) h = kVideoHeight;
-
-	if (x < 0) x = 0;
-	if (y < 0) y = 0;
-	if (x + w > kVideoWidth) x = kVideoWidth - w;
-	if (y + h > kVideoHeight) y = kVideoHeight - h;
-
-	m_videoBorderRect.left = x;
-	m_videoBorderRect.top = y;
-	m_videoBorderRect.right = x + w;
-	m_videoBorderRect.bottom = y + h;
-
-	m_videoBorderLoaded = true;
+	m_videoBorderRect = CVideoCapture::GetInstance()->GetVideoBorderRect();
 }
 
 void CSettingPageUI::SaveVideoBorderRect()
@@ -3675,6 +3627,9 @@ void CSettingPageUI::SaveVideoBorderRect()
 	CSetting::GetInstance()->SetParam("setting_ai_video_rect_y", std::to_string(y));
 	CSetting::GetInstance()->SetParam("setting_ai_video_rect_w", std::to_string(w));
 	CSetting::GetInstance()->SetParam("setting_ai_video_rect_h", std::to_string(h));
+
+	//把这个保存到AI识别的worker里面
+	CVideoCapture::GetInstance()->SetVideoBorderRect(m_videoBorderRect);
 }
 
 RECT CSettingPageUI::GetVideoImageRect()
@@ -3701,31 +3656,31 @@ RECT CSettingPageUI::GetVideoBorderDisplayRect(const RECT& imageRect)
 		return rc;
 	}
 
-	rc.left = imageRect.left + MulDiv(m_videoBorderRect.left, imageWidth, kVideoWidth);
-	rc.top = imageRect.top + MulDiv(m_videoBorderRect.top, imageHeight, kVideoHeight);
-	rc.right = imageRect.left + MulDiv(m_videoBorderRect.right, imageWidth, kVideoWidth);
-	rc.bottom = imageRect.top + MulDiv(m_videoBorderRect.bottom, imageHeight, kVideoHeight);
+	rc.left = imageRect.left + MulDiv(m_videoBorderRect.left, imageWidth, CVideoCapture::GetInstance()->GetVideoWidth());
+	rc.top = imageRect.top + MulDiv(m_videoBorderRect.top, imageHeight, CVideoCapture::GetInstance()->GetVideoHeight());
+	rc.right = imageRect.left + MulDiv(m_videoBorderRect.right, imageWidth, CVideoCapture::GetInstance()->GetVideoWidth());
+	rc.bottom = imageRect.top + MulDiv(m_videoBorderRect.bottom, imageHeight, CVideoCapture::GetInstance()->GetVideoHeight());
 
 	return rc;
 }
 
 int CSettingPageUI::HitTestVideoBorder(POINT pt, const RECT& borderRect)
 {
-	bool nearLeft = (std::abs(pt.x - borderRect.left) <= kVideoGripSize) &&
-		(pt.y >= borderRect.top - kVideoGripSize) &&
-		(pt.y <= borderRect.bottom + kVideoGripSize);
+	bool nearLeft = (std::abs(pt.x - borderRect.left) <= m_kVideoGripSize) &&
+		(pt.y >= borderRect.top - m_kVideoGripSize) &&
+		(pt.y <= borderRect.bottom + m_kVideoGripSize);
 
-	bool nearRight = (std::abs(pt.x - borderRect.right) <= kVideoGripSize) &&
-		(pt.y >= borderRect.top - kVideoGripSize) &&
-		(pt.y <= borderRect.bottom + kVideoGripSize);
+	bool nearRight = (std::abs(pt.x - borderRect.right) <= m_kVideoGripSize) &&
+		(pt.y >= borderRect.top - m_kVideoGripSize) &&
+		(pt.y <= borderRect.bottom + m_kVideoGripSize);
 
-	bool nearTop = (std::abs(pt.y - borderRect.top) <= kVideoGripSize) &&
-		(pt.x >= borderRect.left - kVideoGripSize) &&
-		(pt.x <= borderRect.right + kVideoGripSize);
+	bool nearTop = (std::abs(pt.y - borderRect.top) <= m_kVideoGripSize) &&
+		(pt.x >= borderRect.left - m_kVideoGripSize) &&
+		(pt.x <= borderRect.right + m_kVideoGripSize);
 
-	bool nearBottom = (std::abs(pt.y - borderRect.bottom) <= kVideoGripSize) &&
-		(pt.x >= borderRect.left - kVideoGripSize) &&
-		(pt.x <= borderRect.right + kVideoGripSize);
+	bool nearBottom = (std::abs(pt.y - borderRect.bottom) <= m_kVideoGripSize) &&
+		(pt.x >= borderRect.left - m_kVideoGripSize) &&
+		(pt.x <= borderRect.right + m_kVideoGripSize);
 
 	if (nearLeft && nearTop) return HTTOPLEFT;
 	if (nearRight && nearTop) return HTTOPRIGHT;
@@ -3837,6 +3792,11 @@ bool CSettingPageUI::HandleVideoBorderMouseMessage(UINT uMsg, WPARAM wParam, LPA
 			return true;
 		}
 
+		int kVideoWidth = CVideoCapture::GetInstance()->GetVideoWidth();
+		int kVideoHeight = CVideoCapture::GetInstance()->GetVideoHeight();
+		int kVideoBorderMinWidth = CVideoCapture::GetInstance()->GetVideoBorderMinWidth();
+		int kVideoBorderMinHeight = CVideoCapture::GetInstance()->GetVideoBorderMinHeight();
+
 		int dx = MulDiv(pt.x - m_videoBorderDragStartPt.x, kVideoWidth, imageWidth);
 		int dy = MulDiv(pt.y - m_videoBorderDragStartPt.y, kVideoHeight, imageHeight);
 

+ 3 - 3
zhipuzi_pos_windows/page/CSettingPageUI.h

@@ -65,12 +65,12 @@ private:
 	HBITMAP m_hBitmap = NULL;
 	HDC m_hMemDC = NULL;
 
-	//红色裁剪框的位置Rect,这个坐标是相对800*600的真实坐标,可以直接存入数据库的,不随视频实际显示的尺寸变化,实际显示的红框会根据显示区域尺寸来同比例缩放
+	//红色裁剪框的位置Rect,这个坐标是相对800*600的真实坐标,不随视频实际显示的尺寸变化,实际显示的红框会根据显示区域尺寸来同比例缩放
 	RECT m_videoBorderRect = { 0, 0, 800, 600 };
 	RECT m_videoBorderDragStartRect = { 0, 0, 800, 600 };
 	POINT m_videoBorderDragStartPt = { 0, 0 };
-	
-	bool m_videoBorderLoaded = false;
+
+	const int m_kVideoGripSize = 8;
 
 	bool m_isDraggingVideoBorder = false;
 	int m_videoBorderHitType = HTNOWHERE;

BIN
zhipuzi_pos_windows/resource/skin.zip


+ 25 - 0
zhipuzi_pos_windows/tool/CSetting.cpp

@@ -597,6 +597,31 @@ void CSetting::Init()
 		m_paramsMap[diandan_moling_type] = "0";
 	}
 
+	//AI识别摄像头裁剪框的参数
+	std::string setting_ai_video_rect_x = "setting_ai_video_rect_x";
+	if (m_paramsMap.find(setting_ai_video_rect_x) == m_paramsMap.end())
+	{
+		m_paramsMap[setting_ai_video_rect_x] = "0";
+	}
+
+	std::string setting_ai_video_rect_y = "setting_ai_video_rect_y";
+	if (m_paramsMap.find(setting_ai_video_rect_y) == m_paramsMap.end())
+	{
+		m_paramsMap[setting_ai_video_rect_y] = "0";
+	}
+
+	std::string setting_ai_video_rect_w = "setting_ai_video_rect_w";
+	if (m_paramsMap.find(setting_ai_video_rect_w) == m_paramsMap.end())
+	{
+		m_paramsMap[setting_ai_video_rect_w] = "800";
+	}
+
+	std::string setting_ai_video_rect_h = "setting_ai_video_rect_h";
+	if (m_paramsMap.find(setting_ai_video_rect_h) == m_paramsMap.end())
+	{
+		m_paramsMap[setting_ai_video_rect_h] = "600";
+	}
+
 	m_mutex.unlock();
 
 	//设置好默认参数之后,将默认参数写回到数据库

+ 72 - 5
zhipuzi_pos_windows/tool/CVideoCapture.cpp

@@ -68,17 +68,15 @@ void CVideoCapture::InitVideoCapture()
 	1280×720(720p HD):标准高清分辨率,广泛用于人脸识别、目标检测等视觉任务
 	1920×1080(1080p Full HD):全高清分辨率,提供高质量图像,适用于高精度视觉分析
 	*/
-	int width = 800;
-	int height = 600;
 
-	m_cap.set(cv::CAP_PROP_FRAME_WIDTH, width);
-	m_cap.set(cv::CAP_PROP_FRAME_HEIGHT, height);
+	m_cap.set(cv::CAP_PROP_FRAME_WIDTH, m_kVideoWidth);
+	m_cap.set(cv::CAP_PROP_FRAME_HEIGHT, m_kVideoHeight);
 
 	// 验证设置是否成功
 	double actualWidth = m_cap.get(cv::CAP_PROP_FRAME_WIDTH);
 	double actualHeight = m_cap.get(cv::CAP_PROP_FRAME_HEIGHT);
 
-	std::cout << "设置的分辨率: " << width << " x " << height << std::endl;
+	std::cout << "设置的分辨率: " << m_kVideoWidth << " x " << m_kVideoHeight << std::endl;
 	std::cout << "实际分辨率: " << actualWidth << " x " << actualHeight << std::endl;
 
 	//CLewaimaiLog::OutputMessageBoxFormat(L"摄像头分辨率设置为: %d x %d\n实际分辨率: %.0f x %.0f", width, height, actualWidth, actualHeight);
@@ -98,6 +96,9 @@ void CVideoCapture::InitVideoCapture()
 	//m_cap.set(cv::CAP_PROP_WB_TEMPERATURE, 3300);
 	// 降低饱和度,高光不易一片惨白
 	//m_cap.set(cv::CAP_PROP_SATURATION, 40);
+
+	//初始化裁剪框区域, 如果设置中心重新设置了区域会自动同步到这里
+	this->LoadVideoBorderRect();
 }
 
 bool CVideoCapture::GetFrame(cv::Mat& frame)
@@ -126,4 +127,70 @@ bool CVideoCapture::GetFrame(cv::Mat& frame)
 	//cv::destroyAllWindows();
 
 	return true;
+}
+
+void CVideoCapture::LoadVideoBorderRect()
+{
+	auto readInt = [](const std::string& value, int defaultValue) -> int
+		{
+			if (value.empty())
+			{
+				return defaultValue;
+			}
+
+			return atoi(value.c_str());
+		};
+
+	int x = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_x"), 0);
+	int y = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_y"), 0);
+	int w = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_w"), m_kVideoWidth);
+	int h = readInt(CSetting::GetInstance()->GetParam("setting_ai_video_rect_h"), m_kVideoHeight);
+
+	if (w < m_kVideoBorderMinWidth) w = m_kVideoBorderMinWidth;
+	if (h < m_kVideoBorderMinHeight) h = m_kVideoBorderMinHeight;
+	if (w > m_kVideoWidth) w = m_kVideoWidth;
+	if (h > m_kVideoHeight) h = m_kVideoHeight;
+
+	if (x < 0) x = 0;
+	if (y < 0) y = 0;
+	if (x + w > m_kVideoWidth) x = m_kVideoWidth - w;
+	if (y + h > m_kVideoHeight) y = m_kVideoHeight - h;
+
+	m_videoBorderRect.left = x;
+	m_videoBorderRect.top = y;
+	m_videoBorderRect.right = x + w;
+	m_videoBorderRect.bottom = y + h;
+}
+
+void CVideoCapture::HandleCutFrame(const cv::Mat& frame, cv::Mat& cut_frame)
+{
+	cut_frame = frame(cv::Rect(m_videoBorderRect.left, m_videoBorderRect.top, m_videoBorderRect.right - m_videoBorderRect.left, m_videoBorderRect.bottom - m_videoBorderRect.top));
+}
+
+void CVideoCapture::HandleResizeAndPaddingFrame(const cv::Mat& frame, cv::Mat& processed_frame)
+{
+	//按长边缩放到448
+	int w = frame.cols;
+	int h = frame.rows;
+
+	// 计算缩放比例,长边对齐448
+	float scale = std::min((float)m_target_size / w, (float)m_target_size / h);
+	int new_w = int(w * scale);
+	int new_h = int(h * scale);
+
+	cv::Mat resized;
+	cv::resize(frame, resized, cv::Size(new_w, new_h), cv::INTER_LINEAR);
+
+	//填充灰色边框,补齐 448×448 正方形(和训练 padding 逻辑一致)
+	// 计算上下左右需要填充的像素
+	int top = (m_target_size - new_h) / 2;
+	int bottom = m_target_size - new_h - top;
+	int left = (m_target_size - new_w) / 2;
+	int right = m_target_size - new_w - left;
+
+	// YOLO训练填充灰色 (114,114,114)
+	cv::copyMakeBorder(resized, processed_frame, top, bottom, left, right,
+		cv::BORDER_CONSTANT, cv::Scalar(114, 114, 114));
+
+	// 此时 processed_frame 尺寸固定 448×448
 }

+ 55 - 1
zhipuzi_pos_windows/tool/CVideoCapture.h

@@ -3,7 +3,6 @@
 #include <opencv2/opencv.hpp>
 #include <opencv2/dnn.hpp>
 
-//这个Worker只负责从摄像头读取图像数据,不负责进行任何处理
 class CVideoCapture
 {
 public:
@@ -17,17 +16,72 @@ public:
 		return &instance;
 	}
 
+	//初始化摄像头,打开摄像头,如果摄像头打开失败,会在日志里输出错误信息
 	void InitVideoCapture();
 
+	//读取不经过任何处理的摄像头的原始帧
 	bool GetFrame(cv::Mat& frame);
 
+	//对frame进行裁减,裁减位置由m_videoBorderRect决定
+	void HandleCutFrame(const cv::Mat& frame, cv::Mat& cut_frame);
+
+	//对frame进行缩放、灰度填充,得到符合训练要求的图片【这个里面不再进行裁减】
+	void HandleResizeAndPaddingFrame(const cv::Mat& frame, cv::Mat& processed_frame);
+
+	void SetVideoBorderRect(const RECT& rect)
+	{
+		m_videoBorderRect = rect;
+	}
+
+	RECT& GetVideoBorderRect()
+	{
+		return m_videoBorderRect;
+	}
+	 
+	int GetVideoWidth()
+	{
+		return m_kVideoWidth;
+	}
+
+	int GetVideoHeight()
+	{
+		return m_kVideoHeight;
+	}
+
+	int GetVideoBorderMinWidth()
+	{
+		return m_kVideoBorderMinWidth;
+	}
+
+	int GetVideoBorderMinHeight()
+	{
+		return m_kVideoBorderMinHeight;
+	}
+
 private:
 	int findAvailableCamera();	
 
+	//从数据库读取红色边框存储的矩形位置,保存到m_videoBorderRect中
+	void LoadVideoBorderRect();
+
 private:
 	bool m_is_video_capture_open = false;
 
 	cv::VideoCapture m_cap;
 
 	std::mutex m_init_mutex;
+
+	//红色裁剪框的位置Rect,这个坐标是相对800*600的真实坐标,可以直接存入数据库的,不随视频实际显示的尺寸变化,实际显示的红框会根据显示区域尺寸来同比例缩放
+	RECT m_videoBorderRect = { 0, 0, 800, 600 };
+
+	//原始帧的尺寸
+	const int m_kVideoWidth = 800;
+	const int m_kVideoHeight = 600;
+
+	//红色边框的最小尺寸
+	const int m_kVideoBorderMinWidth = 448;
+	const int m_kVideoBorderMinHeight = 320;
+
+	//推理图片的目标尺寸
+	const int m_target_size = 448;
 };

+ 7 - 2
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -74,6 +74,11 @@ void CDiandanAIShibieWorker::DoAIShibie()
 			return;
 		}
 
+		//对摄像头拍摄的图片进行预处理,主要是裁减、缩放、填充灰色背景,裁减的区域是根据设置的裁减区域来定的
+		CVideoCapture::GetInstance()->HandleCutFrame(image, image);
+		CVideoCapture::GetInstance()->HandleResizeAndPaddingFrame(image, image);
+
+		//裁剪完,填充完,才开始进行推理计算
 		m_ai_shibie_foodname = YoloFeatureManager::GetInstance()->Class(image);
 		if (m_ai_shibie_foodname != "Unknown")
 		{
@@ -160,8 +165,8 @@ void CDiandanAIShibieWorker::DoAIShibie()
 	}
 	catch (const std::exception& e)
 	{
-		std::string aa = std::string(e.what());
-		CLewaimaiLog::OutputDebugMessage(("AI识别失败: " + std::string(e.what())).c_str());
+		std::string err = std::string(e.what());
+		CLewaimaiLog::OutputDebugMessage(("AI识别失败: " + err).c_str());
 	}
 }