admin
2022-06-27 eda1a611bc4afcf1c36a6c728f432aec1f688e1b
'GP代码识别'
14个文件已修改
2个文件已添加
900 ■■■■ 已修改文件
ConsoleApplication/ConsoleApplication.vcxproj 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ConsoleApplication.vcxproj.filters 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ImgUtil.cpp 137 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ImgUtil.h 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/OpenCLExcuter.cpp 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/OpenCLExcuter.h 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/OpenclTest.cpp 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/RecognitionManager.cpp 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/RecognitionManager.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ScreenDataCapture.cpp 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.cpp 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/Win32Util.cpp 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/Win32Util.h 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/kernel.cl 99 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/main.cpp 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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">
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;
                    }
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);
};
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");
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,
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;
                    }
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;
}
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);
};
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);
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;
}
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);
ConsoleApplication/Win32Util.cpp
New file
@@ -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();
}
ConsoleApplication/Win32Util.h
New file
@@ -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);
};
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);
                }
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);