| | |
| | | <ClCompile Include="ScreenDataCapture.cpp" /> |
| | | <ClCompile Include="OpenclTest.cpp" /> |
| | | <ClCompile Include="THSActionUtil.cpp" /> |
| | | <ClCompile Include="Win32Util.cpp" /> |
| | | <ClCompile Include="win32_screen_shots.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | |
| | | <ClInclude Include="resource.h" /> |
| | | <ClInclude Include="ScreenDataCapture.h" /> |
| | | <ClInclude Include="THSActionUtil.h" /> |
| | | <ClInclude Include="Win32Util.h" /> |
| | | <ClInclude Include="win32_screen_shots.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | |
| | | <ClCompile Include="THSActionUtil.cpp"> |
| | | <Filter>源文件</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="Win32Util.cpp"> |
| | | <Filter>源文件</Filter> |
| | | </ClCompile> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="resource.h"> |
| | |
| | | <ClInclude Include="THSActionUtil.h"> |
| | | <Filter>头文件</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="Win32Util.h"> |
| | | <Filter>头文件</Filter> |
| | | </ClInclude> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="ConsoleApplication.rc"> |
| | |
| | | #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) { |
| | |
| | | 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; |
| | | |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | |
| | | 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) { |
| | |
| | | |
| | | |
| | | //将所有的数字格式化为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次,用于矩阵相减 |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | |
| | | |
| | | #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: |
| | |
| | | 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: |
| | | |
| | |
| | | |
| | | //构建模板数据,用于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); |
| | | }; |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | |
| | | 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"); |
| | | } |
| | |
| | | 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"); |
| | | } |
| | |
| | | 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"); |
| | | } |
| | |
| | | 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++) { |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | |
| | | |
| | | //创建缓存对象 |
| | |
| | | } |
| | | |
| | | 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"); |
| | | } |
| | |
| | | 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"); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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"); |
| | | } |
| | |
| | | } |
| | | |
| | | |
| | | 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"); |
| | |
| | | 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, |
| | |
| | | uchar* createTemplateData(int line); |
| | | |
| | | int LINE_NUMBER = 10; |
| | | int RE = 17; |
| | | int RE = _NUMBER_L2_TOTAL_NUMBER; |
| | | |
| | | |
| | | |
| | |
| | | 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(); |
| | | |
| | |
| | | } |
| | | |
| | | 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++) |
| | |
| | | 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; |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | |
| | | #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++) { |
| | |
| | | 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; |
| | | } |
| | |
| | | |
| | | #include "LogUtil.h" |
| | | #include "error.h" |
| | | #include "OpenCLExcuter.h" |
| | | |
| | | using namespace std; |
| | | struct TradeData |
| | |
| | | |
| | | class RecognitionManager |
| | | { |
| | | |
| | | private: |
| | | OpenCLExcuter *openCLExcuter; |
| | | |
| | | public: |
| | | |
| | | RecognitionManager(); |
| | | ~RecognitionManager(); |
| | | //识别某一行数据 |
| | | TradeData recognition(cv::Mat img, int* rowData); |
| | | //识别所有的数据 |
| | |
| | | //识别价格 |
| | | string recognitionPrice(std::string path); |
| | | string recognitionPrice(cv::Mat img); |
| | | |
| | | //数字识别 |
| | | list<uchar> recognitionGPCode(list<cv::Mat> imgList); |
| | | }; |
| | | |
| | | |
| | |
| | | |
| | | //图像识别的数字准备 |
| | | |
| | | 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); |
| | | |
| | | |
| | | |
| | |
| | | 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); |
| | |
| | | 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(); |
| | |
| | | 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); |
| | |
| | | #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; |
| | |
| | | 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; |
| | |
| | | emptyEndRow = i; |
| | | } |
| | | |
| | | if (emptyEndRow - emptyStartRow > 50&& dataItemList.size()>0) { |
| | | if (emptyEndRow - emptyStartRow > 50 && dataItemList.size() > 0) { |
| | | //没有数据了 |
| | | break; |
| | | } |
| | |
| | | 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))); |
| | |
| | | //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; |
| | | } |
| | | } |
| | |
| | | //后面的数据没有足够的空白分隔 |
| | | 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); |
| | | } |
| | |
| | | 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 { |
| | |
| | | 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; |
| | | } |
| | |
| | | #include <opencv2/highgui.hpp> |
| | | #include <opencv2/core.hpp> |
| | | #include <opencv2/imgcodecs.hpp> |
| | | #include "CaptureUtil.h" |
| | | #include "RecognitionManager.h" |
| | | enum ImgType |
| | | { |
| | | IMG_TYPE_GP, |
| | |
| | | //同花顺事件 |
| | | 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); |
| | | |
| | | |
| | | |
New file |
| | |
| | | #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(); |
| | | } |
New file |
| | |
| | | #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); |
| | | }; |
| | | |
| | |
| | | |
| | | #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) { |
| | |
| | | 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); |
| | |
| | | //开始填充数据 |
| | | 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; |
| | | } |
| | | } |
| | | |
| | |
| | | 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]; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | __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); |
| | | } |
| | |
| | | //同花顺(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; |
| | |
| | | */ |
| | | |
| | | 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"; |
| | | |
| | |
| | | cv::Mat img = CaptureUtil::capture(HWND(0x00010CA6)); |
| | | cv::imwrite(path, img); |
| | | |
| | | */ |
| | | |
| | | |
| | | //return 0; |
| | | |
| | |
| | | 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; |
| | |
| | | |
| | | 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); |