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