admin
2022-07-12 c108e5ba42168841311b74034d89c31556d628c4
'完善'
2 文件已重命名
21个文件已修改
4个文件已添加
2277 ■■■■■ 已修改文件
ConsoleApplication/CaptureUtil.cpp 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/CaptureUtil.h 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ConsoleApplication.vcxproj 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/ConsoleApplication.vcxproj.filters 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.cpp 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/L2DataCapture.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/LimitUpCapture.cpp 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/LimitUpCapture.h 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/OpenCLExcuter.cpp 365 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/OpenCLExcuter.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/RecognitionManager.cpp 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.cpp 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/THSActionUtil.h 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeQueueCapture.cpp 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/TradeQueueCapture.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/Win32Util.cpp 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/kernel.cl 671 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/main.cpp 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/ExcelUtil.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/JsonUtil.h 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/app.aps 补丁 | 查看 | 原始文档 | blame | 历史
app/app.rc 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.cpp 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/appDlg.h 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/codesDataDlog.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/level2DataDlg.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/resource.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ConsoleApplication/CaptureUtil.cpp
@@ -1,6 +1,7 @@
#include "CaptureUtil.h"
HWND CaptureUtil::level2Frames[8];
HWND CaptureUtil::tradeQueueFrames[8];
std::list<FrameInfo> CaptureUtil::tempFrames;
BOOL CALLBACK CaptureUtil::EnumChildProc(HWND hwndChild, LPARAM lParam) {
@@ -36,19 +37,71 @@
void CaptureUtil::init(HWND l2win) {
    tempFrames.clear();
    HWND root = l2win;
    RECT rootRect;
    GetWindowRect(root, &rootRect);
    int rootHeight = (rootRect.bottom- rootRect.top);
    root = FindWindowEx(root, NULL, TEXT("AfxFrameOrView100s"), NULL);
    EnumChildWindows(root, EnumChildProc, NULL);
    std::list<FrameInfo> tempL2;
    std::list<FrameInfo> tempTrade;
    //赋值
    std::list<FrameInfo>::iterator ele;
    int index = 0;
    for (ele = tempFrames.begin();ele != tempFrames.end();ele++) {
        if (index > 7) {
            break;
        FrameInfo frameInfo = *ele;
        if (frameInfo.position.bottom - frameInfo.position.top > rootHeight/2) {
            tempL2.push_back(frameInfo);
        }
        else {
            //查找第一个子元素
            HWND temp =  FindWindowEx(frameInfo.frame, NULL,NULL, NULL);
            RECT tempRect;
            GetWindowRect(temp, &tempRect);
            while (!IsWindowVisible(temp) || tempRect.right- tempRect.left<100) {
                temp= FindWindowEx(frameInfo.frame, temp, NULL, NULL);
                GetWindowRect(temp, &tempRect);
            }
            HWND tempc = FindWindowEx(temp, NULL, NULL, NULL);
            tempc = FindWindowEx(temp, tempc, NULL, NULL);
            tempc = FindWindowEx(tempc, NULL, TEXT("SysListView32"), NULL);
            GetWindowRect(tempc, &tempRect);
            FrameInfo tempFrame = FrameInfo();
            tempFrame.frame = tempc;
            tempFrame.position = tempRect;
            tempTrade.push_back(tempFrame);
        }
    }
    //排序
    tempL2.sort();
    tempTrade.sort();
    int index = 0;
    for (ele = tempL2.begin();ele != tempL2.end();ele++) {
        level2Frames[index++] = (*ele).frame;
    }
    index = 0;
    for (ele = tempTrade.begin();ele != tempTrade.end();ele++) {
        tradeQueueFrames[index++] = (*ele).frame;
    }
    //保存图片
    for (int i = 0;i < 8;i++) {
    cv::Mat img= ImgUtil::grayImage(capture(tradeQueueFrames[i]));
    string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade_queue\\";
    path.append(to_string(i)).append(".jpg");
    cv::imwrite(path,img);
    }
}
HWND CaptureUtil::getHWND(int index) {
    return level2Frames[index];
ConsoleApplication/CaptureUtil.h
@@ -12,12 +12,17 @@
    HWND frame;
    RECT position;
    bool operator < (FrameInfo& b) {
        return position.left < b.position.left;
    }
};
class CaptureUtil
{
private:
    static std::list<FrameInfo> tempFrames;
    static HWND level2Frames[8];
    static HWND tradeQueueFrames[8];
    static BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam);
    static HWND getHWND(int index);
ConsoleApplication/ConsoleApplication.vcxproj
@@ -41,7 +41,7 @@
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>StaticLibrary</ConfigurationType>
    <ConfigurationType>Application</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v142</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
@@ -144,6 +144,7 @@
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="CaptureUtil.cpp" />
    <ClCompile Include="LimitUpCapture.cpp" />
    <ClCompile Include="main.cpp" />
    <ClCompile Include="ImgDivider.cpp" />
    <ClCompile Include="ImgUtil.cpp" />
@@ -151,9 +152,10 @@
    <ClCompile Include="OpenCLExcuter.cpp" />
    <ClCompile Include="RecognitionManager.cpp" />
    <ClCompile Include="RecognitionUtil.cpp" />
    <ClCompile Include="ScreenDataCapture.cpp" />
    <ClCompile Include="L2DataCapture.cpp" />
    <ClCompile Include="OpenclTest.cpp" />
    <ClCompile Include="THSActionUtil.cpp" />
    <ClCompile Include="TradeQueueCapture.cpp" />
    <ClCompile Include="Win32Util.cpp" />
    <ClCompile Include="win32_screen_shots.cpp" />
  </ItemGroup>
@@ -162,13 +164,15 @@
    <ClInclude Include="error.h" />
    <ClInclude Include="ImgDivider.h" />
    <ClInclude Include="ImgUtil.h" />
    <ClInclude Include="LimitUpCapture.h" />
    <ClInclude Include="LogUtil.h" />
    <ClInclude Include="OpenCLExcuter.h" />
    <ClInclude Include="RecognitionManager.h" />
    <ClInclude Include="RecognitionUtil.h" />
    <ClInclude Include="resource.h" />
    <ClInclude Include="ScreenDataCapture.h" />
    <ClInclude Include="L2DataCapture.h" />
    <ClInclude Include="THSActionUtil.h" />
    <ClInclude Include="TradeQueueCapture.h" />
    <ClInclude Include="Win32Util.h" />
    <ClInclude Include="win32_screen_shots.h" />
  </ItemGroup>
ConsoleApplication/ConsoleApplication.vcxproj.filters
@@ -30,9 +30,6 @@
    <ClCompile Include="LogUtil.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="ScreenDataCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="main.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
@@ -52,6 +49,15 @@
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="Win32Util.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="L2DataCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="LimitUpCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
    <ClCompile Include="TradeQueueCapture.cpp">
      <Filter>源文件</Filter>
    </ClCompile>
  </ItemGroup>
@@ -77,9 +83,6 @@
    <ClInclude Include="LogUtil.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="ScreenDataCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="error.h">
      <Filter>头文件</Filter>
    </ClInclude>
@@ -95,6 +98,15 @@
    <ClInclude Include="Win32Util.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="L2DataCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="LimitUpCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
    <ClInclude Include="TradeQueueCapture.h">
      <Filter>头文件</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="ConsoleApplication.rc">
ConsoleApplication/L2DataCapture.cpp
File was renamed from ConsoleApplication/ScreenDataCapture.cpp
@@ -1,23 +1,23 @@
#include "ScreenDataCapture.h"
#include "L2DataCapture.h"
#include <thread>
#include<fstream>
#include "THSActionUtil.h"
#include <thread>
bool ScreenDataCapture::inited;
 OpenCLExcuter* ScreenDataCapture::openCLExcuter[THS_FRAME_COUNT];
bool L2DataCapture::inited;
 OpenCLExcuter* L2DataCapture::openCLExcuter[THS_FRAME_COUNT];
//是否正在执行
 bool ScreenDataCapture::running;
 bool ScreenDataCapture::runnings[THS_FRAME_COUNT];
 clock_t ScreenDataCapture::latest_running_times[THS_FRAME_COUNT];
 bool L2DataCapture::running;
 bool L2DataCapture::runnings[THS_FRAME_COUNT];
 clock_t L2DataCapture::latest_running_times[THS_FRAME_COUNT];
 CallbackFun ScreenDataCapture::data_callback;
 CallbackFun L2DataCapture::data_callback;
 string ScreenDataCapture::gpCodes[THS_FRAME_COUNT];
 string L2DataCapture::gpCodes[THS_FRAME_COUNT];
 void* ScreenDataCapture::context;
 void* L2DataCapture::context;
//运行
void ScreenDataCapture::_run(int index)
void L2DataCapture::_run(int index)
{
    while (true) {
        if (running && runnings[index]&& gpCodes[index].length()>0) {
@@ -36,7 +36,7 @@
    }
}
void ScreenDataCapture::setGPCode(int index, string code) {
void L2DataCapture::setGPCode(int index, string code) {
    int length = sizeof(gpCodes) / sizeof(gpCodes[0]);
    if (length <= index) {
        return;
@@ -45,16 +45,16 @@
    gpCodes[index] = code;
}
string ScreenDataCapture::getGPCode(int index) {
string L2DataCapture::getGPCode(int index) {
    return    gpCodes[index];
}
static string getGPCode(int index);
ScreenDataCapture::ScreenDataCapture() {
L2DataCapture::L2DataCapture() {
}
void ScreenDataCapture::refreshHWND() {
void L2DataCapture::refreshHWND() {
    HWND win = THSActionUtil::getL2Win();
    if (win <= 0) {
        throw string("未获取到同花顺LEVEL2盘口");
@@ -62,7 +62,7 @@
    CaptureUtil::init(win);
}
void ScreenDataCapture::init(CallbackFun callback, void* contex) {
void L2DataCapture::init(CallbackFun callback, void* contex) {
    inited = true;
    data_callback = callback;
    context = contex;
@@ -84,51 +84,51 @@
    int length = sizeof(runnings) / sizeof(runnings[0]);
    for (int i = 0;i < length;i++) {
        runnings[i] = false;
        thread rt(&(ScreenDataCapture::_run),i);
        thread rt(&(L2DataCapture::_run),i);
        rt.detach();
    }
}
bool ScreenDataCapture::isRunning() {
bool L2DataCapture::isRunning() {
    return running;
}
void ScreenDataCapture::start(int index) {
void L2DataCapture::start(int index) {
    runnings[index] = true;
}
//结束
void ScreenDataCapture::stop(int index) {
void L2DataCapture::stop(int index) {
    runnings[index] = false;
}
//全部开始
void ScreenDataCapture::start() {
void L2DataCapture::start() {
    running = true;
}
//全部结束
void ScreenDataCapture::stop() {
void L2DataCapture::stop() {
    running = false;
}
void ScreenDataCapture::startAll() {
void L2DataCapture::startAll() {
    int length = sizeof(runnings) / sizeof(runnings[0]);
    for (int i = 0;i < length;i++) {
        runnings[i] = true;
    }
}
void ScreenDataCapture::stopAll() {
void L2DataCapture::stopAll() {
    int length = sizeof(runnings) / sizeof(runnings[0]);
    for (int i = 0;i < length;i++) {
        runnings[i] = false;
    }
}
bool ScreenDataCapture::isInited() {
bool L2DataCapture::isInited() {
    return inited;
}
list<TradeData>  ScreenDataCapture::captureLevel2TradeData(cv::Mat oimg, int identify) {
list<TradeData>  L2DataCapture::captureLevel2TradeData(cv::Mat oimg, int identify) {
    if (oimg.rows == 0 || oimg.cols == 0) {
        throw ERROR_CODE_CAPTURE_FAIL;
    }
@@ -311,9 +311,9 @@
    std::cout << "数据准备-0数据准备: threadid-" << std::this_thread::get_id() << " 耗时:" << time_33 - time_32 << endl;
    openCLExcuter[identify]->splitL2Num(imgData, img.cols, img.rows, pos, 4 * rowDataList.size(), zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, _NUMBER_L2_TOTAL_NUMBER, totalNumberData);
    free(pos);
    free(zeroData);
    free(pos);
    /*
@@ -476,7 +476,7 @@
}
//捕获level2的盘口数据
list<TradeData> ScreenDataCapture::captureLevel2TradeData(HWND hwnd, int index) throw(int) {
list<TradeData> L2DataCapture::captureLevel2TradeData(HWND hwnd, int index) throw(int) {
    cv::Mat img = CaptureUtil::capture(hwnd);
    /*
ConsoleApplication/L2DataCapture.h
File was renamed from ConsoleApplication/ScreenDataCapture.h
@@ -8,7 +8,7 @@
typedef void (*CallbackFun)(int index, string code, list<TradeData> dataList, void* contex);
class ScreenDataCapture
class L2DataCapture
{
private:
    static OpenCLExcuter* openCLExcuter[THS_FRAME_COUNT];
@@ -29,7 +29,7 @@
public:
    ScreenDataCapture();
    L2DataCapture();
    //初始化
    void init(CallbackFun callback, void* context);
ConsoleApplication/LimitUpCapture.cpp
New file
@@ -0,0 +1,274 @@
#include "LimitUpCapture.h"
#include "THSActionUtil.h"
#include <set>
OpenCLExcuter* LimitUpCapture::openCLExcuter;
bool LimitUpCapture::inited;
//是否正在执行
bool LimitUpCapture::running;
CallbackFun_Limit_Up LimitUpCapture::data_callback;
void* LimitUpCapture::context;
HWND LimitUpCapture::win;
RecognitionManager* LimitUpCapture::recognitionManager;
void LimitUpCapture::_run() {
    while (true) {
        if (running && inited) {
            clock_t start = clock();
            list<LimitUpData> codes = captureLimitUpCodes();
            cout << "耗时:" << clock() - start << "  数量:" << codes.size() << endl;
            data_callback(codes, context);
            codes.clear();
            Sleep(3000);
        }
    }
}
void LimitUpCapture::init(CallbackFun_Limit_Up callback, void* contex) {
    data_callback = callback;
    context = contex;
    running = false;
    recognitionManager = new RecognitionManager();
    openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
    thread rt(&(LimitUpCapture::_run));
    rt.detach();
    inited = true;
    refreshHWND();
}
void LimitUpCapture::refreshHWND() {
    HWND hwnd = THSActionUtil::getThirdWindow();
    if (hwnd <= 0)
        throw string("同花顺副屏2未打开");
    HWND content = FindWindowExA(hwnd, NULL, "AfxFrameOrView100s", NULL);
    if (content <= 0)
        throw string("未获取到内容窗口句柄");
    win = content;
}
bool LimitUpCapture::isRunning() {
    return running;
}
list<LimitUpData> LimitUpCapture::captureLimitUpCodes(cv::Mat oimg) {
    cv::Mat grayImg = cv::Mat::zeros(oimg.rows, oimg.cols, CV_8UC1);//ImgUtil::grayImage(oimg);
    uchar* imgData = (uchar*)malloc(sizeof(uchar) * oimg.rows * oimg.cols);
    if (oimg.channels() == 3)
    {
        openCLExcuter->rgb2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
    }
    else {
        openCLExcuter->rgba2Gray(oimg.data, oimg.cols, oimg.rows, imgData);
    }
    grayImg.data = imgData;
    list<int*> rowData = THSActionUtil::splitPlateRowArea(grayImg);
    //每行的元素个数
    int ele_count_per_line = 4;
    int* splitResult = (int*)malloc(sizeof(int) * 4 * 4 * rowData.size());
    int* rowIndex = (int*)malloc(sizeof(int) * 4 * rowData.size());
    int count = 0;
    for (std::list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
        string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
        path.append(to_string(count)).append(".jpg");
        //cv::imwrite(path, cv::Mat(grayImg, cv::Rect((*ele)[0], (*ele)[1], (*ele)[2] - (*ele)[0] + 1, (*ele)[3] - (*ele)[1] + 1)));
        rowIndex[4 * count + 0] = (*ele)[0];
        rowIndex[4 * count + 1] = (*ele)[1];
        rowIndex[4 * count + 2] = (*ele)[2];
        rowIndex[4 * count + 3] = (*ele)[3];
        free(*ele);
        count++;
    }
    int line_number_count = 4 * 6;
    openCLExcuter->splitLimitUpRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, splitResult);
    /*
    *测试
    for (int i = 0;i < rowData.size();i++) {
        for (int j = 0;j < line_number_count;j++) {
            int sx = splitResult[(line_number_count * i + j) * 4 + 0];
            int sy = splitResult[(line_number_count * i + j) * 4 + 1];
            int ex = splitResult[(line_number_count * i + j) * 4 + 2];
            int ey = splitResult[(line_number_count * i + j) * 4 + 3];
            string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
            path.append(to_string(i)).append("_").append(to_string(j)).append(".jpg");
            //cv::imwrite(path, cv::Mat(grayImg, cv::Rect(sx, sy, ex - sx + 1, ey - sy + 1)));
        }
    }
    */
    int start = 4 * 4 * 1 + 4 * 1;
    string path = "C:\\Users\\Administrator\\Desktop\\ocr\\limit_up\\";
    path.append(to_string(start)).append(".jpg");
    //cv::imwrite(path, cv::Mat(grayImg,cv::Rect(splitResult[start], splitResult[start+1], splitResult[start+2]- splitResult[start]+1, splitResult[start+3]- splitResult[start+1]+1)));
    //cv::imwrite(path, cv::Mat(grayImg, cv::Rect(447, 102, 454-447+1,111-102+1 )));
    //分割数字
    unsigned char* zeroData = (unsigned char*)malloc(sizeof(unsigned char) * _NUMBER_GP_CODE_WIDTH * _NUMBER_GP_CODE_HEIGHT);
    for (int r = 0;r < _NUMBER_GP_CODE_HEIGHT;r++) {
        for (int c = 0;c < _NUMBER_GP_CODE_WIDTH;c++)
        {
            zeroData[r * _NUMBER_GP_CODE_WIDTH + c] = ImgUtil::NUMS_GP_CODE[0].data.ptr<uchar>(r)[c];
        }
    }
    unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowData.size()) * _NUMBER_GP_CODE_WIDTH * 10 * line_number_count);
    openCLExcuter->splitPlateNum(grayImg.data, grayImg.cols, grayImg.rows, splitResult, 4 * rowData.size(), zeroData, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, line_number_count, totalNumberData);
    //识别数字
    uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowData.size()) * _NUMBER_GP_CODE_WIDTH * 10 * line_number_count);
    openCLExcuter->createNumberTemplates(rowData.size(), _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, line_number_count, ImgUtil::numsOneLevel_gpcode, templateNums);
    uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_GP_CODE_HEIGHT, _NUMBER_GP_CODE_WIDTH * 10 * line_number_count, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, line_number_count);
    list<LimitUpData> dataList;
    for (int i = 0;i < rowData.size();i++) {
        LimitUpData limitUpData = LimitUpData();
        string code = "";
        for (int j = 0;j < 6;j++)
        {
            code.append(to_string(numberResult[i][j]));
        }
        string time = "";
        for (int j = 0;j < 6;j++)
        {
            if (j == 2 || j == 4) {
                time.append(":");
            }
            time.append(to_string(numberResult[i][6 + j]));
        }
        string price = "";
        for (int j = 0;j < 6;j++)
        {
            if (j == 4) {
                price.append(".");
            }
            price.append(to_string(numberResult[i][6 * 2 + j]));
        }
        string money = "";
        for (int j = 0;j < 6;j++)
        {
            if (j == 4) {
                money.append(".");
            }
            money.append(to_string(numberResult[i][6 * 3 + j]));
        }
        limitUpData.index = i;
        limitUpData.code = code;
        limitUpData.time = time;
        limitUpData.price = price;
        limitUpData.limitMoney = money;
        if (limitUpData.time != "00:00:00" && limitUpData.price != "0000.00" && limitUpData.limitMoney != "0000.00") {
            dataList.push_back(limitUpData);
        }
        free(numberResult[i]);
    }
    free(numberResult);
    int* unitData = (int*)malloc(sizeof(int) * 4 * dataList.size());
    //识别金额单位
    int index = 0;
    for (list<LimitUpData>::iterator ele = dataList.begin();ele != dataList.end();ele++) {
        unitData[index * 4 + 0] = splitResult[(*ele).index * 4 * 4 + 4 * 3 + 0];
        unitData[index * 4 + 1] = splitResult[(*ele).index * 4 * 4 + 4 * 3 + 1];
        unitData[index * 4 + 2] = splitResult[(*ele).index * 4 * 4 + 4 * 3 + 2];
        unitData[index * 4 + 3] = splitResult[(*ele).index * 4 * 4 + 4 * 3 + 3];
        index++;
    }
    int* unitResult = (int*)malloc(sizeof(int) * dataList.size());
    openCLExcuter->recognitionPlateMoneyUnit(grayImg.data, grayImg.cols, grayImg.rows, unitData, 1, dataList.size(), unitResult);
    index = 0;
    for (list<LimitUpData>::iterator ele = dataList.begin();ele != dataList.end();ele++) {
        switch (unitResult[index])
        {
        case 0:
            (*ele).limitMoneyUnit = MONEY_UNIT_Y;
            break;
        case 1:
            (*ele).limitMoneyUnit = MONEY_UNIT_W;
            break;
        default:
            break;
        }
        index++;
    }
    free(rowIndex);
    free(splitResult);
    free(zeroData);
    free(templateNums);
    free(unitData);
    free(unitResult);
    free(imgData);
    grayImg.release();
    return dataList;
}
list<LimitUpData> LimitUpCapture::captureLimitUpCodes() {
    RECT wrect;
    GetWindowRect(win, &wrect);
    list<LimitUpData> flist;
    set<string> codesSet;
    string codestr="";
    for (int i = 0;i < 5;i++)
    {
        int x = wrect.right - 50;
        int y = wrect.top + 50;
        SendMessage(win, WM_MOUSEWHEEL, 0, MAKEWORD(x, y));
        Sleep(200);
        cv::Mat oimg = CaptureUtil::capture(win);
        list<LimitUpData> codes = captureLimitUpCodes(oimg);
        for (list<LimitUpData>::iterator ele = codes.begin();ele != codes.end();ele++) {
            string code = (*ele).code;
            if(codesSet.count(code)==0){
                codesSet.insert(code);
                flist.push_back(*ele);
            }
        }
        codes.clear();
        Sleep(50);
    }
    return flist;
}
//全部开始
void LimitUpCapture::start() {
    running = true;
}
//全部结束
void LimitUpCapture::stop() {
    running = false;
}
bool LimitUpCapture::isInited() {
    return inited;
}
ConsoleApplication/LimitUpCapture.h
New file
@@ -0,0 +1,63 @@
#pragma once
#include <string>
#include <iostream>
#include <list>
#include "ImgUtil.h"
#include "RecognitionManager.h"
enum MoneyUnit {
    MONEY_UNIT_Y,
    MONEY_UNIT_W,
};
struct LimitUpData
{
    string code;
    string time;
    string price;
    string limitMoney;
    MoneyUnit limitMoneyUnit;
    //辅助功能
    int index;
};
//涨停获取
typedef void (*CallbackFun_Limit_Up)(list<LimitUpData> codeList, void* contex);
class LimitUpCapture
{
private:
    static OpenCLExcuter* openCLExcuter;
    static RecognitionManager* recognitionManager;
    static bool inited;
    //是否正在执行
    static bool running;
    static CallbackFun_Limit_Up data_callback;
    static void* context;
    static void _run();
    static HWND win;
public:
    void init(CallbackFun_Limit_Up callback, void* context);
    void refreshHWND();
    bool isRunning();
    static list<LimitUpData> captureLimitUpCodes(cv::Mat img);
    static list<LimitUpData> captureLimitUpCodes();
    //全部开始
    void start();
    //全部结束
    void stop();
    bool isInited();
};
ConsoleApplication/OpenCLExcuter.cpp
@@ -210,12 +210,224 @@
    return fresult;
}
//
void OpenCLExcuter::splitPlateNum(cv::Mat img, IntDataInfo pos, UcharDataInfo result, UcharDataInfo types, unsigned char* zero, int num_width, int num_height,int ele_count_per_line,int length_per_num) {
    clock_t time_0 = clock();
    kernel = clCreateKernel(program, "split_plate_num", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
    int inputSize = (img.cols * img.rows);
    int resultSize = pos.length * (length_per_num * 10 *  num_width * num_height);
    //创建缓存对象
    cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(unsigned char) * inputSize, img.data, &error);
    if (error < 0) {
        throw("Creat memObject1 failed!\n");
    }
    cl_mem memObject2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(int) * pos.length * 4, pos.data, &error);
    if (error < 0) {
        throw("Creat memObject2 failed!\n");
    }
    cl_mem memObject3 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(unsigned char) * num_width * num_height, zero, &error);
    if (error < 0) {
        throw("Creat memObject3 failed!\n");
    }
    cl_mem memObject4 = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
        sizeof(unsigned char) * resultSize, NULL, &error);
    if (error < 0) {
        throw("Creat memObject4 failed!\n");
    }
    cl_mem memObject5 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(unsigned char) * types.length, types.data, &error);
    if (error < 0) {
        throw("Creat memObject5 failed!\n");
    }
    //设置内核参数
    error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
    error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
    error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObject3);
    error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), &memObject5);
    error |= clSetKernelArg(kernel, 4, sizeof(int), &img.cols);
    error |= clSetKernelArg(kernel, 5, sizeof(int), &num_width);
    error |= clSetKernelArg(kernel, 6, sizeof(int), &num_height);
    error |= clSetKernelArg(kernel, 7, sizeof(int), &ele_count_per_line);
    error |= clSetKernelArg(kernel, 8, sizeof(int), &length_per_num);
    error |= clSetKernelArg(kernel, 9, sizeof(cl_mem), &memObject4);
    if (error != CL_SUCCESS) {
        throw("Error setting kernel arguments!\n");
    }
    //执行内核
    size_t globalWorkSize[1] = { pos.length };
    size_t localWorkSize[1] = { 1 };
    const int work_dim = 1;
    error = clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, globalWorkSize,
        localWorkSize, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error queuing kernel for execution!\n");
    }
    //读取执行结果
    error = clEnqueueReadBuffer(queue, memObject4, CL_TRUE, 0, resultSize * sizeof(unsigned char),
        result.data, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error reading result buffer!\n");
    }
    clReleaseKernel(kernel);
    clReleaseMemObject(memObject1);
    clReleaseMemObject(memObject2);
    clReleaseMemObject(memObject3);
    clReleaseMemObject(memObject4);
    clReleaseMemObject(memObject5);
    std::cout << " 耗时:" << (clock() - time_0) << std::endl;
}
void OpenCLExcuter::splitPlateNum(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, "split_plate_num", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
    int inputSize = (img_width * img_height);
    int resultSize = (pos_count / 4) * (num_count * num_width * num_height * 10);
    int length_per_num = 6;
    //创建缓存对象
    cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(unsigned char) * inputSize, img, &error);
    if (error < 0) {
        throw("Creat memObject1 failed!\n");
    }
    cl_mem memObject2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(int) * pos_count * 4, pos, &error);
    if (error < 0) {
        throw("Creat memObject2 failed!\n");
    }
    cl_mem memObject3 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(unsigned char) * num_width * num_height, zero, &error);
    if (error < 0) {
        throw("Creat memObject3 failed!\n");
    }
    cl_mem memObject4 = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
        sizeof(unsigned char) * resultSize, NULL, &error);
    if (error < 0) {
        throw("Creat memObject4 failed!\n");
    }
    unsigned char types[4] = {
            NUM_TYPE_CODE,
            NUM_TYPE_TIME,
            NUM_TYPE_PRICE,
            NUM_TYPE_MONEY,
    };
    cl_mem memObject5 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
        sizeof(unsigned char) * 4, types, &error);
    if (error < 0) {
        throw("Creat memObject5 failed!\n");
    }
    int ele_count_line = 4;
    //设置内核参数
    error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
    error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
    error |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObject3);
    error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), &memObject5);
    error |= clSetKernelArg(kernel, 4, sizeof(int), &img_width);
    error |= clSetKernelArg(kernel, 5, sizeof(int), &num_width);
    error |= clSetKernelArg(kernel, 6, sizeof(int), &num_height);
    error |= clSetKernelArg(kernel, 7, sizeof(int), &ele_count_line);
    error |= clSetKernelArg(kernel, 8, sizeof(int), &length_per_num);
    error |= clSetKernelArg(kernel, 9, sizeof(cl_mem), &memObject4);
    if (error != CL_SUCCESS) {
        throw("Error setting kernel arguments!\n");
    }
    //执行内核
    size_t globalWorkSize[1] = { pos_count };
    size_t localWorkSize[1] = { 1 };
    const int work_dim = 1;
    error = clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, globalWorkSize,
        localWorkSize, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error queuing kernel for execution!\n");
    }
    //读取执行结果
    error = clEnqueueReadBuffer(queue, memObject4, CL_TRUE, 0, resultSize * sizeof(unsigned char),
        result, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error reading result buffer!\n");
    }
    clReleaseKernel(kernel);
    clReleaseMemObject(memObject1);
    clReleaseMemObject(memObject2);
    clReleaseMemObject(memObject3);
    clReleaseMemObject(memObject4);
    clReleaseMemObject(memObject5);
    std::cout << " 耗时:" << (clock() - time_0) << std::endl;
}
void OpenCLExcuter::splitTradeQueueNum(cv::Mat img, IntDataInfo pos, unsigned char* zero, int num_width, int num_height, unsigned char* result,int length_per_num) {
    UcharDataInfo resultData = UcharDataInfo();
    resultData.data = result;
    UcharDataInfo typesData = UcharDataInfo();
    unsigned char types[] = { NUM_TYPE_CODE };
    typesData.length = 1;
    typesData.data = types;
    splitPlateNum(img,pos, resultData, typesData,zero, num_width, num_height,1, length_per_num);
}
void OpenCLExcuter::splitL2Num(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, "split_num", &error);
    kernel = clCreateKernel(program, "split_l2_num", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
@@ -358,7 +570,7 @@
void OpenCLExcuter::splitL2RowData(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int lines,
    int* result) {
    kernel = clCreateKernel(program, "splitRowData", &error);
    kernel = clCreateKernel(program, "splitL2RowData", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
@@ -393,6 +605,82 @@
    error = clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
    error |= clSetKernelArg(kernel, 2, sizeof(int), &imgWidth);
    error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), &memObject3);
    if (error != CL_SUCCESS) {
        throw("Error setting kernel arguments!\n");
    }
    //执行内核
    size_t globalWorkSize[1] = { lines };
    size_t localWorkSize[1] = { 1 };
    const int work_dim = 1;
    error = clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, globalWorkSize,
        localWorkSize, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error queuing kernel for execution!\n");
    }
    //读取执行结果
    error = clEnqueueReadBuffer(queue, memObject3, CL_TRUE, 0, resultSize * sizeof(int),
        result, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error reading result buffer!\n");
    }
    //printf("%d %d %d %d \n", result[0], result[1], result[2], result[3]);
    clReleaseKernel(kernel);
    clReleaseMemObject(memObject1);
    clReleaseMemObject(memObject2);
    clReleaseMemObject(memObject3);
}
void OpenCLExcuter::splitLimitUpRowData(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int lines, int lineEleCount,
    int* result) {
    kernel = clCreateKernel(program, "splitCommonRowData", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
    int inputSize = imgWidth * imgHeight;
    int resultSize = lines * lineEleCount * 4;
    int fromIndex = 1;
    int toIndex = 4;
    //创建缓存对象
    cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(uchar) * inputSize, imgs, &error);
    if (error < 0) {
        throw("Creat memObject1 failed!\n");
    }
    cl_mem memObject2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(int) * lines * 4, rowIndexs, &error);
    if (error < 0) {
        throw("Creat memObject2 failed!\n");
    }
    cl_mem memObject3 = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
        sizeof(int) * resultSize, NULL, &error);
    if (error < 0) {
        throw("Creat memObject3 failed!\n");
    }
    //设置内核参数
    error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
    error = clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
    error |= clSetKernelArg(kernel, 2, sizeof(int), &imgWidth);
    error |= clSetKernelArg(kernel, 3, sizeof(int), &fromIndex);
    error |= clSetKernelArg(kernel, 4, sizeof(int), &toIndex);
    error |= clSetKernelArg(kernel, 5, sizeof(cl_mem), &memObject3);
    if (error != CL_SUCCESS) {
        throw("Error setting kernel arguments!\n");
@@ -498,6 +786,79 @@
}
void OpenCLExcuter::recognitionPlateMoneyUnit(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int colEleCount, int lines,
    int* result) {
    clock_t time_1 = clock();
    kernel = clCreateKernel(program, "recognition_plate_money_unit", &error);
    if (kernel == NULL) {
        throw("Couldn't create kernel!\n");
    }
    int inputSize = imgWidth * imgHeight;
    int resultSize = lines * colEleCount;
    //创建缓存对象
    cl_mem memObject1 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(uchar) * inputSize, imgs, &error);
    if (error < 0) {
        throw("Creat memObject1 failed!\n");
    }
    cl_mem memObject2 = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(int) * lines * 4 * colEleCount, rowIndexs, &error);
    if (error < 0) {
        throw("Creat memObject2 failed!\n");
    }
    cl_mem memObject3 = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
        sizeof(int) * resultSize, NULL, &error);
    if (error < 0) {
        throw("Creat memObject3 failed!\n");
    }
    //设置内核参数
    error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObject1);
    error = clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObject2);
    error |= clSetKernelArg(kernel, 2, sizeof(int), &imgWidth);
    error |= clSetKernelArg(kernel, 3, sizeof(cl_mem), &memObject3);
    if (error != CL_SUCCESS) {
        throw("Error setting kernel arguments!\n");
    }
    //执行内核
    size_t globalWorkSize[1] = { resultSize };
    size_t localWorkSize[1] = { 1 };
    const int work_dim = 1;
    error = clEnqueueNDRangeKernel(queue, kernel, work_dim, NULL, globalWorkSize,
        localWorkSize, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error queuing kernel for execution!\n");
    }
    //读取执行结果
    error = clEnqueueReadBuffer(queue, memObject3, CL_TRUE, 0, resultSize * sizeof(int),
        result, 0, NULL, NULL);
    if (error != CL_SUCCESS) {
        throw("Error reading result buffer!\n");
    }
    //printf("%d %d %d %d \n", result[0], result[1], result[2], result[3]);
    clReleaseKernel(kernel);
    clReleaseMemObject(memObject1);
    clReleaseMemObject(memObject2);
    clReleaseMemObject(memObject3);
}
void OpenCLExcuter::rgb2Gray(unsigned char* imgs, int imgWidth, int imgHeight,
    unsigned char* result) {
ConsoleApplication/OpenCLExcuter.h
@@ -4,6 +4,27 @@
#include<iostream>
#include<CL/cl.h>
#include "ImgUtil.h"
enum SplitType {
    NUM_TYPE_TIME,
    NUM_TYPE_MONEY,
    NUM_TYPE_PRICE,
    NUM_TYPE_CODE,
};
struct IntDataInfo
{
    int* data;
    int length;
};
struct UcharDataInfo
{
    uchar* data;
    int length;
};
class OpenCLExcuter
{
private:
@@ -50,13 +71,29 @@
    void splitL2Num(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 splitPlateNum(cv::Mat img, IntDataInfo pos, UcharDataInfo result, UcharDataInfo types, unsigned char* zero, int num_width, int num_height, int ele_count_per_line, int length_per_num);
    //分隔板块数字
    void splitPlateNum(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 splitTradeQueueNum(cv::Mat img, IntDataInfo pos, unsigned char* zero, int num_width, int num_height, unsigned char* result, int length_per_num);
    //分隔行数据
    //每一行的数据分隔成7个区域
    void splitL2RowData(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int lines,
        int* result);
    void splitLimitUpRowData(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int lines, int lineEleCount,
        int* result);
    //识别非数字
    void recognitionNotNum(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int colCount, int lines,
    void recognitionNotNum(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int colEleCount, int lines,
        int* result);
    void recognitionPlateMoneyUnit(unsigned char* imgs, int imgWidth, int imgHeight, int* rowIndexs, int colEleCount, int lines,
        int* result);
    
ConsoleApplication/RecognitionManager.cpp
@@ -552,10 +552,15 @@
    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);
    }
    free(templateNums);
    free(numberResult[0]);
    free(numberResult);
    free(totalNumberData);
    return resultList;
}
ConsoleApplication/THSActionUtil.cpp
@@ -44,13 +44,13 @@
}
//获取副屏2
HWND getThirdWindow() {
HWND THSActionUtil::getThirdWindow() {
    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 (isSecondScreen(str))
        if (isThirdScreen(str))
        {
            return hwnd;
        }
@@ -363,9 +363,8 @@
    }
}
list<GPCodeArea> splitGPCodeArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col) {
    list<GPCodeArea> resultList;
std::list<int*> THSActionUtil::splitPlateRowArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col) {
    //分隔行内容
    int emptyStartRow = -1;
@@ -390,17 +389,18 @@
                break;
            }
            if (startf > -1 && endf > -1 && emptyEndRow - emptyStartRow > 3) {
            if (startf > -1 && endf > -1 && (dataItemList.size()>0 &&  emptyEndRow - emptyStartRow > 3|| emptyEndRow - emptyStartRow>0)) {
                //内容坐标
                   //LogUtil::debug("内容的高度为:%d \n", endf - startf);
                //行数据高大于6才为有效的行高
                if (endf - startf > 6)
                {
                int* dd = (int*)malloc(sizeof(int) * 4);
                *dd = start_col;
                *(dd + 1) = startf;
                *(dd + 2) = end_col;
                *(dd + 3) = endf;
                //行数据高大于6才为有效的行高
                if (endf - startf > 6)
                {
                    dataItemList.push_back(dd);
                }
                startf = -1;
@@ -424,6 +424,101 @@
            //数据结束
        }
    }
    return dataItemList;
}
//分隔板块行数据
std::list<int*> THSActionUtil::splitPlateRowArea(cv::Mat img) {
    int rows = img.rows;
    int cols = img.cols;
    int r;
    int contentStartRow = -1;
    for (r = 5;r < img.rows;r++) {
        if (ImgDivider::isRowFull(img, r, cols - 100, cols - 5, 2)) {
            contentStartRow = r;
        }
        if (contentStartRow > -1) {
            break;
        }
    }
    if (contentStartRow < 0) {
        throw string("起始行分隔出错");
    }
    //分隔列
    int c = 0;
    int startC = -1;
    int endC = -1;
    for (c = 50;c < cols;c++) {
        if (ImgDivider::isColFull(img, c, contentStartRow + 5, contentStartRow + 100, 2)) {
            if (startC < 0) {
                startC = c;
            }
            else {
                if (c - startC < 20) {
                    startC = c;
                }
                else {
                    endC = c;
                    break;
                }
            }
        }
    }
    if (startC < 0 || endC < 0) {
        throw string("内容框分隔出错");
    }
    //再次分隔内容框,排除干扰
    int cut_index = -1;
    for (int r = contentStartRow + 5;r < contentStartRow + 5 + 100;r++) {
        if (ImgDivider::isRowFull(img, r, startC, endC, 2,25,30)) {
            cut_index = r;
        }
        else {
            if (cut_index>0&& r - cut_index > 30) {
                contentStartRow = cut_index;
                break;
            }
        }
    }
    startC += 1;
    endC -= 1;
    int    start_row = contentStartRow + 25;
    int    start_col = startC;
    int    end_row = rows;
    int    end_col = endC;
    return splitPlateRowArea(img, start_row, start_col, end_row, end_col);
}
list<GPCodeArea> splitGPCodeArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col) {
    list<GPCodeArea> resultList;
    //分隔行内容
    std::list<int*> dataItemList = THSActionUtil::splitPlateRowArea(img, start_row, start_col, end_row, end_col);
    //分隔列
    //分隔每一列的数据
@@ -530,6 +625,12 @@
        }
        //内存释放
        for (std::list<int*>::iterator ele = rowDataList.begin();ele != rowDataList.end();ele++) {
            free(*ele);
        }
        free(*ele);
        //保存数据
        if (false)
@@ -666,7 +767,7 @@
                code.append(to_string(*ele1));
            }
            codeArea.code = code;
            cout << code << endl;
            //cout << code << endl;
            codeList.push_back(codeArea);
        }
    }
@@ -700,21 +801,23 @@
            }
            else {
                if (r - contentStartRow > 10) {
                    contentEndRow = r;
                    //contentEndRow = r;
                }
            }
        }
        if (contentStartRow > -1 && contentEndRow > -1) {
        //contentStartRow > -1 && contentEndRow > -1
        if (contentStartRow > -1) {
            break;
        }
    }
    if (contentStartRow < 0 || contentEndRow < 0) {
    //contentStartRow < 0 || contentEndRow < 0
    if (contentStartRow < 0 ) {
        throw string("起始行或结束行分隔出错");
    }
    contentEndRow = contentStartRow + 50;
    //分隔列
    list<int*> dataColIndexs;
@@ -788,16 +891,148 @@
        int startx = *p;
        int endx = *(p + 1);
        int endRow = 0;
        //判断结束行
        for (int r = contentStartRow + 10;r < img.rows;r++) {
            bool full = ImgDivider::isRowFull(img, r, startx, endx,2 , 10, 30);
            if (full) {
                endRow = r;
                break;
            }
        }
        GPCodeArea area = GPCodeArea();
        area.startx = startx;
        area.endx = endx;
        area.starty = contentStartRow;
        area.endy = contentEndRow;
        area.endy = endRow;
        areaList.push_back(area);
        free(*ele);
    }
    return areaList;
}
//分隔L2交易队列
std::list<GPCodeArea> splitL2TradeQueue(cv::Mat img) {
    int cols = img.cols;
    int contentStartRow = -1;
    int contentEndRow = -1;
    for (int r = 5;r < img.rows;r++) {
        if (ImgDivider::isRowFull(img, r, 0, img.cols/3, 2, 10, 30)&& ImgDivider::isRowFull(img, r, img.cols*2 / 3, img.cols, 2, 10, 30)) {
            if (contentStartRow < 0)
            {
                contentStartRow = r;
                break;
            }
        }
    }
    //contentStartRow < 0 || contentEndRow < 0
    if (contentStartRow < 0) {
        throw string("起始行或结束行分隔出错");
    }
    contentEndRow = contentStartRow + 50;
    //分隔列
    list<int*> dataColIndexs;
    int startf = -1;
    int endf = -1;
    int startIndex = -1;
    for (int i = 10;i < cols;i++) {
        if (startIndex == -1) {
            startIndex = i;
        }
        bool full = ImgDivider::isColFull(img, i, contentStartRow, contentEndRow, 2);
        if (full) {
            if (startf < 0)
            {
                startf = i;
                endf = i;
            }
            else {
                endf = i;
            }
        }
        else {
            if (startf > -1 && endf > -1) {
                int width = endf - startf + 1;
                int* dd = (int*)malloc(sizeof(int) * 2);
                *dd = startIndex;
                *(dd + 1) = startf - 1;
                dataColIndexs.push_back(dd);
                startIndex = i;
            }
            startf = -1;
            endf = -1;
        }
    }
    if (startf > -1 && endf > -1) {
        int width = endf - startf + 1;
        int* dd = (int*)malloc(sizeof(int) * 2);
        *dd = startIndex;
        *(dd + 1) = startf - 1;
        LogUtil::debug("列数据:%d-%d\n", *dd, *(dd + 1));
        dataColIndexs.push_back(dd);
        startf = -1;
        endf = -1;
    }
    if (cols - startIndex > 50) {
        int* dd = (int*)malloc(sizeof(int) * 2);
        *dd = startIndex;
        *(dd + 1) = cols - 1;
        dataColIndexs.push_back(dd);
    }
    std::list<GPCodeArea> areaList;
    list<int*>::iterator ele;
    for (ele = dataColIndexs.begin();ele != dataColIndexs.end();ele++) {
        int* p = *ele;
        int startx = *p;
        int endx = *(p + 1);
        int endRow = 0;
        //判断结束行
        for (int r = contentStartRow + 10;r < img.rows;r++) {
            bool full = ImgDivider::isRowFull(img, r, startx, endx, 2, 10, 30);
            if (full) {
                endRow = r;
                break;
            }
        }
        GPCodeArea area = GPCodeArea();
        area.startx = startx;
        area.endx = endx;
        area.starty = contentStartRow;
        area.endy = endRow;
        areaList.push_back(area);
        free(*ele);
    }
    return areaList;
}
std::map<int, string> THSActionUtil::getListenL2GPCodes(RecognitionManager* recognitionManager) {
@@ -850,6 +1085,13 @@
    int index = 0;
    for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) {
        GPCodeArea area = *ele;
        if (false) {
            string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\";
            path.append("cate_").append(to_string(index)).append(".jpg");
            cv::imwrite(path, cv::Mat(img, cv::Rect(area.startx, area.starty, area.endx - area.startx + 1, area.endy - area.starty + 1)));
        }
        index++;
        std::list<GPCodeArea> resultList = splitGPCodeArea(img, area.starty + 20, area.startx, area.endy, area.endx);
ConsoleApplication/THSActionUtil.h
@@ -36,9 +36,16 @@
    static HWND getL2Win();
    static HWND getThirdWindow();
    //检测环境
    static bool checkEnv();
    //板块内容分割
    static std::list<int*> splitPlateRowArea(cv::Mat img);
    static std::list<int*> splitPlateRowArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col);
    //打开同花顺的副屏幕
    static void openSecondScreen();
    //设置股票
ConsoleApplication/TradeQueueCapture.cpp
New file
@@ -0,0 +1,207 @@
#include "TradeQueueCapture.h"
#include "CaptureUtil.h"
TradeQueueCapture::TradeQueueCapture() {
    openCLExcuter = new OpenCLExcuter();
    openCLExcuter->init();
}
list<int*>    TradeQueueCapture::split(cv::Mat img) {
    int full_row = -1;
    int content_start = -1;
    int content_end = -1;
    list<int*> dataItemList;
    for (int r = 5;r < img.rows;r++) {
        if (ImgDivider::isRowFull(img, r, 0, img.cols, 2, 45, 55)) {
            full_row = r;
            if (content_start >= 0 && content_end >= 0) {
                //加入内容
                //printf("%d-%d\n", content_start, content_end);
                int* item = (int*)malloc(sizeof(int) * 2);
                item[0] = content_start;
                item[1] = content_end;
                dataItemList.push_back(item);
                content_start = -1;
                content_end = -1;
            }
        }
        else {
            if (full_row > -1) {
                if (content_start < 0) {
                    content_start = r;
                    content_end = r;
                }
                else {
                    content_end = r;
                }
            }
        }
    }
    int index = 0;
    list<int*> rowDataList;
    for (list<int*>::iterator ele = dataItemList.begin();ele != dataItemList.end();ele++) {
        index++;
        int start_row = (*ele)[0];
        int end_row = (*ele)[1];
        free(*ele);
        int empty_start = -1;
        int empty_end = -1;
        int content_start = -1;
        int content_end = -1;
        for (int c = 0;c < img.cols;c += 1) {
            if (ImgDivider::isColEmpty(img, c, start_row, end_row, _IMG_BINARY_THRESHOLD)) {
                if (empty_start < 0) {
                    empty_start = c;
                    empty_end = c;
                }
                else {
                    empty_end = c;
                    if (empty_end - empty_start > 5) {
                        if (content_start > -1 && content_end > -1) {
                            //printf("%d-%d\n", content_start, content_end);
                            int* item = (int*)malloc(sizeof(int) * 4);
                            item[0] = content_start;
                            item[1] = start_row;
                            item[2] = content_end;
                            item[3] = end_row;
                            rowDataList.push_back(item);
                            content_start = -1;
                            content_end = -1;
                        }
                    }
                }
            }
            else {
                if (empty_end - empty_start >= 5) {
                    content_start = c;
                    content_end = c;
                    empty_start = -1;
                    empty_end = -1;
                }
                else {
                    if (content_start >= 0) {
                        content_end = c;
                    }
                    empty_start = -1;
                    empty_end = -1;
                }
            }
        }
        if (content_start > -1 && content_end > -1) {
            printf("%d-%d\n", content_start, content_end);
            int* item = (int*)malloc(sizeof(int) * 4);
            item[0] = content_start;
            item[1] = start_row;
            item[2] = content_end;
            item[3] = end_row;
            rowDataList.push_back(item);
            content_start = -1;
            content_end = -1;
        }
    }
    return rowDataList;
}
list<int> TradeQueueCapture::recognition(cv::Mat img,list<int*> rowDataList) {
    int c = 0;
    int* pos = (int*)malloc(sizeof(int) * 4 * rowDataList.size());
    for (list<int*>::iterator ele = rowDataList.begin();ele != rowDataList.end();ele++) {
        pos[c * 4 + 0] = (*ele)[0];
        pos[c * 4 + 1] = (*ele)[1];
        pos[c * 4 + 2] = (*ele)[2];
        pos[c * 4 + 3] = (*ele)[3];
        /*
        string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade_queue\\num_";
        path.append(to_string(index)).append("_").append(to_string(c)).append(".jpg");
        cv::imwrite(path, cv::Mat(img, cv::Rect((*ele)[0], (*ele)[1], (*ele)[2] - (*ele)[0] + 1, (*ele)[3] - (*ele)[1] + 1)));
        */
        free(*ele);
        c++;
    }
    unsigned char* zeroData = (unsigned char*)malloc(sizeof(unsigned char) * _NUMBER_GP_CODE_WIDTH * _NUMBER_GP_CODE_HEIGHT);
    for (int r = 0;r < _NUMBER_GP_CODE_HEIGHT;r++) {
        for (int c = 0;c < _NUMBER_GP_CODE_WIDTH;c++)
        {
            zeroData[r * _NUMBER_GP_CODE_WIDTH + c] = ImgUtil::NUMS_GP_CODE[0].data.ptr<uchar>(r)[c];
        }
    }
    int length_per_num = 5;
    unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowDataList.size()) * _NUMBER_GP_CODE_WIDTH * 10 * length_per_num);
    openCLExcuter->splitTradeQueueNum(img, IntDataInfo({ pos, (int)(rowDataList.size()) }), zeroData, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, totalNumberData, length_per_num);
    /*
    cv::Mat m = cv::Mat::zeros(_NUMBER_GP_CODE_HEIGHT * rowDataList.size(), _NUMBER_GP_CODE_WIDTH * 10 * length_per_num, CV_8UC1);
    m.data = totalNumberData;
    cv::Mat binary;
    threshold(m, binary, 0, 255, cv::THRESH_BINARY);
    cv::imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\trade_queue\\test.jpg", binary);
    */
    uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_GP_CODE_HEIGHT * rowDataList.size()) * _NUMBER_GP_CODE_WIDTH * 10 * length_per_num);
    openCLExcuter->createNumberTemplates(rowDataList.size(), _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, length_per_num, ImgUtil::numsOneLevel_gpcode, templateNums);
    uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowDataList.size() * _NUMBER_GP_CODE_HEIGHT, _NUMBER_GP_CODE_WIDTH * 10 * length_per_num, _NUMBER_GP_CODE_WIDTH, _NUMBER_GP_CODE_HEIGHT, length_per_num);
    list<int> numberList;
    for (int i = 0;i < rowDataList.size();i++) {
        string st = "";
        for (int j = 0;j < length_per_num;j++)
        {
            st.append(to_string(numberResult[i][j]));
        }
        numberList.push_back(stoi(st));
        free(numberResult[i]);
        printf("结果:%d\n", stoi(st));
    }
    free(numberResult);
    free(zeroData);
    free(templateNums);
    free(totalNumberData);
    return numberList;
}
list<int> TradeQueueCapture::recognition(HWND hwnd) {
    cv::Mat img = CaptureUtil::capture(hwnd);
    uchar* data = (uchar*)malloc(sizeof(uchar) * img.cols * img.rows);
    openCLExcuter->rgba2Gray(img.data, img.cols, img.rows, data);
    cv::Mat grayImg = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
    grayImg.data = data;
    img.release();
    list<int*> rowDataList = split(grayImg);
    return recognition(grayImg,rowDataList);
}
list<int> TradeQueueCapture::recognition(cv::Mat grayImg) {
    list<int*> rowDataList = split(grayImg);
    return recognition(grayImg, rowDataList);
}
ConsoleApplication/TradeQueueCapture.h
New file
@@ -0,0 +1,16 @@
#pragma once
#include "ImgUtil.h"
#include "OpenCLExcuter.h"
class TradeQueueCapture
{
private:
    OpenCLExcuter *openCLExcuter;
public:
    TradeQueueCapture();
    list<int*>    split(cv::Mat grayImg);
    list<int> recognition(cv::Mat grayImg,list<int*> pos);
    list<int> recognition(HWND hwnd);
    list<int> recognition(cv::Mat grayImg);
};
ConsoleApplication/Win32Util.cpp
@@ -66,7 +66,7 @@
     TCHAR getbuf[1000];
     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 类型。
     char* chRtn =(char*) alloca( iLen * sizeof(char));  //定义一个 TCHAR 长度大小的 CHAR 类型。
     WideCharToMultiByte(CP_ACP, 0, getbuf, -1, chRtn, iLen, NULL, NULL);  //将TCHAR 类型的数据转换为 CHAR 类型。
     std::string str(chRtn);
     return str;
ConsoleApplication/kernel.cl
@@ -50,7 +50,537 @@
    return v >= 64 ? 1 : 0;
}
__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,
//分隔板块数字
__kernel void split_plate_num(__global const unsigned char* img_in, __global const int* pos_in, __global const unsigned char* zero, __global const unsigned char* types, int width, int num_width, int num_height, int ele_count_per_line,int length_per_num,
    __global unsigned char* result) {
    int index = get_global_id(0);
    //区域坐标
    int startP = index * 4;
    int startx = pos_in[startP];
    int starty = pos_in[startP + 1];
    int endx = pos_in[startP + 2];
    int endy = pos_in[startP + 3];
    if (startx > 0)
    {
        int startNy = -1;
        int endNy = -1;
        //去除上下的白边
        int y = 0;
        for (y = starty;y <= endy;y++) {
            bool empty = 1;
            for (int x = startx;x <= endx;x++)
            {
                int p = get_one_level_position(width, x, y);
                unsigned char value = get_binary_value(img_in[p]);
                //有数据
                if (value > 0) {
                    empty = 0;
                    break;
                }
            }
            if (!empty) {
                startNy = y;
                break;
            }
        }
        for (y = endy;y >= starty;y--) {
            bool empty = 1;
            for (int x = startx;x <= endx;x++)
            {
                int p = get_one_level_position(width, x, y);
                unsigned char value = get_binary_value(img_in[p]);
                //有数据
                if (value > 0) {
                    empty = 0;
                    break;
                }
            }
            if (!empty) {
                endNy = y;
                break;
            }
        }
        starty = startNy;
        endy = endNy;
    }
    int cols = endx - startx + 1;
    int rows = endy - starty + 1;
    //每个元素占用6个数字的空间,不够的前面填充0
    int num_count = ele_count_per_line * length_per_num;
    int nps[12];
    //只能识别4种数字
    unsigned char type = types[index % ele_count_per_line];
    //printf("ele_count_line:%d\n", ele_count_line);
    //时间
    if (type == 0) {
        //时间
        int s = cols / 2;
        int i;
        //往前查找冒号
        int m1_s = -1, m1_e = -1, m2_s = -1, m2_e = -1;
        uchar temp[10];
        for (i = s;i > -1;i--) {
            if (i < 5) {
                break;
            }
            temp[0] = get_binary_value(img_in[get_one_level_position(width, startx + i, endy)]);
            temp[1] = get_binary_value(img_in[get_one_level_position(width, startx + i - 1, endy)]);
            temp[2] = get_binary_value(img_in[get_one_level_position(width, startx + i - 2, endy)]);
            temp[3] = get_binary_value(img_in[get_one_level_position(width, startx + i - 3, endy)]);
            temp[4] = get_binary_value(img_in[get_one_level_position(width, startx + i - 4, endy)]);
            temp[5] = get_binary_value(img_in[get_one_level_position(width, startx + i - 5, endy)]);
            temp[6] = get_binary_value(img_in[get_one_level_position(width, startx + i - 2, endy - 1)]);
            temp[7] = get_binary_value(img_in[get_one_level_position(width, startx + i - 3, endy - 1)]);
            temp[8] = get_binary_value(img_in[get_one_level_position(width, startx + i - 2, endy - 2)]);
            temp[9] = get_binary_value(img_in[get_one_level_position(width, startx + i - 3, endy - 2)]);
            if (temp[3] > 0 && temp[2] > 0 && temp[6] > 0 && temp[7] > 0) {
                int t = temp[0] + temp[1] + temp[4] + temp[5]+ temp[8]+ temp[9];
                if (t == 0) {
                    m1_s = i - 5;
                    m1_e = i;
                    break;
                }
            }
        }
        //往后查找冒号
        for (i = s;i < cols;i++) {
            if (i > cols - 5) {
                break;
            }
            temp[0] = get_binary_value(img_in[get_one_level_position(width, startx + i, endy)]);
            temp[1] = get_binary_value(img_in[get_one_level_position(width, startx + i + 1, endy)]);
            temp[2] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy)]);
            temp[3] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy)]);
            temp[4] = get_binary_value(img_in[get_one_level_position(width, startx + i + 4, endy)]);
            temp[5] = get_binary_value(img_in[get_one_level_position(width, startx + i + 5, endy)]);
            temp[6] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy - 1)]);
            temp[7] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy - 1)]);
            temp[8] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy - 2)]);
            temp[9] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy - 2)]);
            if (temp[2] > 0 && temp[3] > 0 && temp[6] > 0 && temp[7] > 0) {
                int t = temp[0] + temp[1] + temp[4] + temp[5]+ temp[8] + temp[9];
                if (t == 0) {
                    m2_s = i;
                    m2_e = i + 5;
                    break;
                }
            }
        }
        if (m1_s < 0 || m1_e < 0 || m2_s < 0 || m2_e < 0) {
            //没有分割成功的话填充0
            nps[0] = -1;
            nps[1] = -1;
            nps[2] = -1;
            nps[3] = -1;
            nps[4] = -1;
            nps[5] = -1;
            nps[6] = -1;
            nps[7] = -1;
            nps[8] = -1;
            nps[9] = -1;
            nps[10] = -1;
            nps[11] = -1;
        }else {
            //3个时间的坐标
            nps[0] = startx;
            nps[1] = starty;
            nps[2] = startx + m1_s - 1;
            nps[3] = endy;
            nps[4] = startx + m1_e + 1;
            nps[5] = starty;
            nps[6] = startx + m2_s - 1;
            nps[7] = endy;
            nps[8] = startx + m2_e + 1;
            nps[9] = starty;
            nps[10] = endx;
            nps[11] = endy;
        }
    }
    //金额
    else if (type == 1) {
        //查找单位前的空格
        int num_end = -1;
        int i;
        for (i = endx - 11;i >= startx;i--) {
            bool empty = 1;
            for (int y = starty;y < endy;y++) {
                if (get_binary_value(img_in[get_one_level_position(width, i, y)]) > 0) {
                    empty = 0;
                    break;
                }
            }
            if (empty) {
                num_end = i - 1;
                break;
            }
        }
        if (num_end >= 0) {
            endx = num_end;
        }
        //去除上下的空白
        int startNy = -1;
        int endNy = -1;
        //去除上下的白边
        int y = 0;
        for (y = starty;y <= endy;y++) {
            bool empty = 1;
            for (int x = startx;x <= endx;x++)
            {
                int p = get_one_level_position(width, x, y);
                unsigned char value = get_binary_value(img_in[p]);
                //有数据
                if (value > 0) {
                    empty = 0;
                    break;
                }
            }
            if (!empty) {
                startNy = y;
                break;
            }
        }
        for (y = endy;y >= starty;y--) {
            bool empty = 1;
            for (int x = startx;x <= endx;x++)
            {
                int p = get_one_level_position(width, x, y);
                unsigned char value = get_binary_value(img_in[p]);
                //有数据
                if (value > 0) {
                    empty = 0;
                    break;
                }
            }
            if (!empty) {
                endNy = y;
                break;
            }
        }
        starty = startNy;
        endy = endNy;
        cols = endx - startx + 1;
        int m_s = -1, m_e = -1;
        uchar temp[8];
        for (i = 0;i < cols;i++) {
            if (i > cols - 5) {
                break;
            }
            temp[0] = get_binary_value(img_in[get_one_level_position(width, startx + i, endy)]);
            temp[1] = get_binary_value(img_in[get_one_level_position(width, startx + i + 1, endy)]);
            temp[2] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy)]);
            temp[3] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy)]);
            temp[4] = get_binary_value(img_in[get_one_level_position(width, startx + i + 4, endy)]);
            temp[5] = get_binary_value(img_in[get_one_level_position(width, startx + i + 5, endy)]);
            temp[6] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy - 1)]);
            temp[7] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy - 1)]);
            if (temp[2] > 0 && temp[3] > 0 && temp[6] > 0 && temp[7] > 0) {
                if (temp[0] + temp[1] + temp[4] + temp[5] == 0)
                {
                    bool empty = 1;
                    for (int y = starty;y < endy - 1;y++) {
                        if (get_binary_value(img_in[get_one_level_position(width, startx + i + 2, y)]) > 0) {
                            empty = 0;
                            break;
                        }
                    }
                    //小数点上方为空值
                    if (empty) {
                        m_s = i;
                        m_e = i + 5;
                        break;
                    }
                }
            }
        }
        if (m_s == -1 || m_e == -1) {
            nps[0] = -1;
            nps[1] = -1;
            nps[2] = -1;
            nps[3] = -1;
            nps[4] = -1;
            nps[5] = -1;
            nps[6] = -1;
            nps[7] = -1;
        }else {
            nps[0] = startx;
            nps[1] = starty;
            nps[2] = startx + m_s - 1;
            nps[3] = endy;
            nps[4] = startx + m_e + 1;
            nps[5] = starty;
            nps[6] = num_end;
            nps[7] = endy;
        }
    }
    //价格
    else if (type == 2) {
        //股价
        //printf("startx:%d starty:%d endx:%d endy:%d\n",startx,starty,endx,endy);
            //往前查找小数点
        int m_s = -1, m_e = -1;
        uchar temp[8];
        int i;
        for (i = 0;i < cols;i++) {
            if (i > cols - 5) {
                break;
            }
            temp[0] = get_binary_value(img_in[get_one_level_position(width, startx + i, endy)]);
            temp[1] = get_binary_value(img_in[get_one_level_position(width, startx + i + 1, endy)]);
            temp[2] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy)]);
            temp[3] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy)]);
            temp[4] = get_binary_value(img_in[get_one_level_position(width, startx + i + 4, endy)]);
            temp[5] = get_binary_value(img_in[get_one_level_position(width, startx + i + 5, endy)]);
            temp[6] = get_binary_value(img_in[get_one_level_position(width, startx + i + 2, endy - 1)]);
            temp[7] = get_binary_value(img_in[get_one_level_position(width, startx + i + 3, endy - 1)]);
            if (temp[2] > 0 && temp[3] > 0 && temp[6] > 0 && temp[7] > 0) {
                if (temp[0] + temp[1] + temp[4] + temp[5] == 0)
                {
                    bool empty = 1;
                    for (int y = starty;y < endy - 1;y++) {
                        if (get_binary_value(img_in[get_one_level_position(width, startx + i + 2, y)]) > 0) {
                            empty = 0;
                            break;
                        }
                    }
                    //小数点上方为空值
                    if (empty) {
                        m_s = i;
                        m_e = i + 5;
                        break;
                    }
                }
            }
        }
        if (m_s == -1 || m_e == -1) {
            nps[0] = -1;
            nps[1] = -1;
            nps[2] = -1;
            nps[3] = -1;
            nps[4] = -1;
            nps[5] = -1;
            nps[6] = -1;
            nps[7] = -1;
            nps[8] = -1;
            nps[9] = -1;
            nps[10] = -1;
            nps[11] = -1;
        }
        else {
            nps[0] = startx;
            nps[1] = starty;
            nps[2] = startx + m_s - 1;
            nps[3] = endy;
            nps[4] = startx + m_e + 1;
            nps[5] = starty;
            nps[6] = endx;
            nps[7] = endy;
            nps[8] = -1;
            nps[9] = -1;
            nps[10] = -1;
            nps[11] = -1;
        }
    }
    //代码
    else if (type == 3) {
        //手数
        nps[0] = startx;
        nps[1] = starty;
        nps[2] = endx;
        nps[3] = endy;
        nps[4] = -1;
        nps[5] = -1;
        nps[6] = -1;
        nps[7] = -1;
        nps[8] = -1;
        nps[9] = -1;
        nps[10] = -1;
        nps[11] = -1;
    }
    //分隔数据
    //最大分割6个数
    int numCount = 0;
    //记录分割得到的数据
    int  numberCols[12];
    int i;
    for (i = 0;i < 3;i++) {
        if (nps[i * 4] == -1) {
            break;
        }
        int _startx = nps[i * 4];
        int _starty = nps[i * 4 + 1];
        int _endx = nps[i * 4 + 2];
        int _endy = nps[i * 4 + 3];
        int _cols = _endx - _startx + 1;
        int c, startC = -1, endC = -1;
        for (c = 0;c < _cols;c++) {
            bool empty = 1;
            for (int y = _starty;y <= _endy;y++) {
                unsigned char value = get_binary_value(img_in[get_one_level_position(width, _startx + c, y)]);
                if (value > 0) {
                    empty = 0;
                    break;
                }
            }
            if (empty) {
                if (startC > -1 && endC > -1) {
                    numberCols[numCount * 2] = _startx + startC;
                    numberCols[numCount * 2 + 1] = _startx + endC;
                    numCount++;
                }
                startC = -1;
                endC = -1;
            }
            else {
                if (startC == -1) {
                    startC = c;
                    endC = c;
                }
                else {
                    endC = c;
                }
            }
        }
        if (startC > -1 && endC > -1) {
            numberCols[numCount * 2] = _startx + startC;
            numberCols[numCount * 2 + 1] = _startx + endC;
            numCount++;
        }
    }
    int zeroCount = length_per_num - numCount;
    //最大为10位数
    int fresult[10 * 2];
    for (i = 0;i < zeroCount;i++) {
        fresult[i * 2] = -1;
        fresult[i * 2 + 1] = -1;
    }
    for (i = 0;i < numCount;i++) {
        fresult[(i + zeroCount) * 2] = numberCols[i * 2];
        fresult[(i + zeroCount) * 2 + 1] = numberCols[i * 2 + 1];
    }
    //开始填充数据
    for (i = 0;i < length_per_num;i++) {
        unsigned char numData[100 * 100];
        if (fresult[i * 2] == -1) {
            //填充0
            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 * num_width + c] = value;
                }
            }
        }
        else {
            int _startx = fresult[i * 2];
            int _endx = fresult[i * 2 + 1];
            for (int r = starty;r <= endy;r++) {
                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) * num_width + c] = value;
                    }
                    else {
                        numData[(r - starty) * num_width + c] = 0;
                    }
                }
            }
        }
        int rowDataCount = num_height * num_width * 10 * num_count;
        int rowIndex = index / ele_count_per_line;
        int index_0 = rowDataCount * rowIndex;
        //行偏移量
        int index_2 = (num_width * 10) * ( 6 * (index % ele_count_per_line) + i);
        for (int re = 0;re < 10;re++) {
            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 value:%d \n", index, findex, numData[r * num_width + c]);
                    result[findex] = numData[r * num_width + c];
                }
            }
        }
    }
    //printf("\n");
}
//分割L2数字
__kernel void split_l2_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);
@@ -516,7 +1046,7 @@
}
__kernel void splitRowData(__global unsigned char* imgs, __global int* rowIndexs, int width,
__kernel void splitL2RowData(__global unsigned char* imgs, __global int* rowIndexs, int width,
    __global int* result) {
    int gid = get_global_id(0);
@@ -643,6 +1173,102 @@
        */
        }
    }
}
__kernel void splitCommonRowData(__global unsigned char* imgs, __global int* rowIndexs, int width, int fromIndex, int toIndex,
    __global int* result) {
    int gid = get_global_id(0);
    int startCol = rowIndexs[gid * 4];
    int startRow = rowIndexs[gid * 4 + 1];
    int endCol = rowIndexs[gid * 4 + 2];
    int endRow = rowIndexs[gid * 4 + 3];
    //printf(" index:%d - startCol:%d,startRow:%d,endCol:%d,endRow:%d\n", gid, startCol, startRow, endCol, endRow);
    int emptyStart = -1;
    int emptyEnd = -1;
    int dataStart = -1;
    int dataEnd = -1;
    int rowDataSize = 0;
    int ELE_NUMBER_PER_LINE = toIndex - fromIndex + 1;
    //每行最多50个数据
    int rowDataIndexs[50 * 4];
    //排除第一列序号列
    int startRowDataIndex = (ELE_NUMBER_PER_LINE) * 4 * gid;
    for (int i = startCol;i <= endCol;i++) {
        bool empty = 1;
        for (int j = startRow;j <= endRow;j++) {
            unsigned char value = imgs[get_one_level_position(width, i, j)];
            if (value >= 64) {
                empty = 0;
                break;
            }
        }
        if (empty) {
            if (emptyStart < 0) {
                emptyStart = i;
                emptyEnd = i;
            }
            else {
                emptyEnd = i;
            }
            //5个及以上的空白数据才分列
            if (emptyEnd - emptyStart >= 5 && dataEnd - dataStart > 0) {
                if (rowDataSize >= fromIndex && rowDataSize <= toIndex)
                {
                    rowDataIndexs[(rowDataSize - fromIndex) * 4 + 0] = dataStart;
                    rowDataIndexs[(rowDataSize - fromIndex) * 4 + 1] = startRow;
                    rowDataIndexs[(rowDataSize - fromIndex) * 4 + 2] = dataEnd;
                    rowDataIndexs[(rowDataSize - fromIndex) * 4 + 3] = endRow;
                }
                rowDataSize++;
                dataEnd = -1;
                dataStart = -1;
            }
        }
        else {
            if (dataStart < 0) {
                dataStart = i;
                dataEnd = i;
            }
            else {
                dataEnd = i;
            }
            emptyStart = -1;
            emptyEnd = -1;
        }
    }
    //后面的数据没有足够的空白分隔
    if (dataEnd - dataStart > 0) {
        if (rowDataSize >= fromIndex && rowDataSize <= toIndex)
        {
            rowDataIndexs[(rowDataSize - fromIndex) * 4 + 0] = dataStart;
            rowDataIndexs[(rowDataSize - fromIndex) * 4 + 1] = startRow;
            rowDataIndexs[(rowDataSize - fromIndex) * 4 + 2] = dataEnd;
            rowDataIndexs[(rowDataSize - fromIndex) * 4 + 3] = endRow;
        }
        rowDataSize++;
    }
    int emptyCount = 0;
    for (int i = 0;i < ELE_NUMBER_PER_LINE;i++) {
        result[startRowDataIndex + 4 * i + 0] = rowDataIndexs[4 * (i - emptyCount) + 0];
        result[startRowDataIndex + 4 * i + 1] = rowDataIndexs[4 * (i - emptyCount) + 1];
        result[startRowDataIndex + 4 * i + 2] = rowDataIndexs[4 * (i - emptyCount) + 2];
        result[startRowDataIndex + 4 * i + 3] = rowDataIndexs[4 * (i - emptyCount) + 3];
    }
}
@@ -864,3 +1490,44 @@
    }
}
//识别板块中的金额单位
__kernel void recognition_plate_money_unit(__global unsigned char* imgs, __global int* rowIndexs, int width,
    __global int* result) {
    int index = get_global_id(0);
    int start = index * 4;
    int startx = rowIndexs[start+0];
    int starty = rowIndexs[start + 1];
    int endx = rowIndexs[start + 2];
    int endy = rowIndexs[start + 3];
    int unit_start = -1;
    int i;
    for (i = endx - 11;i >= startx;i--) {
        bool empty = 1;
        for (int y = starty;y < endy;y++) {
            if (get_binary_value(imgs[get_one_level_position(width, i, y)]) > 0) {
                empty = 0;
                break;
            }
        }
        if (empty) {
            unit_start = i+1;
            break;
        }
    }
    int count = 0;
    for (int c = unit_start;c <= endx;c++) {
        for (int y = starty;y <= endy;y++) {
            count+=(get_binary_value(imgs[get_one_level_position(width, c, y)]) > 0 ? 1 : 0);
        }
    }
    if (count >= 48) {
        result[index] = 0;
    }
    else {
        result[index] = 1;
    }
}
ConsoleApplication/main.cpp
@@ -1,7 +1,8 @@
#include "ScreenDataCapture.h"
#include "L2DataCapture.h"
#include "CaptureUtil.h"
#include "THSActionUtil.h"
#include "Win32Util.h"
#include "LimitUpCapture.h"
void gray();
void ths();
/*
@@ -15,7 +16,7 @@
    int p = *index;
    ScreenDataCapture* creenDataCapture = new ScreenDataCapture();
    L2DataCapture* creenDataCapture = new L2DataCapture();
    while (true)
    {
        //同花顺(v9.10.50) - 深圳Level-2分时走势
@@ -94,22 +95,32 @@
void notify(int index,string code, list<TradeData> data,void *context) {
    cout << index << endl;
}
void callback(list<LimitUpData> codeList, void* contex) {
}
#include "TradeQueueCapture.h"
void splitTradeQueue() {
    //横向切割
    TradeQueueCapture* tradeQueueCapture = new TradeQueueCapture();
    for (int i = 0;i < 8;i++)
    {
        string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade_queue\\";
        path.append(to_string(i)).append(".jpg");
        tradeQueueCapture->recognition(cv::imread(path, cv::IMREAD_GRAYSCALE));
    }
}
int main() {
    HWND win = HWND(0x000313FE);
    RECT wrect;
    GetWindowRect(win, &wrect);
    ImgUtil::init();
    cv::Mat img=    CaptureUtil::capture(win);
    cv::Mat grayImg= ImgUtil::grayImage(img);
    GPCodeArea area= THSActionUtil::recognitionPlateContentArea(grayImg);
    splitTradeQueue();
    //SendMessage(win, WM_MOUSEMOVE,0, MAKEWORD(area.startx+50, area.starty + 100));
    for (int i = 0;i < 5;i++)
    {
        SendMessage(win, WM_MOUSEWHEEL, 0, MAKEWORD(wrect.right -  50, wrect.top + 50));
        Sleep(1000);
    }
    /*
    ImgUtil::init();
app/ExcelUtil.h
@@ -1,5 +1,5 @@
#pragma once
#include <ScreenDataCapture.h>
#include <L2DataCapture.h>
#include <afxstr.h>
class ExcelUtil
app/JsonUtil.h
@@ -3,6 +3,7 @@
#include <list>
#include "json/json.h"
#include <THSActionUtil.h>
#include "LimitUpCapture.h"
class JsonUtil {
@@ -23,6 +24,19 @@
            item["cancelTime"] = (*ele).cancelTime;
            item["cancelTimeUnit"] = (*ele).cancelTimeUnit;
            root[index++] = item;
        }
        return root;
    }
    static  Json::Value toJson(set<string> dataList) {
        Json::Value root;
        set<string>::iterator ele;
        int index = 0;
        for (ele = dataList.begin();ele != dataList.end();ele++) {
            root[index++] = *ele;
        }
        return root;
    }
@@ -51,6 +65,31 @@
        return toJsonStr(root);
    }
    static  std::string loadLimitUpData(list<LimitUpData>  dataList) {
        Json::Value root;
        root["type"] = 2;
        Json::Value data;
        std::list<LimitUpData>::iterator ele;
        int index = 0;
        for (ele = dataList.begin();ele != dataList.end();ele++) {
            Json::Value  item;
            item["time"] = (*ele).time;
            item["price"] = (*ele).price;
            item["limitMoney"] = (*ele).limitMoney;
            item["limitMoneyUnit"] = (*ele).limitMoneyUnit;
            item["code"] = (*ele).code;
            data[index++] = item;
        }
        root["data"] = data;
        return toJsonStr(root);
    }
    static  std::string loadGPCodeData(std::list<string> codeList) {
        Json::Value root;
app/app.aps
Binary files differ
app/app.rc
Binary files differ
app/appDlg.cpp
@@ -71,13 +71,16 @@
    socketManager = new SocketManager(CappDlg::OnActionCallback, this);
    RecognitionUtil::init();
    ImgUtil::init();
    capture = new  ScreenDataCapture();
    capture = new  L2DataCapture();
    recognitionManager = new RecognitionManager();
    limitUpCapture = new LimitUpCapture();
}
void CappDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_CHECK2, limitUpUpload);
    DDX_Control(pDX, IDC_BUTTON12, limitUpBtn);
}
BEGIN_MESSAGE_MAP(CappDlg, CDialogEx)
@@ -92,6 +95,7 @@
    ON_BN_CLICKED(IDC_BUTTON5, &CappDlg::OnBnClickedButton5)
    ON_BN_CLICKED(IDC_BUTTON7, &CappDlg::OnBnClickedButton7)
    ON_BN_CLICKED(IDC_BUTTON8, &CappDlg::OnBnClickedButton8)
    ON_BN_CLICKED(IDC_BUTTON12, &CappDlg::OnBnClickedButton12)
END_MESSAGE_MAP()
@@ -139,7 +143,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
        }
@@ -203,7 +207,7 @@
}
void  CappDlg::OnDataCallback(int index, string code, list<TradeData> dataList, void* context) {
void  CappDlg::OnL2DataCallback(int index, string code, list<TradeData> dataList, void* context) {
    //转为json
    CappDlg* app = (CappDlg*)context;
    //cout << "回调:" << std::this_thread::get_id() << ":" << index << endl;
@@ -221,6 +225,29 @@
            app->socketManager->Connect(index);
        }
        cout<<"*****数据处理时间:"<<(clock()- time_start)<<endl;
    }
}
void  CappDlg::OnLimitUpDataCallback(list<LimitUpData>  dataList, void* context) {
    //转为json
    CappDlg* app = (CappDlg*)context;
    //cout << "回调:" << std::this_thread::get_id() << ":" << index << endl;
    CButton* btn = (CButton*)app->GetDlgItem(IDC_CHECK2);
    bool check = btn->GetCheck();
    if (check) {
        string data = JsonUtil::loadLimitUpData(dataList);
        clock_t time_start = clock();
        try {
            app->socketManager->sendMsg(8,data.c_str());
        }
        catch (string st) {
            //重新连接服务器
            app->socketManager->resetClient(8);
            app->socketManager->Connect(8);
        }
        cout << "####涨停数据处理时间:" << (clock() - time_start) << endl;
    }
}
@@ -289,6 +316,7 @@
void CappDlg::OnBnClickedButton3()
{
    try {
    socketManager->sendMsg(0, "0");
    socketManager->sendMsg(1, "1");
    socketManager->sendMsg(2, "2");
@@ -297,6 +325,11 @@
    socketManager->sendMsg(5, "5");
    socketManager->sendMsg(6, "6");
    socketManager->sendMsg(7, "7");
    }
    catch (string st) {
        CString msg(st.c_str());
        AfxMessageBox(msg);
    }
}
@@ -319,8 +352,13 @@
    int scount = 0;
    for (int i = 0; i < num; i++)
    {
        try {
        if (socketManager->sendMsg(i, "test")) {
            scount++;
            }
        }
        catch (string st) {
        }
    }
@@ -362,7 +400,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
            CString msg(st.c_str());
@@ -391,7 +429,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
            CString msg(st.c_str());
@@ -446,7 +484,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
            CString msg(st.c_str());
@@ -494,7 +532,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
            CString msg(st.c_str());
@@ -535,7 +573,7 @@
    if (!capture->isInited())
    {
        try {
            capture->init(OnDataCallback, this);
            capture->init(OnL2DataCallback, this);
        }
        catch (string st) {
            CString msg(st.c_str());
@@ -568,3 +606,46 @@
    codesDataDlog dlg;
    dlg.DoModal();
}
//涨停上传
void CappDlg::OnBnClickedButton12()
{
    if (!limitUpCapture->isInited()) {
        try
        {
            limitUpCapture->init(OnLimitUpDataCallback, this);
        }
        catch (string st)
        {
            CString msg(st.c_str());
            AfxMessageBox(msg);
            return;
        }
    }
    if (
        limitUpCapture->isRunning()) {
        limitUpCapture->stop();
        limitUpBtn.SetWindowTextW(_T("启动涨停识别任务"));
    }
    else {
        try
        {
            limitUpCapture->refreshHWND();
        }catch (string st)
        {
            CString msg(st.c_str());
            AfxMessageBox(msg);
            return;
        }
        limitUpCapture->start();
        limitUpBtn.SetWindowTextW(_T("暂停涨停识别任务"));
    }
}
app/appDlg.h
@@ -4,7 +4,8 @@
#pragma once
#include "SocketManager.h"
#include "ScreenDataCapture.h"
#include "L2DataCapture.h"
#include "LimitUpCapture.h"
#include "CaptureUtil.h"
#include "RecognitionManager.h"
@@ -20,9 +21,12 @@
private:
    static RecognitionManager* recognitionManager;
    SocketManager *socketManager;
    ScreenDataCapture* capture;
    L2DataCapture* capture;
    LimitUpCapture* limitUpCapture;
    void OnDataCallback(int index, list<TradeData> dataList);
    static void  OnDataCallback(int index,string code, list<TradeData> dataList, void* context);
    static void  OnL2DataCallback(int index,string code, list<TradeData> dataList, void* context);
    static void  OnLimitUpDataCallback(list<LimitUpData> dataList, void* context);
    static bool  OnActionCallback(string data, void* context);
@@ -63,4 +67,7 @@
    afx_msg void OnBnClickedButton5();
    afx_msg void OnBnClickedButton7();
    afx_msg void OnBnClickedButton8();
    CButton limitUpUpload;
    CButton limitUpBtn;
    afx_msg void OnBnClickedButton12();
};
app/codesDataDlog.h
@@ -1,5 +1,5 @@
#pragma once
#include "ScreenDataCapture.h"
#include "L2DataCapture.h"
// codesDataDlog 对话框
app/level2DataDlg.h
@@ -3,7 +3,7 @@
//
#pragma once
#include "ScreenDataCapture.h"
#include "L2DataCapture.h"
struct Level2CaptureInfo
{
app/resource.h
@@ -23,6 +23,8 @@
#define IDC_BUTTON20                    1014
#define IDC_STATIC3                     1016
#define IDC_EDIT2                       1018
#define IDC_CHECK2                      1020
#define IDC_BUTTON12                    1021
// Next default values for new objects
// 
@@ -30,7 +32,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        134
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1020
#define _APS_NEXT_CONTROL_VALUE         1022
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif