From eda1a611bc4afcf1c36a6c728f432aec1f688e1b Mon Sep 17 00:00:00 2001
From: admin <weikou2014>
Date: 星期一, 27 六月 2022 19:13:36 +0800
Subject: [PATCH] 'GP代码识别'

---
 ConsoleApplication/RecognitionManager.h               |   11 
 ConsoleApplication/OpenCLExcuter.cpp                  |   47 +-
 ConsoleApplication/RecognitionManager.cpp             |   52 +++
 ConsoleApplication/THSActionUtil.h                    |   17 
 ConsoleApplication/ImgUtil.h                          |   49 ++
 ConsoleApplication/ConsoleApplication.vcxproj.filters |    6 
 ConsoleApplication/OpenclTest.cpp                     |   22 
 ConsoleApplication/main.cpp                           |   58 +++
 ConsoleApplication/ConsoleApplication.vcxproj         |    2 
 ConsoleApplication/ScreenDataCapture.cpp              |   18 
 ConsoleApplication/kernel.cl                          |   99 +++---
 ConsoleApplication/OpenCLExcuter.h                    |    6 
 ConsoleApplication/Win32Util.h                        |   33 ++
 ConsoleApplication/THSActionUtil.cpp                  |  238 ++++++++++++++-
 ConsoleApplication/Win32Util.cpp                      |  105 +++++++
 ConsoleApplication/ImgUtil.cpp                        |  137 +++++++-
 16 files changed, 735 insertions(+), 165 deletions(-)

diff --git a/ConsoleApplication/ConsoleApplication.vcxproj b/ConsoleApplication/ConsoleApplication.vcxproj
index 5d14a44..03222e6 100644
--- a/ConsoleApplication/ConsoleApplication.vcxproj
+++ b/ConsoleApplication/ConsoleApplication.vcxproj
@@ -154,6 +154,7 @@
     <ClCompile Include="ScreenDataCapture.cpp" />
     <ClCompile Include="OpenclTest.cpp" />
     <ClCompile Include="THSActionUtil.cpp" />
+    <ClCompile Include="Win32Util.cpp" />
     <ClCompile Include="win32_screen_shots.cpp" />
   </ItemGroup>
   <ItemGroup>
@@ -168,6 +169,7 @@
     <ClInclude Include="resource.h" />
     <ClInclude Include="ScreenDataCapture.h" />
     <ClInclude Include="THSActionUtil.h" />
+    <ClInclude Include="Win32Util.h" />
     <ClInclude Include="win32_screen_shots.h" />
   </ItemGroup>
   <ItemGroup>
diff --git a/ConsoleApplication/ConsoleApplication.vcxproj.filters b/ConsoleApplication/ConsoleApplication.vcxproj.filters
index 9f56599..8eee256 100644
--- a/ConsoleApplication/ConsoleApplication.vcxproj.filters
+++ b/ConsoleApplication/ConsoleApplication.vcxproj.filters
@@ -51,6 +51,9 @@
     <ClCompile Include="THSActionUtil.cpp">
       <Filter>婧愭枃浠�</Filter>
     </ClCompile>
+    <ClCompile Include="Win32Util.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="resource.h">
@@ -89,6 +92,9 @@
     <ClInclude Include="THSActionUtil.h">
       <Filter>澶存枃浠�</Filter>
     </ClInclude>
+    <ClInclude Include="Win32Util.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ConsoleApplication.rc">
diff --git a/ConsoleApplication/ImgUtil.cpp b/ConsoleApplication/ImgUtil.cpp
index bb56699..6299532 100644
--- a/ConsoleApplication/ImgUtil.cpp
+++ b/ConsoleApplication/ImgUtil.cpp
@@ -1,9 +1,65 @@
 #include "ImgUtil.h"
 
-NumberData ImgUtil::NUMS[10];
-uchar* ImgUtil::numsOneLevel;
-const int ImgUtil::NUM_WIDTH;
-const int ImgUtil::NUM_HEIGHT;
+NumberData ImgUtil::NUMS_LEVEL2[10];
+NumberData ImgUtil::NUMS_GP_CODE[10];
+uchar* ImgUtil::numsOneLevel_level2;
+uchar* ImgUtil::numsOneLevel_gpcode;
+
+cv::Mat  ImgUtil::formatNumGPCode(cv::Mat num)  throw(string) {
+	if (num.empty()) {
+		//空值填充0
+		cv::Mat zero;
+		ImgUtil::NUMS_GP_CODE[0].data.copyTo(zero);
+		return zero;
+	}
+
+	//去除周围的黑边
+	int rows = num.rows;
+	int cols = num.cols;
+	int startRow = -1, endRow = -1;
+	for (int r = 0;r < rows;r++) {
+		if (!ImgDivider::isRowEmpty(num, r)) {
+			startRow = r;
+			break;
+		}
+	}
+
+	for (int r = rows - 1;r > -1;r--) {
+		if (!ImgDivider::isRowEmpty(num, r)) {
+			endRow = r;
+			break;
+		}
+	}
+	//去除前后的白边
+	int startCol = -1, endCol = -1;
+	for (int c = 0;c < cols;c++) {
+		if (!ImgDivider::isColEmpty(num, c, 1)) {
+			startCol = c;
+			break;
+		}
+	}
+
+	for (int c = cols - 1;c > -1;c--) {
+		if (!ImgDivider::isColEmpty(num, c, 1)) {
+			endCol = c;
+			break;
+		}
+	}
+
+	num = cv::Mat(num, cv::Rect(startCol, startRow, endCol - startCol + 1, endRow - startRow + 1));
+
+	//判断列数是否正常
+	if (num.cols == _NUMBER_GP_CODE_WIDTH && num.rows == _NUMBER_GP_CODE_HEIGHT) {
+		return num;
+	}
+	//往右下角添加数据
+	cv::Mat m = cv::Mat::zeros(num.rows, _NUMBER_GP_CODE_WIDTH - num.cols, CV_8UC1);
+	cv::Mat dst;
+	cv::hconcat(num, m, dst);
+	return dst;
+}
+
+
 
 //分隔时间
 list<cv::Mat> ImgUtil::splitTime(cv::Mat src) throw(std::string) {
@@ -199,7 +255,7 @@
 list<cv::Mat> ImgUtil::splitNum(cv::Mat src)  throw(string) {
 	cv::Mat binary;
 	//去除上下的空白图
-	threshold(src, binary, 40, 255, cv::THRESH_BINARY);
+	threshold(src, binary, _IMG_BINARY_THRESHOLD, 255, cv::THRESH_BINARY);
 	int rows = src.rows;
 	int cols = src.cols;
 
@@ -286,11 +342,11 @@
 	return resultList;
 }
 
-cv::Mat  ImgUtil::formatNum(cv::Mat num)  throw(string) {
+cv::Mat  ImgUtil::formatNumLevel2(cv::Mat num)  throw(string) {
 	if (num.empty()) {
 		//空值填充0
 		cv::Mat zero;
-		ImgUtil::NUMS[0].data.copyTo(zero);
+		ImgUtil::NUMS_LEVEL2[0].data.copyTo(zero);
 		return zero;
 	}
 
@@ -330,11 +386,11 @@
 	num = cv::Mat(num, cv::Rect(startCol, startRow, endCol - startCol + 1, endRow - startRow + 1));
 
 	//判断列数是否正常
-	if (num.cols == 5 && num.rows == 8) {
+	if (num.cols == _NUMBER_L2_WIDTH && num.rows == _NUMBER_L2_HEIGHT) {
 		return num;
 	}
 	//往右下角添加数据
-	cv::Mat m = cv::Mat::zeros(num.rows, 5 - num.cols, CV_8UC1);
+	cv::Mat m = cv::Mat::zeros(num.rows, _NUMBER_L2_WIDTH - num.cols, CV_8UC1);
 	cv::Mat dst;
 	cv::hconcat(num, m, dst);
 	return dst;
@@ -351,27 +407,50 @@
 
 void ImgUtil::init() {
 
-
+	//LEVE2数字初始化
 	for (int i = 0;i < 10;i++) {
 		std::string sdir = "C:\\Users\\Administrator\\Desktop\\ocr\\number\\";
 		std::string path = sdir.append(std::to_string(i)).append(".jpg");
 		NumberData data = NumberData();
-		data.data = formatNum(cv::imread(path.c_str(), cv::IMREAD_GRAYSCALE));
+		data.data = formatNumLevel2(cv::imread(path.c_str(), cv::IMREAD_GRAYSCALE));
 		data.num = std::to_string(i);
-		NUMS[i] = data;
+		NUMS_LEVEL2[i] = data;
 	}
 
-	numsOneLevel = (uchar*)malloc(sizeof(uchar) * NUM_HEIGHT * NUM_WIDTH * 10);
+	numsOneLevel_level2 = (uchar*)malloc(sizeof(uchar) * _NUMBER_L2_HEIGHT * _NUMBER_L2_WIDTH * 10);
 	for (int i = 0;i < 10;i++) {
-		int baseIndex = i * NUM_HEIGHT * NUM_WIDTH;
-		for (int r = 0;r < NUM_HEIGHT;r++) {
-			int baseIndex_1 = r * NUM_WIDTH;
-			for (int c = 0;c < NUM_WIDTH;c++) {
+		int baseIndex = i * _NUMBER_L2_HEIGHT * _NUMBER_L2_WIDTH;
+		for (int r = 0;r < _NUMBER_L2_HEIGHT;r++) {
+			int baseIndex_1 = r * _NUMBER_L2_WIDTH;
+			for (int c = 0;c < _NUMBER_L2_WIDTH;c++) {
 				int index = baseIndex + baseIndex_1 + c;
-				numsOneLevel[index] = NUMS[i].data.ptr<uchar>(r)[c];
+				numsOneLevel_level2[index] = NUMS_LEVEL2[i].data.ptr<uchar>(r)[c];
 			}
 		}
 	}
+
+
+	for (int i = 0;i < 10;i++) {
+		std::string sdir = "C:\\Users\\Administrator\\Desktop\\ocr\\number_2\\";
+		std::string path = sdir.append(std::to_string(i)).append(".jpg");
+		NumberData data = NumberData();
+		data.data = formatNumGPCode(cv::imread(path.c_str(), cv::IMREAD_GRAYSCALE));
+		data.num = std::to_string(i);
+		NUMS_GP_CODE[i] = data;
+	}
+
+	numsOneLevel_gpcode = (uchar*)malloc(sizeof(uchar) * _NUMBER_GP_CODE_HEIGHT * _NUMBER_GP_CODE_WIDTH * 10);
+	for (int i = 0;i < 10;i++) {
+		int baseIndex = i * _NUMBER_GP_CODE_HEIGHT * _NUMBER_GP_CODE_WIDTH;
+		for (int r = 0;r < _NUMBER_GP_CODE_HEIGHT;r++) {
+			int baseIndex_1 = r * _NUMBER_GP_CODE_WIDTH;
+			for (int c = 0;c < _NUMBER_GP_CODE_WIDTH;c++) {
+				int index = baseIndex + baseIndex_1 + c;
+				numsOneLevel_gpcode[index] = NUMS_GP_CODE[i].data.ptr<uchar>(r)[c];
+			}
+		}
+	}
+
 }
 
 list<int*> ImgUtil::divideImg(cv::Mat img) {
@@ -790,14 +869,14 @@
 
 
 	//将所有的数字格式化为5*8的点阵格式
-	int ROW = ImgUtil::NUM_HEIGHT, COL = ImgUtil::NUM_WIDTH;
-	int rowData = ROW * COL * 10 * 17;
+	int ROW = _NUMBER_L2_HEIGHT, COL = _NUMBER_L2_WIDTH;
+	int rowData = ROW * COL * 10 * _NUMBER_L2_TOTAL_NUMBER;
 
 	list<cv::Mat>::iterator eleM;
 	index = 0;
 	for (eleM = numList.begin();eleM != numList.end();eleM++) {
 		index++;
-		cv::Mat numMat = formatNum(*eleM);
+		cv::Mat numMat = formatNumLevel2(*eleM);
 		//转为数组的形式
 		for (int r = 0;r < ROW;r++) {
 			//将每个数字重复加入10次,用于矩阵相减
@@ -846,25 +925,25 @@
 }
 
 uchar* ImgUtil::createTemplateNumData(int lines) {
-	int LINE_NUMBER_COUNT = 17;
+	int LINE_NUMBER_COUNT = _NUMBER_L2_TOTAL_NUMBER;
 	int NUMBER_COUNT = 10;
-	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (ImgUtil::NUM_HEIGHT * lines) * ImgUtil::NUM_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT);
-	int outLineDataCount = ImgUtil::NUM_HEIGHT * ImgUtil::NUM_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT;
-	int inLineDataCount = ImgUtil::NUM_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT;
+	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * lines) * _NUMBER_L2_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT);
+	int outLineDataCount = _NUMBER_L2_HEIGHT * _NUMBER_L2_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT;
+	int inLineDataCount = _NUMBER_L2_WIDTH * NUMBER_COUNT * LINE_NUMBER_COUNT;
 	for (int l = 0;l < lines;l++)
 	{
 		int outLineCount = outLineDataCount * l;
 		for (int re = 0;re < LINE_NUMBER_COUNT;re++) {
 			for (int n = 0;n < NUMBER_COUNT;n++)
 			{
-				for (int r = 0;r < ImgUtil::NUM_HEIGHT;r++) {
+				for (int r = 0;r < _NUMBER_L2_HEIGHT;r++) {
 					int intLineCount = inLineDataCount * r;
 
-					for (int c = 0;c < ImgUtil::NUM_WIDTH;c++) {
-						uchar value = ImgUtil::NUMS[n].data.ptr(r)[c];
+					for (int c = 0;c < _NUMBER_L2_WIDTH;c++) {
+						uchar value = ImgUtil::NUMS_LEVEL2[n].data.ptr(r)[c];
 						int index = outLineCount;
 						index += intLineCount;
-						int x = re * NUMBER_COUNT * ImgUtil::NUM_WIDTH + n * ImgUtil::NUM_WIDTH + c;
+						int x = re * NUMBER_COUNT * _NUMBER_L2_WIDTH + n * _NUMBER_L2_WIDTH + c;
 						index += x;
 						data[index] = value > 40 ? 1 : 0;
 					}
diff --git a/ConsoleApplication/ImgUtil.h b/ConsoleApplication/ImgUtil.h
index 9c0694a..91603e2 100644
--- a/ConsoleApplication/ImgUtil.h
+++ b/ConsoleApplication/ImgUtil.h
@@ -19,18 +19,47 @@
 
 #include "win32_screen_shots.h"
 
+#ifndef _NUMBER_L2_WIDTH
+#define _NUMBER_L2_WIDTH 5
+#endif 
 
+#ifndef _NUMBER_L2_HEIGHT
+#define _NUMBER_L2_HEIGHT 8
+#endif 
+
+#ifndef _NUMBER_L2_TOTAL_NUMBER
+#define _NUMBER_L2_TOTAL_NUMBER 17
+#endif 
+
+
+#ifndef _NUMBER_GP_CODE_WIDTH
+#define _NUMBER_GP_CODE_WIDTH 11
+#endif 
+
+#ifndef _NUMBER_GP_CODE_HEIGHT
+#define _NUMBER_GP_CODE_HEIGHT 14
+#endif 
+
+#ifndef _NUMBER_GP_CODE_TOTAL_NUMBER
+#define _NUMBER_GP_CODE_TOTAL_NUMBER 6
+#endif  
+
+#ifndef _IMG_BINARY_THRESHOLD
+#define _IMG_BINARY_THRESHOLD 64
+#endif 
 
 
 using namespace std;
 class ImgUtil
 {
 public:
-	static NumberData NUMS[10];
+	static NumberData NUMS_LEVEL2[10];
+	static NumberData NUMS_GP_CODE[10];
+
+
 	//数字(0-9)一维数据
-	static uchar* numsOneLevel;
-	static const int NUM_WIDTH = 5;
-	static const int NUM_HEIGHT = 8;
+	static uchar* numsOneLevel_level2;
+	static uchar* numsOneLevel_gpcode;
 
 
 private:
@@ -38,10 +67,11 @@
 	static list<cv::Mat> splitTime(cv::Mat img)  throw(string);
 	//分隔小数,中间的空Mat表示小数点
 	static list<cv::Mat> splitDecimal(cv::Mat img)  throw(string);
-	//分隔整数
-	static list<cv::Mat> splitNum(cv::Mat img)  throw(string);
+
 	//将0-9的数字图片做格式化
-	static cv::Mat formatNum(cv::Mat num)  throw(string);
+	static cv::Mat formatNumLevel2(cv::Mat num)  throw(string);
+
+
 
 public:
 
@@ -65,6 +95,11 @@
 
 	//构建模板数据,用于opencl矩阵运算中的数字识别
 	static uchar* createTemplateNumData(int lines);
+
+	//分隔整数
+	static list<cv::Mat> splitNum(cv::Mat img)  throw(string);
+
+	static cv::Mat formatNumGPCode(cv::Mat num)  throw(string);
 };
 
 
diff --git a/ConsoleApplication/OpenCLExcuter.cpp b/ConsoleApplication/OpenCLExcuter.cpp
index d94176c..2df0471 100644
--- a/ConsoleApplication/OpenCLExcuter.cpp
+++ b/ConsoleApplication/OpenCLExcuter.cpp
@@ -62,13 +62,13 @@
 }
 
 
-unsigned char** OpenCLExcuter::recognition_numbers(unsigned char* data, unsigned char* b_in, const int rows, const int cols) throw(std::string) {
+unsigned char** OpenCLExcuter::recognition_numbers(unsigned char* data, unsigned char* b_in, const int rows, const int cols,const int num_width, const int num_height, const int num_count) throw(std::string) {
 	//----------程序正文开始---------
 	auto startexectime = std::chrono::steady_clock::now();
-	const int resultSize = rows * cols / (5 * 8);
+	const int resultSize = rows * cols / (num_width * num_height);
 	const int inputSize = rows * cols;
 	//创建内核
-	kernel = clCreateKernel(program, "test1", &error);
+	kernel = clCreateKernel(program, "recognition_numbers_1", &error);
 	if (kernel == NULL) {
 		throw("Couldn't create kernel!\n");
 	}
@@ -92,12 +92,15 @@
 		throw("Creat memObject4 failed!\n");
 	}
 
-	int width = cols / 5;
+	int width = cols / num_width;
 	//设置内核参数
 	error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
 	error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
 	error |= clSetKernelArg(kernel, 2, sizeof(int), &width);
-	error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), &memObject4);
+	error |= clSetKernelArg(kernel, 3, sizeof(int), &num_width);
+	error |= clSetKernelArg(kernel, 4, sizeof(int), &num_height);
+	error |= clSetKernelArg(kernel, 5, sizeof(int), &num_count);
+	error |= clSetKernelArg(kernel, 6, sizeof(cl_mem), &memObject4);
 	if (error != CL_SUCCESS) {
 		throw("Error setting kernel arguments!\n");
 	}
@@ -134,7 +137,7 @@
 	int resultSize2 = resultSize / 10;
 	unsigned char* result2 = (unsigned char*)malloc(sizeof(unsigned char) * resultSize2);
 
-	kernel = clCreateKernel(program, "test2", &error);
+	kernel = clCreateKernel(program, "recognition_numbers_2", &error);
 	if (kernel == NULL) {
 		throw("Couldn't create kernel!\n");
 	}
@@ -191,8 +194,8 @@
 	clReleaseMemObject(memObject22);
 
 	//复制最后的计算结果
-	int fcol = 17;
-	int frow = rows / 8;
+	int fcol = num_count;
+	int frow = rows / num_height;
 	unsigned char** fresult = (unsigned char**)malloc(sizeof(unsigned char*) * frow);
 
 	for (int r = 0; r < frow; r++) {
@@ -209,17 +212,17 @@
 
 
 
-void OpenCLExcuter::splitNum(unsigned char* img, int img_width, int img_height, int* pos, int pos_count, unsigned char* zero, unsigned char* result) {
+void OpenCLExcuter::splitNum(unsigned char* img, int img_width, int img_height, int* pos, int pos_count, unsigned char* zero, int num_width,int num_height,int num_count, unsigned char* result) {
 	clock_t time_0 = clock();
 
-	kernel = clCreateKernel(program, "test4", &error);
+	kernel = clCreateKernel(program, "split_num", &error);
 	if (kernel == NULL) {
 		throw("Couldn't create kernel!\n");
 	}
 
 	int inputSize = (img_width * img_height);
 
-	int resultSize = (pos_count / 3) * (17 * 5 * 8 * 10);
+	int resultSize = (pos_count / 3) * (num_count * num_width * num_height * 10);
 
 
 	//创建缓存对象
@@ -236,7 +239,7 @@
 	}
 
 	cl_mem memObject3 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-		sizeof(unsigned char) * 5 * 8, zero, &error);
+		sizeof(unsigned char) * num_width * num_height, zero, &error);
 	if (error < 0) {
 		throw("Creat memObject3 failed!\n");
 	}
@@ -252,7 +255,10 @@
 	error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
 	error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObject3);
 	error |= clSetKernelArg(kernel, 3, sizeof(int), &img_width);
-	error |= clSetKernelArg(kernel, 4, sizeof(cl_mem), &memObject4);
+	error |= clSetKernelArg(kernel, 4, sizeof(int), &num_width);
+	error |= clSetKernelArg(kernel, 5, sizeof(int), &num_height);
+	error |= clSetKernelArg(kernel, 6, sizeof(int), &num_count);
+	error |= clSetKernelArg(kernel, 7, sizeof(cl_mem), &memObject4);
 	if (error != CL_SUCCESS) {
 		throw("Error setting kernel arguments!\n");
 	}
@@ -287,20 +293,20 @@
 
 
 
-void OpenCLExcuter::createNumberTemplates(int lines, unsigned char* result) {
+void OpenCLExcuter::createNumberTemplates(int lines,int num_width,int num_height,int num_count, uchar* numsOneLevelData, unsigned char* result) {
 	kernel = clCreateKernel(program, "createTemplateNumbers", &error);
 	if (kernel == NULL) {
 		throw("Couldn't create kernel!\n");
 	}
 
 
-	int inputSize = ImgUtil::NUM_HEIGHT * ImgUtil::NUM_WIDTH * 10;
-	int resultSize = lines * 17 * 10 * ImgUtil::NUM_HEIGHT * ImgUtil::NUM_WIDTH;
+	int inputSize = num_height * num_width * 10;
+	int resultSize = lines * num_count * 10 * num_height * num_width;
 
 
 	//创建缓存对象
 
-	cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(uchar) * inputSize, ImgUtil::numsOneLevel, &error);
+	cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(uchar) * inputSize, numsOneLevelData, &error);
 	if (error < 0) {
 		throw("Creat memObject1 failed!\n");
 	}
@@ -313,11 +319,12 @@
 	}
 
 
-	int line_nums = 17;
 	//设置内核参数
 	error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
-	error |= clSetKernelArg(kernel, 1, sizeof(int), &line_nums);
-	error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObject2);
+	error |= clSetKernelArg(kernel, 1, sizeof(int), &num_width);
+	error |= clSetKernelArg(kernel, 2, sizeof(int), &num_height);
+	error |= clSetKernelArg(kernel, 3, sizeof(int), &num_count);
+	error |= clSetKernelArg(kernel, 4, sizeof(cl_mem), &memObject2);
 
 	if (error != CL_SUCCESS) {
 		throw("Error setting kernel arguments!\n");
diff --git a/ConsoleApplication/OpenCLExcuter.h b/ConsoleApplication/OpenCLExcuter.h
index bc3a7a4..ca72c44 100644
--- a/ConsoleApplication/OpenCLExcuter.h
+++ b/ConsoleApplication/OpenCLExcuter.h
@@ -30,13 +30,13 @@
 public:
 	void init();
 	void destory();
-	unsigned char** recognition_numbers(unsigned char* data, unsigned char* template_num, const int rows, const int cols);
+	unsigned char** recognition_numbers(unsigned char* data, unsigned char* b_in, const int rows, const int cols, const int num_width, const int num_height, const int num_count);
 
 	//分隔每一行需要识别的数字
-	void splitNum(unsigned char* img, int img_width, int img_height, int* pos, int pos_count, unsigned char* zero, unsigned char* result);
+	void splitNum(unsigned char* img, int img_width, int img_height, int* pos, int pos_count, unsigned char* zero, int num_width, int num_height, int number_count, unsigned char* result);
 
 	//创建识别的数字模板
-	void createNumberTemplates(int lines, unsigned char* result);
+	void createNumberTemplates(int lines, int num_width, int num_height, int num_count, uchar* numsOneLevelData, unsigned char* result);
 
 	//分隔行数据
 	void splitRowData(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int lines,
diff --git a/ConsoleApplication/OpenclTest.cpp b/ConsoleApplication/OpenclTest.cpp
index 16337f6..673c0b4 100644
--- a/ConsoleApplication/OpenclTest.cpp
+++ b/ConsoleApplication/OpenclTest.cpp
@@ -11,7 +11,7 @@
 uchar* createTemplateData(int line);
 
 int LINE_NUMBER = 10;
-int RE = 17;
+int RE = _NUMBER_L2_TOTAL_NUMBER;
 
 
 
@@ -253,7 +253,7 @@
 	op->init();
 	for (int i = 0;i < 100;i++)
 	{
-		op->recognition_numbers(a_in, b_in, rows, cols);
+		op->recognition_numbers(a_in, b_in, rows, cols ,_NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER);
 	}
 	op->destory();
 
@@ -261,7 +261,7 @@
 }
 
 uchar* createDemoData(int line) {
-	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (ImgUtil::NUM_HEIGHT * line) * 5 * LINE_NUMBER * RE);
+	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * line) * 5 * LINE_NUMBER * RE);
 	int outLineDataCount = 8 * 5 * LINE_NUMBER * RE;
 	int inLineDataCount = 5 * LINE_NUMBER * RE;
 	for (int l = 0;l < line;l++)
@@ -277,7 +277,7 @@
 					int intLineCount = inLineDataCount * r;
 
 					for (int c = 0;c < 5;c++) {
-						uchar value = ImgUtil::NUMS[re%10].data.ptr(r)[c];
+						uchar value = ImgUtil::NUMS_LEVEL2[re%10].data.ptr(r)[c];
 						int index = outLineCount;
 						index += intLineCount;
 						int x = re * LINE_NUMBER * 5 + n * 5 + c;
@@ -292,23 +292,23 @@
 }
 
 uchar* createTemplateData(int line) {
-	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (ImgUtil::NUM_HEIGHT * line) * ImgUtil::NUM_WIDTH * LINE_NUMBER * RE);
-	int outLineDataCount = ImgUtil::NUM_HEIGHT * ImgUtil::NUM_WIDTH * LINE_NUMBER * RE;
-	int inLineDataCount = ImgUtil::NUM_WIDTH * LINE_NUMBER * RE;
+	unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * line) * _NUMBER_L2_WIDTH * LINE_NUMBER * RE);
+	int outLineDataCount = _NUMBER_L2_HEIGHT * _NUMBER_L2_WIDTH * LINE_NUMBER * RE;
+	int inLineDataCount = _NUMBER_L2_WIDTH * LINE_NUMBER * RE;
 	for (int l = 0;l < line;l++)
 	{
 		int outLineCount = outLineDataCount * l;
 		for (int re = 0;re < RE;re++) {
 			for (int n = 0;n < LINE_NUMBER;n++)
 			{
-				for (int r = 0;r < ImgUtil::NUM_HEIGHT;r++) {
+				for (int r = 0;r < _NUMBER_L2_HEIGHT;r++) {
 					int intLineCount = inLineDataCount * r;
 
-					for (int c = 0;c < ImgUtil::NUM_WIDTH;c++) {
-						uchar value = ImgUtil::NUMS[n].data.ptr(r)[c];
+					for (int c = 0;c < _NUMBER_L2_WIDTH;c++) {
+						uchar value = ImgUtil::NUMS_LEVEL2[n].data.ptr(r)[c];
 						int index = outLineCount;
 						index += intLineCount;
-						int x = re * LINE_NUMBER * ImgUtil::NUM_WIDTH + n * ImgUtil::NUM_WIDTH + c;
+						int x = re * LINE_NUMBER * _NUMBER_L2_WIDTH + n * _NUMBER_L2_WIDTH + c;
 						index += x;
 						data[index] = value > 40 ? 1 : 0;
 					}
diff --git a/ConsoleApplication/RecognitionManager.cpp b/ConsoleApplication/RecognitionManager.cpp
index 171c7dd..bec0797 100644
--- a/ConsoleApplication/RecognitionManager.cpp
+++ b/ConsoleApplication/RecognitionManager.cpp
@@ -1,5 +1,17 @@
 #include "RecognitionManager.h"
 
+
+
+RecognitionManager::RecognitionManager() {
+	openCLExcuter = new OpenCLExcuter();
+	openCLExcuter->init();
+}
+
+RecognitionManager::~RecognitionManager() {
+	openCLExcuter->destory();
+}
+
+
 TradeData RecognitionManager::recognition(cv::Mat img, int* rowData) {
 	TradeData tradeData = {};
 	for (int index = 1;index < 8;index++) {
@@ -506,4 +518,44 @@
 	LogUtil::debug("识别结果:%s\n", st.c_str());
 
 	return st;
+}
+
+list<uchar> RecognitionManager::recognitionGPCode(list<cv::Mat> imgList) {
+	
+	unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * 1) * _NUMBER_GP_CODE_WIDTH * 10 * imgList.size());
+	list<cv::Mat>::iterator ele;
+	int i = 0;
+	for (ele= imgList.begin();ele!= imgList.end();++ele)
+	{
+		int index_2 = i * 10 * _NUMBER_GP_CODE_WIDTH;
+		for (int n = 0;n < 10;n++)
+		{
+			int index_3= n * _NUMBER_GP_CODE_WIDTH;
+			cv::Mat img = ImgUtil::formatNumGPCode(*ele);
+
+			for (int r = 0;r < _NUMBER_GP_CODE_HEIGHT;r++)
+			{
+				int index_1 = r * imgList.size()* 10 * _NUMBER_GP_CODE_WIDTH;
+				for (int c = 0;c < _NUMBER_GP_CODE_WIDTH;c++) {
+					int index = index_1 + index_2+index_3 + c;
+					totalNumberData[index] = (img.ptr<uchar>(r)[c] >= _IMG_BINARY_THRESHOLD) ? 1 : 0;
+				}
+			}
+		}
+		i++;
+	}
+
+
+	uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * 1) * _NUMBER_GP_CODE_WIDTH * 10 * imgList.size());
+	openCLExcuter->createNumberTemplates(1, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, imgList.size(),ImgUtil::numsOneLevel_gpcode, templateNums);
+
+
+
+	uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, 1 * _NUMBER_GP_CODE_HEIGHT, _NUMBER_GP_CODE_WIDTH * 10* imgList.size(), _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, imgList.size());
+	list<uchar> resultList;
+	for (int i = 0;i < imgList.size();i++) {
+		uchar num= numberResult[0][i];
+		resultList.push_back(num);
+	}
+	return resultList;
 }
\ No newline at end of file
diff --git a/ConsoleApplication/RecognitionManager.h b/ConsoleApplication/RecognitionManager.h
index 1e25a22..80fc990 100644
--- a/ConsoleApplication/RecognitionManager.h
+++ b/ConsoleApplication/RecognitionManager.h
@@ -10,6 +10,7 @@
 
 #include "LogUtil.h"
 #include "error.h"
+#include "OpenCLExcuter.h"
 
 using namespace std;
 struct TradeData
@@ -32,7 +33,14 @@
 
 class RecognitionManager
 {
+
+private:
+	OpenCLExcuter *openCLExcuter;
+
 public:
+
+	RecognitionManager();
+	~RecognitionManager();
 	//识别某一行数据
 	TradeData recognition(cv::Mat img, int* rowData);
 	//识别所有的数据
@@ -50,6 +58,9 @@
 	//识别价格
 	string recognitionPrice(std::string path);
 	string recognitionPrice(cv::Mat img);
+
+	//数字识别
+	list<uchar> recognitionGPCode(list<cv::Mat> imgList);
 };
 
 
diff --git a/ConsoleApplication/ScreenDataCapture.cpp b/ConsoleApplication/ScreenDataCapture.cpp
index 6275e6a..bff7a56 100644
--- a/ConsoleApplication/ScreenDataCapture.cpp
+++ b/ConsoleApplication/ScreenDataCapture.cpp
@@ -91,7 +91,7 @@
 
 	//图像识别的数字准备
 
-	unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (ImgUtil::NUM_HEIGHT * rowDataList.size()) * ImgUtil::NUM_WIDTH * 10 * 17);
+	unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowDataList.size()) * _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER);
 
 
 
@@ -135,18 +135,18 @@
 	clock_t time_32 = clock();
 	std::cout << "数据准备-位置数据准备: threadid-" << std::this_thread::get_id() << " 耗时:" << time_32 - time_31 << endl;
 
-	unsigned char* zeroData = (unsigned char*)malloc(sizeof(unsigned char) * 5 * 8);
-	for (int r = 0;r < 8;r++) {
-		for (int c = 0;c < 5;c++)
+	unsigned char* zeroData = (unsigned char*)malloc(sizeof(unsigned char) * _NUMBER_L2_WIDTH * _NUMBER_L2_HEIGHT);
+	for (int r = 0;r < _NUMBER_L2_HEIGHT;r++) {
+		for (int c = 0;c < _NUMBER_L2_WIDTH;c++)
 		{
-			zeroData[r * 5 + c] = ImgUtil::NUMS[0].data.ptr<uchar>(r)[c];
+			zeroData[r * _NUMBER_L2_WIDTH + c] = ImgUtil::NUMS_LEVEL2[0].data.ptr<uchar>(r)[c];
 		}
 	}
 
 	clock_t time_33 = clock();
 	std::cout << "数据准备-0数据准备: threadid-" << std::this_thread::get_id() << " 耗时:" << time_33 - time_32 << endl;
 
-	openCLExcuter->splitNum(imgData, img.cols, img.rows, pos, 3 * rowDataList.size(), zeroData, totalNumberData);
+	openCLExcuter->splitNum(imgData, img.cols, img.rows, pos, 3 * rowDataList.size(), zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, totalNumberData);
 
 	free(pos);
 	free(zeroData);
@@ -165,9 +165,9 @@
 	std::cout << "数据准备-数字分隔完成: threadid-" << std::this_thread::get_id() << " 耗时:" << time_34 - time_33 << endl;
 
 	//准备模板数字
-	uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (ImgUtil::NUM_HEIGHT * rowDataList.size()) * ImgUtil::NUM_WIDTH * 10 * 17);
+	uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowDataList.size()) * _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER);
 
-	openCLExcuter->createNumberTemplates(rowDataList.size(), templateNums);
+	openCLExcuter->createNumberTemplates(rowDataList.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, ImgUtil::numsOneLevel_level2 ,templateNums);
 
 	//ImgUtil::createTemplateNumData(data.size());
 	clock_t time_4 = clock();
@@ -191,7 +191,7 @@
 	std::cout << "非数字数据识别完成: threadid-" << std::this_thread::get_id() << " 耗时:" << time_5 - time_4 << endl;
 
 	//数字识别
-	uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowDataList.size() * ImgUtil::NUM_HEIGHT, ImgUtil::NUM_WIDTH * 10 * 17);
+	uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowDataList.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * _NUMBER_L2_TOTAL_NUMBER, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER);
 	//释放内存
 	free(totalNumberData);
 	free(templateNums);
diff --git a/ConsoleApplication/THSActionUtil.cpp b/ConsoleApplication/THSActionUtil.cpp
index 27429a5..3506f84 100644
--- a/ConsoleApplication/THSActionUtil.cpp
+++ b/ConsoleApplication/THSActionUtil.cpp
@@ -1,18 +1,193 @@
 #include "THSActionUtil.h"
 #include "ImgDivider.h"
+#include "Win32Util.h"
+
+
+//获取副屏
+HWND getSecondWindow() {
+	list<HWND> wlist = Win32Util::searchWindow("同花顺(");
+	list<HWND>::iterator ele;
+	for (ele = wlist.begin();ele != wlist.end();ele++) {
+		HWND hwnd = *ele;
+		string str = Win32Util::getWindowName(hwnd);
+		if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos)
+		{
+			return hwnd;
+		}
+	}
+	return 0;
+}
+
 void THSActionUtil::openSecondScreen() {
 
+	list<HWND> wlist = Win32Util::searchWindow("同花顺(");
+
+	bool open = false;
+	HWND mainPage = 0;
+
+	list<HWND>::iterator ele;
+	for (ele = wlist.begin();ele != wlist.end();ele++) {
+		HWND hwnd = *ele;
+		string str = Win32Util::getWindowName(hwnd);
+		if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos)
+		{
+			cout << str << endl;
+			SetForegroundWindow(hwnd);
+			SetFocus(hwnd);
+			open = true;
+			break;
+		}
+
+		if (str.find("同花顺") != string::npos && str.find("热门股") != string::npos) {
+			cout << hwnd << endl;
+			//获取尺寸
+			RECT rc;
+			GetWindowRect(hwnd, &rc);
+			if (rc.right - rc.left > 200 && rc.bottom - rc.top > 200) {
+				mainPage = hwnd;
+			}
+		}
+
+	}
+
+	if (!open) {
+		Win32Util::focus(mainPage);
+		//查找主窗口的工具栏
+		HWND tool = FindWindowExA(mainPage, NULL, "AfxControlBar100s", NULL);
+
+		//获取第一个子窗口
+		tool = FindWindowExA(tool, NULL, NULL, NULL);
+		cout << "操作栏:" << tool << endl;
+		//打开副屏,多窗按钮ID为:0x00007AF9
+		HWND btn = GetDlgItem(tool, 0x00007AF9);
+		RECT rc;
+		GetWindowRect(btn, &rc);
+		//获取需要点击的位置
+		int x = rc.left + (rc.right - rc.left) / 3;
+		int y = rc.top + (rc.bottom - rc.top) / 3;
+		//点击多窗
+		Win32Util::click(x, y);
+		//点击副屏1 
+		Win32Util::click(x + 10, y + 21 * 7 + 5, 500);
+	}
 }
 //添加股票
-void THSActionUtil::addGP(std::string quickCode, std::string code) {
+void THSActionUtil::setGP(std::string quickCode, list<std::string> codeList) {
+	//打开副屏
+	HWND sw = getSecondWindow();
+	if (sw <= 0)
+	{
+		openSecondScreen();
+		Sleep(2000);
+		sw = getSecondWindow();
+	}
+	if (sw <= 0) {
+		throw("未打开副屏");
+	}
+
+	//打开板块
+	Win32Util::keyboardNum(quickCode);
+	Win32Util::keyboard(VK_RETURN, 200);
+	Sleep(1000);
+	//设置板块中的股票
+
+	//获取板块内容句柄
+
+	HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL);
+	cv::Mat img = CaptureUtil::capture(content);
+	if (img.cols <= 0 || img.rows <= 0) {
+		throw("板块截屏内容为空");
+	}
+
+	std::list<GPCodeArea>  areaList = recognitionGPArea(img);
+
+	std::list<string> addList;
+	std::list<GPCodeArea> delList;
+	std::list<GPCodeArea> resultList = recognitionNum(img, areaList);
+
+	for (std::list<GPCodeArea>::reverse_iterator ele= resultList.rbegin();ele != resultList.rend();++ele) {
+
+		bool contains = false;
+		std::list<string>::iterator e;
+		for (e = codeList.begin();e != codeList.end();e++) {
+			if (*e == (*ele).code) {
+				contains = true;
+				break;
+			}
+		}
+
+		if (!contains) {
+			delList.push_back(*ele);
+		}
+		else
+		{
+			codeList.remove((*ele).code);
+		}
+	
+	}
+	//-----先删除需要删除的
+	//获取内容板块坐标
+	RECT rect;
+	GetWindowRect(content, &rect);
+	
+
+	for (std::list<GPCodeArea>::iterator ele = delList.begin();ele != delList.end();++ele) {     
+		int x = rect.left;
+		int y = rect.top;
+		x += (*ele).startx+5;
+		y += (*ele).starty+5;
+	    //选中删除
+		Win32Util::click(x,y,50);
+		Win32Util::keyboard(VK_DELETE, 50);
+	}
+
+	//----增加
+	//截图,识别出增加按钮位置,点击增加,输入内容
 
 }
-//删除股票
-void  THSActionUtil::deleteGP(std::string quickCode, std::string code) {
 
+
+void add(string code) {
+	//打开副屏
+	HWND sw = getSecondWindow();
+	if (sw <= 0)
+	{
+		openSecondScreen();
+		Sleep(2000);
+		sw = getSecondWindow();
+	}
+	if (sw <= 0) {
+		throw("未打开副屏");
+	}
+
+	HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL);
+	cv::Mat img = CaptureUtil::capture(content);
+	if (img.cols <= 0 || img.rows <= 0) {
+		throw("板块截屏内容为空");
+	}
+	std::list<GPCodeArea>  areaList = recognitionGPArea(img);
+	for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();++ele) {
+		GPCodeArea codeArea = *ele;
+		if (codeArea.type == IMG_TYPE_ADD) {
+			RECT rc;
+			GetWindowRect(HWND(0x00161728), &rc);
+			int y = rc.top + codeArea.starty + (codeArea.endy - codeArea.starty) / 2;
+			int x = rc.left + codeArea.startx + (codeArea.endx - codeArea.startx) / 2;
+			Win32Util::click(x, y, 50);
+			//输入股票代码
+			Win32Util::keyboardNum(code,1000);
+			Win32Util::keyboard(VK_RETURN, 1500);
+			//关闭按钮
+			Sleep(100);
+			HWND close = FindWindowA(0, "添加股票");
+			SendMessage(close, WM_CLOSE, 0, 0);
+			break;
+		}
+	}
 }
+
 //识别股票代码
-std::list<GPCodeArea>  THSActionUtil::recognitionGPCode(cv::Mat img) {
+std::list<GPCodeArea>  THSActionUtil::recognitionGPArea(cv::Mat img) {
 	//获取title分隔线
 	int rows = img.rows;
 	int cols = img.cols;
@@ -70,7 +245,7 @@
 	std::list<int*> dataItemList;
 
 	for (int i = contentStartRow + 30;i < rows;i++) {
-		bool empty = ImgDivider::isRowEmpty(img, i, startC, startC+50, 1, 64)&& ImgDivider::isRowEmpty(img, i, startC +(endC-startC)/2-40, startC + (endC - startC) / 2 + 40, 1, 64);
+		bool empty = ImgDivider::isRowEmpty(img, i, startC, startC + 50, 1, 64) && ImgDivider::isRowEmpty(img, i, startC + (endC - startC) / 2 - 40, startC + (endC - startC) / 2 + 40, 1, 64);
 		if (empty) {
 			if (emptyStartRow < 0) {
 				emptyStartRow = i;
@@ -80,7 +255,7 @@
 				emptyEndRow = i;
 			}
 
-			if (emptyEndRow - emptyStartRow > 50&& dataItemList.size()>0) {
+			if (emptyEndRow - emptyStartRow > 50 && dataItemList.size() > 0) {
 				//没有数据了
 				break;
 			}
@@ -133,7 +308,7 @@
 		LogUtil::debug("%d %d %d %d\n", startRow, startCol, endRow, endCol);
 
 		//保存行数据
-		if (true) {
+		if (false) {
 			std::string path = "C:\\Users\\Administrator\\Desktop\\ocr\\split\\";
 			path.append(std::to_string(index)).append(".jpg");
 			imwrite(path, cv::Mat(img, cv::Rect(startCol, startRow, endCol - startCol + 1, endRow - startRow + 1)));
@@ -160,14 +335,14 @@
 				//3个及以上的空白数据才分列
 				if (emptyEnd - emptyStart >= 5 && dataEnd - dataStart > 0) {
 					int* dd = (int*)malloc(sizeof(int) * 4);
-					*dd = dataStart ;
+					*dd = dataStart;
 					*(dd + 1) = startRow;
-					*(dd + 2) = dataEnd ;
+					*(dd + 2) = dataEnd;
 					*(dd + 3) = endRow;
 					rowDataList.push_back(dd);
 					dataEnd = -1;
 					dataStart = -1;
-					if (rowDataList.size() >= 2){
+					if (rowDataList.size() >= 2) {
 						break;
 					}
 				}
@@ -188,9 +363,9 @@
 		//后面的数据没有足够的空白分隔
 		if (dataEnd - dataStart > 0) {
 			int* dd = (int*)malloc(sizeof(int) * 4);
-			*dd = dataStart ;
+			*dd = dataStart;
 			*(dd + 1) = startRow;
-			*(dd + 2) = dataEnd ;
+			*(dd + 2) = dataEnd;
 			*(dd + 3) = endRow;
 			rowDataList.push_back(dd);
 		}
@@ -198,15 +373,15 @@
 		int rowDataSize = rowDataList.size();
 		if (rowDataSize == 2) {
 
-			std::list<int*>::iterator ele= rowDataList.begin();
+			std::list<int*>::iterator ele = rowDataList.begin();
 			std::advance(ele, 1);
 
 			GPCodeArea area = GPCodeArea();
 			area.type = IMG_TYPE_GP;
 			area.startx = **ele;
-			area.starty = *(*ele+1);
-			area.endx = *(*ele+2);
-			area.endy = *(*ele+3);
+			area.starty = *(*ele + 1);
+			area.endx = *(*ele + 2);
+			area.endy = *(*ele + 3);
 			resultList.push_back(area);
 		}
 		else {
@@ -245,9 +420,38 @@
 				cc++;
 			}
 		}
-	
+
 	}
 
 	return resultList;
 
+}
+
+std::list<GPCodeArea>   THSActionUtil::recognitionNum(cv::Mat img, std::list<GPCodeArea> areaList) {
+
+	if (!recognitionManager) {
+		recognitionManager = new RecognitionManager();
+	}
+	//识别数字
+	std::list<GPCodeArea> codeList;
+
+	std::list<GPCodeArea>::iterator ele;
+
+	for (ele = areaList.begin();ele != areaList.end();ele++) {
+		GPCodeArea codeArea = *ele;
+		if (codeArea.type == IMG_TYPE_GP) {
+			cv::Mat nums = cv::Mat(img, cv::Rect(codeArea.startx, codeArea.starty, codeArea.endx - codeArea.startx + 1, codeArea.endy - codeArea.starty + 1));
+			std::list<cv::Mat> list2 = ImgUtil::splitNum(nums);
+			std::list<uchar> resultList = recognitionManager->recognitionGPCode(list2);
+			std::list<uchar>::iterator ele1;
+			string code = "";
+			for (ele1 = resultList.begin();ele1 != resultList.end();++ele1) {
+				code.append(to_string(*ele1));
+			}
+			codeArea.code = code;
+			codeList.push_back(codeArea);
+		}
+	}
+
+	return codeList;
 }
\ No newline at end of file
diff --git a/ConsoleApplication/THSActionUtil.h b/ConsoleApplication/THSActionUtil.h
index ffd818f..1343cda 100644
--- a/ConsoleApplication/THSActionUtil.h
+++ b/ConsoleApplication/THSActionUtil.h
@@ -6,6 +6,8 @@
 #include <opencv2/highgui.hpp>
 #include <opencv2/core.hpp>
 #include <opencv2/imgcodecs.hpp> 
+#include "CaptureUtil.h"
+#include "RecognitionManager.h"
 enum ImgType
 {
 	IMG_TYPE_GP,
@@ -23,18 +25,19 @@
 //同花顺事件
 class THSActionUtil
 {
+private:
+	static RecognitionManager *recognitionManager;
+
 public:
 	//打开同花顺的副屏幕
 	static void openSecondScreen();
-	//添加股票
-	static void addGP(std::string quickCode, std::string code);
-	//删除股票
-	static void  deleteGP(std::string quickCode, std::string code);
+	//设置股票
+	static void setGP(std::string quickCode, list<std::string> codeList);
 	//识别股票代码
-	static std::list<GPCodeArea>  recognitionGPCode(cv::Mat img);
+	static std::list<GPCodeArea>  recognitionGPArea(cv::Mat img);
 
-
-
+	//识别数字
+	static std::list<GPCodeArea>  recognitionNum(cv::Mat img,std::list<GPCodeArea> areaList);
 
 
 
diff --git a/ConsoleApplication/Win32Util.cpp b/ConsoleApplication/Win32Util.cpp
new file mode 100644
index 0000000..953dbe6
--- /dev/null
+++ b/ConsoleApplication/Win32Util.cpp
@@ -0,0 +1,105 @@
+#include "Win32Util.h"
+
+#include <thread>
+
+
+void clickRunner(int delay) // 函数名字可随意
+{
+	Sleep(delay);
+	mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
+	Sleep(10);
+	mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
+	Sleep(10);
+}
+
+void moveRunner(int x, int y,int delay) // 函数名字可随意
+{
+	Sleep(delay);
+	SetCursorPos(x, y);
+	Sleep(20);
+}
+
+
+void kbNumRunner(string nums, int delay) // 函数名字可随意
+{
+	Sleep(delay);
+	for (int i = 0;i < nums.length();i++)
+	{
+		keybd_event(nums.c_str()[i], 0, 0, 0);
+		keybd_event(nums.c_str()[i], 0, KEYEVENTF_KEYUP, 0);
+	}
+
+}
+
+void kbKeyRunner(int code, int delay) // 函数名字可随意
+{
+	Sleep(delay);
+	keybd_event(code, 0, 0, 0);
+	keybd_event(code, 0, KEYEVENTF_KEYUP, 0);
+}
+
+
+list<HWND> Win32Util::searchWindow(string name) {
+	auto hwnd = GetDesktopWindow();
+	HWND mainPage = HWND();
+	//获取桌面子窗口句柄
+	hwnd = GetWindow(hwnd, GW_CHILD);
+	list<HWND> list;
+	while (hwnd != NULL)
+	{
+		std::string str= getWindowName(hwnd);
+		if (str.find(name) != string::npos)
+		{
+			list.push_back(hwnd);
+		}
+		hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
+	}
+
+	return list;
+}
+
+
+ string Win32Util::getWindowName(HWND hwnd) {
+	 int length = GetWindowTextLength(hwnd);
+	 TCHAR getbuf[100];
+	 GetWindowText(hwnd, getbuf, length + 1);
+	 int iLen = WideCharToMultiByte(CP_ACP, 0, getbuf, -1, NULL, 0, NULL, NULL);   //首先计算TCHAR 长度。
+	 char* chRtn = new char[iLen * sizeof(char)];  //定义一个 TCHAR 长度大小的 CHAR 类型。
+	 WideCharToMultiByte(CP_ACP, 0, getbuf, -1, chRtn, iLen, NULL, NULL);  //将TCHAR 类型的数据转换为 CHAR 类型。
+	 std::string str(chRtn);
+	 return str;
+}
+
+
+void Win32Util::click(int delay) {
+	thread clickRunner(clickRunner,delay);
+	clickRunner.join();
+}
+
+void Win32Util::click(int x, int y, int delay) {
+	thread clickRunner(moveRunner, x, y,delay);
+	clickRunner.join();
+	click();
+}
+
+void Win32Util::mouseMove(int x, int y, int delay) {
+	thread clickRunner(moveRunner, x, y, delay);
+	clickRunner.join();
+}
+
+void Win32Util::focus(HWND hwnd) {
+	SetForegroundWindow(hwnd);
+	SetFocus(hwnd);
+}
+
+//键盘输入数字
+void Win32Util::keyboardNum(string num, int delay) {
+	thread runner(kbNumRunner, num, delay);
+	runner.join();
+}
+
+//键盘输入其他键
+void Win32Util::keyboard(int code, int delay) {
+	thread runner(kbKeyRunner, code, delay);
+	runner.join();
+}
\ No newline at end of file
diff --git a/ConsoleApplication/Win32Util.h b/ConsoleApplication/Win32Util.h
new file mode 100644
index 0000000..6930dad
--- /dev/null
+++ b/ConsoleApplication/Win32Util.h
@@ -0,0 +1,33 @@
+#pragma once
+#include <list>
+#include "Windows.h"
+#include <string>
+using namespace std;
+class Win32Util
+{
+public:
+	//按照名称搜索窗体
+	static list<HWND> searchWindow(string name);
+
+	//获取窗口名称
+	static string getWindowName(HWND hwnd);
+
+	//单击
+	static void click(int delay=0);
+
+	//单击指定位置
+	static void click(int x,int y, int delay=0);
+
+	//移动鼠标
+	static void mouseMove(int x, int y,int delay=0);
+
+	//获取焦点
+	static void focus(HWND hwnd);
+
+	//键盘输入数字
+	static void keyboardNum(string num, int delay=0);
+
+	//键盘输入其他键
+	static void keyboard(int code, int delay=0);
+};
+
diff --git a/ConsoleApplication/kernel.cl b/ConsoleApplication/kernel.cl
index 48785e5..28b9174 100644
--- a/ConsoleApplication/kernel.cl
+++ b/ConsoleApplication/kernel.cl
@@ -1,45 +1,45 @@
 
-#define ROWS 8 
-#define COLS 5 
-
-__kernel void createBuffer(__global const float* a_in,
-	__global const float* b_in,
-	__global float* result) {
-	int gid = get_global_id(0);
-	result[gid] = a_in[gid] * b_in[gid];
-}
-
-__kernel void test1(__global const unsigned char* a_in,
-	__global const unsigned char* b_in, int width,
+__kernel void recognition_numbers_1(__global const unsigned char* a_in,
+	__global const unsigned char* b_in, int width,int num_width,int num_height,int num_count,
 	__global unsigned char* result) {
 
 	int p = get_global_id(0);
-	int startIndex = p / width * width * 5 * 8 + p % 170 * 5;
+	int startIndex = p / width * width * num_width * num_height + p % (num_count*10) * num_width;
 	unsigned char t = 0;
-	for (int r = 0;r < 8;r++)
-		for (int c = 0;c < 5;c++) {
-			int index = startIndex + 5 * width * r + c;
-			t += (a_in[index] ^ b_in[index]);
+	for (int r = 0;r < num_height;r++)
+		for (int c = 0;c < num_width;c++) {
+			int index = startIndex + num_width * width * r + c;
+			t += abs(a_in[index] - b_in[index]);
+			if (p == 0) {
+				//printf("值:%d-%d \n", a_in[index], b_in[index]);
+			}
 		}
 	result[p] = t;
 }
 
 
-__kernel void test2(__global const unsigned char* a_in,
+__kernel void recognition_numbers_2(__global const unsigned char* a_in,
 	__global unsigned char* result) {
 
 	int index = get_global_id(0);
 	int startIndex = index * 10;
 	int endIndex = (index + 1) * 10;
 
+	//获取最小值
+	int min =255;
+	int minIndex = 11;
 
 	for (int i = startIndex;i < endIndex;i++)
 	{
-		if (a_in[i] == 0) {
-			result[index] = i - startIndex;
-			break;
+		if (a_in[i] < min) {
+			min = a_in[i];
+			minIndex = i;
 		}
 	}
+
+	//printf("最小值:%d - %d - %d \n", index, min, minIndex - startIndex);
+
+	result[index] = minIndex - startIndex;
 }
 
 int get_one_level_position(int width, int x, int y) {
@@ -49,13 +49,8 @@
 unsigned char get_binary_value(unsigned char v) {
 	return v >= 64 ? 1 : 0;
 }
-__kernel void test5(__global const unsigned char* img_in, __global const int* pos_in, __global const unsigned char* zero, int width,
-	__global unsigned char* result) {
 
-}
-
-
-__kernel void test4(__global const unsigned char* img_in, __global const int* pos_in, __global const unsigned char* zero, int width,
+__kernel void split_num(__global const unsigned char* img_in, __global const int* pos_in, __global const unsigned char* zero, int width,int num_width,int num_height,int num_count,
 	__global unsigned char* result) {
 
 	int index = get_global_id(0);
@@ -355,15 +350,15 @@
 	//开始填充数据
 	for (i = 0;i < maxNumberCount;i++) {
 
-		unsigned char numData[8][5];
+		unsigned char numData[100*100];
 
 		if (fresult[i * 2] == -1) {
 			//填充0
-			for (int r = 0;r < 8;r++) {
-				for (int c = 0;c < 5;c++) {
-					unsigned char value = get_binary_value(zero[r * 5 + c]);
+			for (int r = 0;r < num_height;r++) {
+				for (int c = 0;c < num_width;c++) {
+					unsigned char value = get_binary_value(zero[r * num_width + c]);
 					//设置输出坐标的值 
-					numData[r][c] = value;
+					numData[r* num_width+c] = value;
 				}
 			}
 
@@ -372,44 +367,44 @@
 			int _startx = fresult[i * 2];
 			int _endx = fresult[i * 2 + 1];
 			for (int r = starty;r <= endy;r++) {
-				for (int c = 0;c < 5;c++) {
+				for (int c = 0;c < num_width;c++) {
 					unsigned char value = 0;
 					if (_startx + c <= _endx) {
 						//填充空白0	
 						value = get_binary_value(img_in[get_one_level_position(width, _startx + c, r)]);
 						//设置输出坐标的值 
-						numData[r - starty][c] = value;
+						numData[(r - starty)* num_width+c] = value;
 					}
 					else {
-						numData[r - starty][c] = 0;
+						numData[(r - starty)* num_width+c] = 0;
 					}
 				}
 			}
 		}
 
-		int rowData = ROWS * COLS * 10 * 17;
+		int rowData = num_height * num_width * 10 * num_count;
 		int rowIndex = index / 3;
 		int index_0 = rowData * rowIndex;
 		//设置坐标值
 		int index_2 = 0;
 		if (index % 3 == 0) {
-			index_2 += COLS * 10 * i;
+			index_2 += num_width * 10 * i;
 		}
 		else if (index % 3 == 1) {
-			index_2 += (COLS * 10) * (6 + i);
+			index_2 += (num_width * 10) * (6 + i);
 		}
 		else {
-			index_2 += (COLS * 10) * (6 + 6 + i);
+			index_2 += (num_width * 10) * (6 + 6 + i);
 		}
 
 		for (int re = 0;re < 10;re++) {
-			int index_3 = re * COLS;
-			for (int r = 0;r < 8;r++) {
-				int index_1 = r * (COLS * 10 * 17);
-				for (int c = 0;c < COLS;c++) {
+			int index_3 = re * num_width;
+			for (int r = 0;r < num_height;r++) {
+				int index_1 = r * (num_width * 10 * num_count);
+				for (int c = 0;c < num_width;c++) {
 					int findex = index_0 + index_1 + index_2 + index_3 + c;
 					//printf("index:%d-findex:%d \n",index, findex);
-					result[findex] = numData[r][c];
+					result[findex] = numData[r* num_width+c];
 				}
 			}
 		}
@@ -422,30 +417,30 @@
 
 
 
-__kernel void createTemplateNumbers(__global unsigned char* numbers, int countPerLine,
+__kernel void createTemplateNumbers(__global unsigned char* numbers,int num_width,int num_height, int countPerLine,
 	__global unsigned char* result) {
 
 	int gid = get_global_id(0);
 	int LINE_NUMBER_COUNT = countPerLine;
 	int NUMBER_COUNT = 10;
 	//unsigned char* data = (unsigned char*)malloc(sizeof(unsigned char) * (ROWS * lines) *COLS * NUMBER_COUNT * LINE_NUMBER_COUNT);
-	int outLineDataCount = ROWS * COLS * NUMBER_COUNT * LINE_NUMBER_COUNT;
-	int inLineDataCount = COLS * NUMBER_COUNT * LINE_NUMBER_COUNT;
+	int outLineDataCount = num_height * num_width * NUMBER_COUNT * LINE_NUMBER_COUNT;
+	int inLineDataCount = num_width * NUMBER_COUNT * LINE_NUMBER_COUNT;
 
 	int outLineCount = outLineDataCount * gid;
 	for (int re = 0;re < LINE_NUMBER_COUNT;re++) {
 		for (int n = 0;n < NUMBER_COUNT;n++)
 		{
-			int index_num_0 = n * ROWS * COLS;
-			for (int r = 0;r < ROWS;r++) {
+			int index_num_0 = n * num_width * num_height;
+			for (int r = 0;r < num_height;r++) {
 				int intLineCount = inLineDataCount * r;
 
-				for (int c = 0;c < COLS;c++) {
-					int index_num = index_num_0 + r * COLS + c;
+				for (int c = 0;c < num_width;c++) {
+					int index_num = index_num_0 + r * num_width + c;
 					unsigned char value = numbers[index_num];
 					int index = outLineCount;
 					index += intLineCount;
-					int x = re * NUMBER_COUNT * COLS + n * COLS + c;
+					int x = re * NUMBER_COUNT * num_width + n * num_width + c;
 					index += x;
 					result[index] = get_binary_value(value);
 				}
diff --git a/ConsoleApplication/main.cpp b/ConsoleApplication/main.cpp
index f81986d..58a73d5 100644
--- a/ConsoleApplication/main.cpp
+++ b/ConsoleApplication/main.cpp
@@ -20,7 +20,7 @@
 		//鍚岃姳椤�(v9.10.50) - 娣卞湷Level-2鍒嗘椂璧板娍
 		//鍚岃姳椤�(v9.10.50) - pppp
 		list<TradeData>  map = creenDataCapture->captureLevel2TradeData(cv::imread( "C:\\Users\\Administrator\\Desktop\\ocr\\demo\\0_388.jpg"),p);
-		//break;
+		break;
 	}
 
 	return 0L;
@@ -91,13 +91,35 @@
 */
 
 int main() {
-
-	
+	//THSActionUtil::openSecondScreen();
+	RecognitionUtil::init();
+	CaptureUtil::init("鍚岃姳椤�(v9.10.50) - 鐑棬鑲�888");// 鐑棬鑲�888
+	ImgUtil::init();
 	ths();
+
+	/*
+	RecognitionManager* recognitionManager = new RecognitionManager();
+	
+	for (int i = 1;i < 14;i++)
+	{
+		string path = "C:\\Users\\Administrator\\Desktop\\ocr\\split\\";
+		path.append(to_string(i)).append("_1.jpg");
+		list<cv::Mat> list1 = ImgUtil::splitNum(cv::imread(path.c_str(), cv::IMREAD_GRAYSCALE));
+		list<uchar> resultList= recognitionManager->recognitionGPCode(list1);
+		list<uchar>::iterator ele;
+		for (ele = resultList.begin();ele != resultList.end();++ele) {
+			printf("%d",*ele);
+		}
+		printf("\n");
+	}
+	*/
+
+
 	cv::waitKey(0);
 	cv::destroyAllWindows();
 	return 0;
-	/*
+		
+	
 	
 	string path = "C:\\Users\\Administrator\\Desktop\\ocr\\temp.jpg";
 	
@@ -105,7 +127,7 @@
 	cv::Mat img = CaptureUtil::capture(HWND(0x00010CA6));
 	cv::imwrite(path, img);
 	
-	*/
+
 
 	//return 0;
 	
@@ -113,7 +135,7 @@
 	RecognitionUtil::init();
 	CaptureUtil::init("鍚岃姳椤�(v9.10.50) - 鐑棬鑲�888");// 鐑棬鑲�888
 	ImgUtil::init();
-	for (int i = 0;i < 8;i++)
+	for (int i = 0;i < 1;i++)
 	{
 		int* params =(int*) malloc(sizeof(int));
 		*params = i;
@@ -205,16 +227,32 @@
 
 void ths() {
 	//00421530
-	cv::Mat img = CaptureUtil::capture(HWND(0x00161728));
+	cv::Mat img = CaptureUtil::capture(HWND(0x00040CAE));
 	img=ImgUtil::grayImage(img);
-	cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\bk.jpg",img);
-	std::list<GPCodeArea> list=  THSActionUtil::recognitionGPCode(img);
+	//cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\bk.jpg",img);
+	std::list<GPCodeArea> list=  THSActionUtil::recognitionGPArea(img);
 	std::list<GPCodeArea>::iterator ele;
+	RecognitionManager* recognitionManager = new RecognitionManager();
+	int index = 0;
 	for (ele = list.begin();ele != list.end();ele++) {
+		index++;
+		GPCodeArea codeArea = *ele;
+		if (codeArea.type == IMG_TYPE_GP) {
+			cv::Mat nums = cv::Mat(img,cv::Rect( codeArea.startx, codeArea.starty, codeArea.endx- codeArea.startx+1, codeArea.endy- codeArea.starty+1));
+			std::list<cv::Mat> list2 = ImgUtil::splitNum(nums);
+			std::list<uchar> resultList = recognitionManager->recognitionGPCode(list2);
+			std::list<uchar>::iterator ele1;
+			printf("%d-", index);
+			for (ele1 = resultList.begin();ele1 != resultList.end();++ele1) {
+				printf("%d", *ele1);
+			}
+			printf("\n");
+		}
+
+		continue;
 
 		SetForegroundWindow(HWND(0x00161728));
 		SetFocus(HWND(0x00161728));
-		GPCodeArea codeArea = *ele;
 		if (codeArea.type == IMG_TYPE_ADD) {
 			RECT rc;
 			GetWindowRect(HWND(0x00161728), &rc);

--
Gitblit v1.8.0