admin
2023-01-02 954ead41d9391bca28a3cc4f9592f73f25b3bbc8
ConsoleApplication/TradeListCapture.cpp
@@ -5,12 +5,15 @@
#include "GPUtil.h"
bool TradeListCapture::tradeTimeCapture_success;
bool TradeListCapture::tradeTimeCapture_delegate;
OpenCLExcuter* TradeListCapture::openCLExcuter;
OpenCLExcuter* TradeListCapture::openCLExcuterDelegate;
OpenCLExcuter* TradeListCapture::openCLExcuterSuccess;
bool TradeListCapture::inited;
bool TradeListCapture::kill_d;
bool TradeListCapture::kill_s;
HWND TradeListCapture::trade_delegate_win;
HWND TradeListCapture::trade_success_win;
HWND TradeListCapture::trade_simple_delegate_win;
RecognitionManager* TradeListCapture::recognitionManager;
//是否正在执行
@@ -72,8 +75,8 @@
      if (running_d && inited) {
         clock_t start = clock();
         try {
            list<TradeDelegateData> datas = captureTradeDelegateInfo();
            string money = getAvaiableMoney();
            list<TradeDelegateData> datas = captureSimpleTradeDelegateInfo();
            string money = getSimpleAvaiableMoney();
            cout << "耗时:" << clock() - start << "  数量:" << datas.size() << endl;
            data_callback_delegate(datas, money, context);
            datas.clear();
@@ -81,7 +84,7 @@
         catch (...) {
         }
         Sleep(5);
         Sleep(500);
      }
      else {
         Sleep(2000);
@@ -91,16 +94,16 @@
cv::Mat TradeListCapture::grayImgs(cv::Mat oimg) {
cv::Mat TradeListCapture::grayImgs(cv::Mat oimg, OpenCLExcuter* openCLExcuter) {
   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->rgb2ThresholdInvert(oimg.data, oimg.cols, oimg.rows, imgData,64);
      openCLExcuter->rgb2ThresholdInvert(oimg.data, oimg.cols, oimg.rows, imgData, 64);
   }
   else {
      openCLExcuter->rgba2ThresholdInvert(oimg.data, oimg.cols, oimg.rows, imgData,64);
      openCLExcuter->rgba2ThresholdInvert(oimg.data, oimg.cols, oimg.rows, imgData, 64);
   }
   grayImg.data = imgData;
@@ -118,8 +121,11 @@
   running_d = false;
   recognitionManager = new RecognitionManager();
   openCLExcuter = new OpenCLExcuter();
   openCLExcuter->init();
   openCLExcuterDelegate = new OpenCLExcuter();
   openCLExcuterDelegate->init();
   openCLExcuterSuccess = new OpenCLExcuter();
   openCLExcuterSuccess->init();
   thread rt(&(TradeListCapture::_run_s));
   rt.detach();
@@ -138,6 +144,13 @@
   try {
      refreshTradeDelegateHWND();
   }
   catch (...) {
   }
   try {
      refreshTradeSimpleDelegateHWND();
   }
   catch (...) {
@@ -176,6 +189,33 @@
   trade_delegate_win = content;
}
void TradeListCapture::refreshTradeSimpleDelegateHWND()
{
   HWND hwnd = THSActionUtil::getTradeSimpleDelegateWindow();
   if (hwnd <= 0)
      throw string("同花顺远航版精简交易页面未打开");
   HWND win = FindWindowExA(hwnd, NULL, "AfxMDIFrame140s", NULL);
   HWND child = NULL;
   HWND content = 0;
   for (int i = 0; i < 3; i++) {
      child = FindWindowExA(win, child, "#32770", NULL);
      if (child > 0) {
         HWND table = FindWindowExA(child, NULL, NULL, "HexinScrollWnd");
         if (table > 0) {
            content = table;
            break;
         }
      }
   }
   if (content <= 0)
      throw string("未获取到内容窗口句柄");
   trade_simple_delegate_win = content;
}
void TradeListCapture::refreshTradeSuccessHWND() {
   HWND hwnd = THSActionUtil::getTradeSuccessWindow();
@@ -187,7 +227,7 @@
   HWND temp = FindWindowEx(hwnd, NULL, TEXT("#32770"), NULL);
   HWND first = 0;
   for (int i = 0;i < 20;i++) {
   for (int i = 0; i < 20; i++) {
      if (IsWindowVisible(temp)) {
         RECT rect;
         GetWindowRect(temp, &rect);
@@ -216,7 +256,7 @@
//顺序 代码-成交时间-成交数量-成交均价-成交金额-合同编号-操作
list<TradeSuccessData> TradeListCapture::captureTradeSuccessInfo(cv::Mat oimg) {
   cv::Mat grayImg = grayImgs(oimg);
   cv::Mat grayImg = grayImgs(oimg, openCLExcuterSuccess);
   list<TradeSuccessData> dataList;
   //分隔元素
   int empty_start = -1;
@@ -224,7 +264,7 @@
   int data_start = -1;
   int data_end = -1;
   list<int*> rowData;
   for (int r = 0;r < grayImg.rows;r++) {
   for (int r = 0; r < grayImg.rows; r++) {
      if (ImgDivider::isRowEmpty(grayImg, r, 0, 50)) {
         if (empty_start < 0) {
@@ -261,7 +301,7 @@
   {
      free(grayImg.data);
      grayImg.release();
      for (list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
      for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
         free(*ele);
      }
      return dataList;
@@ -279,7 +319,7 @@
   int* rowIndex = (int*)malloc(sizeof(int) * rowData.size() * 4);
   int index = 0;
   for (list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
   for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
      rowIndex[index * 4 + 0] = 0;
      rowIndex[index * 4 + 1] = (*ele)[0];
      rowIndex[index * 4 + 2] = grayImg.cols - 1;
@@ -295,13 +335,13 @@
   int* splitResult = (int*)malloc(sizeof(int) * 4 * ele_count_per_line * rowData.size());
   openCLExcuter->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 6, splitResult);
   openCLExcuterSuccess->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 6, splitResult);
   if (false) {
      //保存分隔结果
      for (int i = 0;i < rowData.size();i++) {
      for (int i = 0; i < rowData.size(); i++) {
         int start = i * ele_count_per_line * 4;
         for (int j = 0;j < ele_count_per_line;j++)
         for (int j = 0; j < ele_count_per_line; j++)
         {
            int startx = splitResult[start];
@@ -319,8 +359,8 @@
   //分割数字
   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++)
   for (int r = 0; r < _NUMBER_L2_HEIGHT; r++) {
      for (int c = 0; c < _NUMBER_L2_WIDTH; c++)
      {
         zeroData[r * _NUMBER_L2_WIDTH + c] = ImgUtil::NUMS_LEVEL2[0].data.ptr<uchar>(r)[c];
      }
@@ -335,7 +375,7 @@
   typesData.length = ele_count_per_line;
   typesData.data = types;
   openCLExcuter->splitL2NumNew(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, ele_count_per_line, length_per_num);
   openCLExcuterSuccess->splitL2NumNew(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, ele_count_per_line, length_per_num);
@@ -343,22 +383,22 @@
   //识别数字
   uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
   openCLExcuter->createNumberTemplates(rowData.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count, ImgUtil::numsOneLevel_level2, templateNums);
   uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * line_number_count, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count);
   openCLExcuterSuccess->createNumberTemplates(rowData.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count, ImgUtil::numsOneLevel_level2, templateNums);
   uchar** numberResult = openCLExcuterSuccess->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * line_number_count, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count);
   for (int i = 0;i < rowData.size();i++) {
   for (int i = 0; i < rowData.size(); i++) {
      TradeSuccessData industryData = TradeSuccessData();
      //代码
      string code = "";
      for (int j = length_per_num - 6;j < length_per_num;j++)
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         code.append(to_string(numberResult[i][length_per_num * 0 + j]));
      }
      //时间
      string time = "";
      for (int j = length_per_num - 6;j < length_per_num;j++)
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         if (j - (length_per_num - 6) == 2 || j - (length_per_num - 6) == 4)
            time.append(":");
@@ -366,7 +406,7 @@
      }
      //数量
      string num = "";
      for (int j = 0;j < length_per_num;j++)
      for (int j = 0; j < length_per_num; j++)
      {
         num.append(to_string(numberResult[i][length_per_num * 2 + j]));
      }
@@ -374,7 +414,7 @@
      //价格
      string price = "";
      for (int j = 0;j < length_per_num;j++)
      for (int j = 0; j < length_per_num; j++)
      {
         if (j == length_per_num - 3) {
            price.append(".");
@@ -392,7 +432,7 @@
      //金额
      string money = "";
      for (int j = 0;j < length_per_num;j++)
      for (int j = 0; j < length_per_num; j++)
      {
         if (j == length_per_num - 3) {
            money.append(".");
@@ -409,7 +449,7 @@
      //合同编号
      string trade_num = "";
      for (int j = 0;j < length_per_num;j++)
      for (int j = 0; j < length_per_num; j++)
      {
         trade_num.append(to_string(numberResult[i][length_per_num * 5 + j]));
      }
@@ -422,8 +462,8 @@
      int endy = splitResult[start + 3];
      int count = 0;
      for (int r = starty;r <= endy;r++) {
         for (int c = startx;c <= endx;c++) {
      for (int r = starty; r <= endy; r++) {
         for (int c = startx; c <= endx; c++) {
            uchar v = grayImg.ptr<uchar>(r)[c];
            if (v >= _IMG_BINARY_THRESHOLD) {
               count++;
@@ -468,6 +508,14 @@
list<TradeSuccessData> TradeListCapture::captureTradeSuccessInfo() {
   HWND win = THSActionUtil::getTradeSuccessWindow();
   //刷新数据,按F5刷新
   Win32Util::virtualKeyboard(win, VK_F5);
   //HWND toolBar = FindWindowExA(win, NULL, "ToolbarWindow32", NULL);
   //RECT rect;
   //Win32Util::getWindowRect(toolBar, &rect);
   //Win32Util::click(rect.left + 170, rect.top + 5);
   cv::Mat oimg = CaptureUtil::capture(trade_success_win);
   if (oimg.cols < 10 || oimg.rows < 10) {
      throw string("截图出错");
@@ -480,256 +528,256 @@
//顺序:委托时间-代码-委托数量-委托价格-成交均价-成效数量-操作
list<TradeDelegateData> TradeListCapture::captureTradeDelegateInfo(cv::Mat oimg) {
   cv::Mat grayImg = grayImgs(oimg);
   cv::Mat grayImg = grayImgs(oimg, openCLExcuterDelegate);
      list<TradeDelegateData> dataList;
      //分隔元素
      int empty_start = -1;
      int empty_end = -1;
      int data_start = -1;
      int data_end = -1;
      list<int*> rowData;
      for (int r = 0;r < grayImg.rows;r++) {
         if (ImgDivider::isRowEmpty(grayImg, r, 0, 50)) {
   list<TradeDelegateData> dataList;
   //分隔元素
   int empty_start = -1;
   int empty_end = -1;
   int data_start = -1;
   int data_end = -1;
   list<int*> rowData;
   for (int r = 0; r < grayImg.rows; r++) {
      if (ImgDivider::isRowEmpty(grayImg, r, 0, 100)) {
            if (empty_start < 0) {
               empty_start = r;
               empty_end = r;
            }
            else {
               empty_end = r;
            }
            if (data_start > -1 && data_end > -1 && data_end - data_start > 5) {
               printf("%d-%d\n", data_start, data_end);
               int* d = (int*)malloc(sizeof(int) * 2);
               d[0] = data_start;
               d[1] = data_end;
               rowData.push_back(d);
               data_start = -1;
               data_end = -1;
            }
         if (empty_start < 0) {
            empty_start = r;
            empty_end = r;
         }
         else {
            empty_start = -1;
            empty_end = -1;
            if (data_start < 0) {
               data_start = r;
               data_end = r;
            }
            else {
               data_end = r;
            }
            empty_end = r;
         }
         if (data_start > -1 && data_end > -1 && data_end - data_start > 5) {
            printf("%d-%d\n", data_start, data_end);
            int* d = (int*)malloc(sizeof(int) * 2);
            d[0] = data_start;
            d[1] = data_end;
            rowData.push_back(d);
            data_start = -1;
            data_end = -1;
         }
      }
      if (rowData.size() < 2)
      {
         free(grayImg.data);
         grayImg.release();
         for (list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
            free(*ele);
         }
         return dataList;
      }
      else {
         empty_start = -1;
         empty_end = -1;
      //ȥͷȥβ
      list<int*>::iterator start = rowData.begin();
      list<int*>::iterator end = rowData.end();
      free(*start);
      rowData.erase(start);
      std::advance(end, -1);
      free(*end);
      rowData.erase(end);
      int* rowIndex = (int*)malloc(sizeof(int) * rowData.size() * 4);
      int index = 0;
      for (list<int*>::iterator ele = rowData.begin();ele != rowData.end();ele++) {
         rowIndex[index * 4 + 0] = 0;
         rowIndex[index * 4 + 1] = (*ele)[0];
         rowIndex[index * 4 + 2] = grayImg.cols - 1;
         rowIndex[index * 4 + 3] = (*ele)[1];
         free(*ele);
         index++;
      }
      int ele_count_per_line = 7;
      int length_per_num = 8;
      int* splitResult = (int*)malloc(sizeof(int) * 4 * ele_count_per_line * rowData.size());
      openCLExcuter->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 6, splitResult);
      if (false) {
         //保存分隔结果
         for (int i = 0;i < rowData.size();i++) {
            int start = i * ele_count_per_line * 4;
            for (int j = 0;j < ele_count_per_line;j++)
            {
               int startx = splitResult[start];
               int starty = splitResult[start + 1];
               int endx = splitResult[start + 2];
               int endy = splitResult[start + 3];
               start += 4;
               string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade\\";
               path.append(to_string(i)).append("_").append(to_string(j)).append(".jpg");
               cv::imwrite(path, cv::Mat(grayImg, cv::Rect(startx, starty, endx - startx + 1, endy - starty + 1)));
            }
         }
      }
      //分割数字
      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 * _NUMBER_L2_WIDTH + c] = ImgUtil::NUMS_LEVEL2[0].data.ptr<uchar>(r)[c];
         }
      }
      int line_number_count = ele_count_per_line * length_per_num;
      unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
      UcharDataInfo typesData = UcharDataInfo();
      unsigned char types[] = { NUM_TYPE_TIME,NUM_TYPE_CODE,NUM_TYPE_CODE,NUM_TYPE_PRICE,NUM_TYPE_PRICE,NUM_TYPE_CODE, NUM_TYPE_CODE };
      typesData.length = ele_count_per_line;
      typesData.data = types;
      openCLExcuter->splitL2NumNew(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, ele_count_per_line, length_per_num);
      //识别数字
      uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
      openCLExcuter->createNumberTemplates(rowData.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count, ImgUtil::numsOneLevel_level2, templateNums);
      uchar** numberResult = openCLExcuter->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * line_number_count, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count);
      for (int i = 0;i < rowData.size();i++) {
         TradeDelegateData delegateData = TradeDelegateData();
         //时间
         string time = "";
         for (int j = length_per_num - 6;j < length_per_num;j++)
         {
            if (j - (length_per_num - 6) == 2 || j - (length_per_num - 6) == 4)
               time.append(":");
            time.append(to_string(numberResult[i][length_per_num * 0 + j]));
         }
         //代码
         string code = "";
         for (int j = length_per_num - 6;j < length_per_num;j++)
         {
            code.append(to_string(numberResult[i][length_per_num * 1 + j]));
         }
         //委托数量
         string num = "";
         for (int j = 0;j < length_per_num;j++)
         {
            num.append(to_string(numberResult[i][length_per_num * 2 + j]));
         }
         num = to_string(stoi(num));
         //委托价格
         string delegate_price = "";
         for (int j = 0;j < length_per_num;j++)
         {
            if (length_per_num - j == 3)
               delegate_price.append(".");
            delegate_price.append(to_string(numberResult[i][length_per_num * 3 + j]));
         }
         delegate_price = to_string(stod(delegate_price));
         char* chCode;
         chCode = new char[20];
         sprintf_s(chCode, delegate_price.length(), "%.3lf", stod(delegate_price));
         std::string delegate_price_str(chCode);
         delegate_price = delegate_price_str;
         //成交均价
         string percent_price = "";
         for (int j = 0;j < length_per_num;j++)
         {
            if (length_per_num - j == 3)
               percent_price.append(".");
            percent_price.append(to_string(numberResult[i][length_per_num * 4 + j]));
         }
         chCode = new char[20];
         sprintf_s(chCode, percent_price.length(), "%.3lf", stod(percent_price));
         std::string percent_price_str(chCode);
         percent_price = percent_price_str;
         //成交数量
         string success_num = "";
         for (int j = 0;j < length_per_num;j++)
         {
            success_num.append(to_string(numberResult[i][length_per_num * 5 + j]));
         }
         success_num = to_string(stoi(success_num));
         //买入卖出
         int start = i * 4 * ele_count_per_line + 6 * 4;
         int startx = splitResult[start];
         int starty = splitResult[start + 1];
         int endx = splitResult[start + 2];
         int endy = splitResult[start + 3];
         int count = 0;
         for (int r = starty;r <= endy;r++) {
            for (int c = startx;c <= endx;c++) {
               uchar v = grayImg.ptr<uchar>(r)[c];
               if (v >= _IMG_BINARY_THRESHOLD) {
                  count++;
               }
            }
         }
         if (count > 50) {
            //卖出
            delegateData.type = TRADE_TYPE_SELL;
         if (data_start < 0) {
            data_start = r;
            data_end = r;
         }
         else {
            //买入
            delegateData.type = TRADE_TYPE_BUY;
            data_end = r;
         }
         delegateData.index = i;
         delegateData.code = code;
         delegateData.time = time;
         delegateData.num = num;
         delegateData.price = delegate_price;
         delegateData.trade_price = percent_price;
         delegateData.trade_num = success_num;
         dataList.push_back(delegateData);
         free(numberResult[i]);
      }
      free(totalNumberData);
      free(numberResult);
      free(rowIndex);
      free(splitResult);
      free(zeroData);
      free(templateNums);
   }
   if (rowData.size() < 2)
   {
      free(grayImg.data);
      grayImg.release();
      for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
         free(*ele);
      }
      return dataList;
   }
   //ȥͷȥβ
   list<int*>::iterator start = rowData.begin();
   list<int*>::iterator end = rowData.end();
   free(*start);
   rowData.erase(start);
   std::advance(end, -1);
   free(*end);
   rowData.erase(end);
   int* rowIndex = (int*)malloc(sizeof(int) * rowData.size() * 4);
   int index = 0;
   for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
      rowIndex[index * 4 + 0] = 0;
      rowIndex[index * 4 + 1] = (*ele)[0];
      rowIndex[index * 4 + 2] = grayImg.cols - 1;
      rowIndex[index * 4 + 3] = (*ele)[1];
      free(*ele);
      index++;
   }
   int ele_count_per_line = 7;
   int length_per_num = 8;
   int* splitResult = (int*)malloc(sizeof(int) * 4 * ele_count_per_line * rowData.size());
   openCLExcuterDelegate->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 6, splitResult);
   if (false) {
      //保存分隔结果
      for (int i = 0; i < rowData.size(); i++) {
         int start = i * ele_count_per_line * 4;
         for (int j = 0; j < ele_count_per_line; j++)
         {
            int startx = splitResult[start];
            int starty = splitResult[start + 1];
            int endx = splitResult[start + 2];
            int endy = splitResult[start + 3];
            start += 4;
            string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade\\";
            path.append(to_string(i)).append("_").append(to_string(j)).append(".jpg");
            cv::imwrite(path, cv::Mat(grayImg, cv::Rect(startx, starty, endx - startx + 1, endy - starty + 1)));
         }
      }
   }
   //分割数字
   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 * _NUMBER_L2_WIDTH + c] = ImgUtil::NUMS_LEVEL2[0].data.ptr<uchar>(r)[c];
      }
   }
   int line_number_count = ele_count_per_line * length_per_num;
   unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
   UcharDataInfo typesData = UcharDataInfo();
   unsigned char types[] = { NUM_TYPE_TIME,NUM_TYPE_CODE,NUM_TYPE_CODE,NUM_TYPE_PRICE,NUM_TYPE_PRICE,NUM_TYPE_CODE, NUM_TYPE_CODE };
   typesData.length = ele_count_per_line;
   typesData.data = types;
   openCLExcuterDelegate->splitL2NumNew(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, ele_count_per_line, length_per_num);
   //识别数字
   uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
   openCLExcuterDelegate->createNumberTemplates(rowData.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count, ImgUtil::numsOneLevel_level2, templateNums);
   uchar** numberResult = openCLExcuterDelegate->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * line_number_count, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count);
   for (int i = 0; i < rowData.size(); i++) {
      TradeDelegateData delegateData = TradeDelegateData();
      //时间
      string time = "";
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         if (j - (length_per_num - 6) == 2 || j - (length_per_num - 6) == 4)
            time.append(":");
         time.append(to_string(numberResult[i][length_per_num * 0 + j]));
      }
      //代码
      string code = "";
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         code.append(to_string(numberResult[i][length_per_num * 1 + j]));
      }
      //委托数量
      string num = "";
      for (int j = 0; j < length_per_num; j++)
      {
         num.append(to_string(numberResult[i][length_per_num * 2 + j]));
      }
      num = to_string(stoi(num));
      //委托价格
      string delegate_price = "";
      for (int j = 0; j < length_per_num; j++)
      {
         if (length_per_num - j == 3)
            delegate_price.append(".");
         delegate_price.append(to_string(numberResult[i][length_per_num * 3 + j]));
      }
      delegate_price = to_string(stod(delegate_price));
      char* chCode;
      chCode = new char[20];
      sprintf_s(chCode, delegate_price.length(), "%.3lf", stod(delegate_price));
      std::string delegate_price_str(chCode);
      delegate_price = delegate_price_str;
      //成交均价
      string percent_price = "";
      for (int j = 0; j < length_per_num; j++)
      {
         if (length_per_num - j == 3)
            percent_price.append(".");
         percent_price.append(to_string(numberResult[i][length_per_num * 4 + j]));
      }
      chCode = new char[20];
      sprintf_s(chCode, percent_price.length(), "%.3lf", stod(percent_price));
      std::string percent_price_str(chCode);
      percent_price = percent_price_str;
      //成交数量
      string success_num = "";
      for (int j = 0; j < length_per_num; j++)
      {
         success_num.append(to_string(numberResult[i][length_per_num * 5 + j]));
      }
      success_num = to_string(stoi(success_num));
      //买入卖出
      int start = i * 4 * ele_count_per_line + 6 * 4;
      int startx = splitResult[start];
      int starty = splitResult[start + 1];
      int endx = splitResult[start + 2];
      int endy = splitResult[start + 3];
      int count = 0;
      for (int r = starty; r <= endy; r++) {
         for (int c = startx; c <= endx; c++) {
            uchar v = grayImg.ptr<uchar>(r)[c];
            if (v >= _IMG_BINARY_THRESHOLD) {
               count++;
            }
         }
      }
      if (count > 50) {
         //卖出
         delegateData.type = TRADE_TYPE_SELL;
      }
      else {
         //买入
         delegateData.type = TRADE_TYPE_BUY;
      }
      delegateData.index = i;
      delegateData.code = code;
      delegateData.time = time;
      delegateData.num = num;
      delegateData.price = delegate_price;
      delegateData.trade_price = percent_price;
      delegateData.trade_num = success_num;
      dataList.push_back(delegateData);
      free(numberResult[i]);
   }
   free(totalNumberData);
   free(numberResult);
   free(rowIndex);
   free(splitResult);
   free(zeroData);
   free(templateNums);
   free(grayImg.data);
   grayImg.release();
   return dataList;
}
@@ -744,6 +792,298 @@
   return codes;
}
list<TradeDelegateData> TradeListCapture::captureSimpleTradeDelegateInfo(cv::Mat img)
{
   cv::Mat grayImg = grayImgs(img, openCLExcuterDelegate);
   list<TradeDelegateData> dataList;
   //分隔元素
   int empty_start = -1;
   int empty_end = -1;
   int data_start = -1;
   int data_end = -1;
   list<int*> rowData;
   for (int r = 0; r < grayImg.rows; r++) {
      if (ImgDivider::isRowEmpty(grayImg, r, 0, 100)) {
         if (empty_start < 0) {
            empty_start = r;
            empty_end = r;
         }
         else {
            empty_end = r;
         }
         if (data_start > -1 && data_end > -1 && data_end - data_start > 5) {
            printf("%d-%d\n", data_start, data_end);
            int* d = (int*)malloc(sizeof(int) * 2);
            d[0] = data_start;
            d[1] = data_end;
            rowData.push_back(d);
            data_start = -1;
            data_end = -1;
         }
      }
      else {
         empty_start = -1;
         empty_end = -1;
         if (data_start < 0) {
            data_start = r;
            data_end = r;
         }
         else {
            data_end = r;
         }
      }
   }
   if (rowData.size() < 2)
   {
      free(grayImg.data);
      grayImg.release();
      for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
         free(*ele);
      }
      return dataList;
   }
   //ȥͷȥβ
   list<int*>::iterator start = rowData.begin();
   list<int*>::iterator end = rowData.end();
   int start_end = (*start)[1];
   free(*start);
   rowData.erase(start);
   if (rowData.size() == 1)
   {
      std::advance(end, -1);
      if ((*end)[0] - start_end > 30)
      {
         free(*end);
         rowData.erase(end);
      }
   }
   else {
      std::advance(end, -1);
      free(*end);
      rowData.erase(end);
   }
   int* rowIndex = (int*)malloc(sizeof(int) * rowData.size() * 4);
   int index = 0;
   for (list<int*>::iterator ele = rowData.begin(); ele != rowData.end(); ele++) {
      rowIndex[index * 4 + 0] = 0;
      rowIndex[index * 4 + 1] = (*ele)[0];
      rowIndex[index * 4 + 2] = grayImg.cols - 1;
      rowIndex[index * 4 + 3] = (*ele)[1];
      free(*ele);
      index++;
   }
   int ele_count_per_line = 8;
   int length_per_num = 9;
   int* splitResult = (int*)malloc(sizeof(int) * 4 * ele_count_per_line * rowData.size());
   openCLExcuterDelegate->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 7, splitResult);
   if (false) {
      //保存分隔结果
      for (int i = 0; i < rowData.size(); i++) {
         int start = i * ele_count_per_line * 4;
         for (int j = 0; j < ele_count_per_line; j++)
         {
            int startx = splitResult[start];
            int starty = splitResult[start + 1];
            int endx = splitResult[start + 2];
            int endy = splitResult[start + 3];
            start += 4;
            string path = "C:\\Users\\Administrator\\Desktop\\ocr\\trade\\";
            path.append(to_string(i)).append("_").append(to_string(j)).append(".jpg");
            cv::imwrite(path, cv::Mat(grayImg, cv::Rect(startx, starty, endx - startx + 1, endy - starty + 1)));
         }
      }
   }
   //分割数字
   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 * _NUMBER_L2_WIDTH + c] = ImgUtil::NUMS_LEVEL2[0].data.ptr<uchar>(r)[c];
      }
   }
   int line_number_count = ele_count_per_line * length_per_num;
   unsigned char* totalNumberData = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
   UcharDataInfo typesData = UcharDataInfo();
   //委托时间,证券代码,申报时间,委托数量,委托价格,成交均价,成交数量,操作
   unsigned char types[] = { NUM_TYPE_TIME,NUM_TYPE_CODE,NUM_TYPE_NUM,NUM_TYPE_CODE,NUM_TYPE_PRICE,NUM_TYPE_PRICE,NUM_TYPE_CODE, NUM_TYPE_CODE };
   typesData.length = ele_count_per_line;
   typesData.data = types;
   openCLExcuterDelegate->splitL2NumNew(grayImg, IntDataInfo({ splitResult,(int)(ele_count_per_line * rowData.size()) }), UcharDataInfo({ totalNumberData, -1 }), typesData, zeroData, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, ele_count_per_line, length_per_num);
   //识别数字
   uchar* templateNums = (unsigned char*)malloc(sizeof(unsigned char) * (_NUMBER_L2_HEIGHT * rowData.size()) * _NUMBER_L2_WIDTH * 10 * line_number_count);
   openCLExcuterDelegate->createNumberTemplates(rowData.size(), _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count, ImgUtil::numsOneLevel_level2, templateNums);
   uchar** numberResult = openCLExcuterDelegate->recognition_numbers(totalNumberData, templateNums, rowData.size() * _NUMBER_L2_HEIGHT, _NUMBER_L2_WIDTH * 10 * line_number_count, _NUMBER_L2_WIDTH, _NUMBER_L2_HEIGHT, line_number_count);
   for (int i = 0; i < rowData.size(); i++) {
      TradeDelegateData delegateData = TradeDelegateData();
      //时间
      string time = "";
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         if (j - (length_per_num - 6) == 2 || j - (length_per_num - 6) == 4)
            time.append(":");
         time.append(to_string(numberResult[i][length_per_num * 0 + j]));
      }
      //代码
      string code = "";
      for (int j = length_per_num - 6; j < length_per_num; j++)
      {
         code.append(to_string(numberResult[i][length_per_num * 1 + j]));
      }
      // 申报时间
      string apply_time = "";
      for (int j = length_per_num - 9; j < length_per_num; j++)
      {
         apply_time.append(to_string(numberResult[i][length_per_num * 2 + j]));
      }
      //委托数量
      string num = "";
      for (int j = 0; j < length_per_num; j++)
      {
         num.append(to_string(numberResult[i][length_per_num * 3 + j]));
      }
      num = to_string(stoi(num));
      //委托价格
      string delegate_price = "";
      for (int j = 0; j < length_per_num; j++)
      {
         if (length_per_num - j == 3)
            delegate_price.append(".");
         delegate_price.append(to_string(numberResult[i][length_per_num * 4 + j]));
      }
      delegate_price = to_string(stod(delegate_price));
      char* chCode;
      chCode = new char[20];
      sprintf_s(chCode, delegate_price.length(), "%.3lf", stod(delegate_price));
      std::string delegate_price_str(chCode);
      delegate_price = delegate_price_str;
      //成交均价
      string percent_price = "";
      for (int j = 0; j < length_per_num; j++)
      {
         if (length_per_num - j == 3)
            percent_price.append(".");
         percent_price.append(to_string(numberResult[i][length_per_num * 5 + j]));
      }
      chCode = new char[20];
      sprintf_s(chCode, percent_price.length(), "%.3lf", stod(percent_price));
      std::string percent_price_str(chCode);
      percent_price = percent_price_str;
      //成交数量
      string success_num = "";
      for (int j = 0; j < length_per_num; j++)
      {
         success_num.append(to_string(numberResult[i][length_per_num * 6 + j]));
      }
      success_num = to_string(stoi(success_num));
      //买入卖出
      int start = i * 4 * ele_count_per_line + 7 * 4;
      int startx = splitResult[start];
      int starty = splitResult[start + 1];
      int endx = splitResult[start + 2];
      int endy = splitResult[start + 3];
      int count = 0;
      for (int r = starty; r <= endy; r++) {
         for (int c = startx; c <= endx; c++) {
            uchar v = grayImg.ptr<uchar>(r)[c];
            if (v >= _IMG_BINARY_THRESHOLD) {
               count++;
            }
         }
      }
      if (count > 50) {
         //卖出
         delegateData.type = TRADE_TYPE_SELL;
      }
      else {
         //买入
         delegateData.type = TRADE_TYPE_BUY;
      }
      delegateData.index = i;
      delegateData.code = code;
      delegateData.time = time;
      delegateData.apply_time = apply_time;
      delegateData.num = num;
      delegateData.price = delegate_price;
      delegateData.trade_price = percent_price;
      delegateData.trade_num = success_num;
      dataList.push_back(delegateData);
      free(numberResult[i]);
   }
   free(totalNumberData);
   free(numberResult);
   free(rowIndex);
   free(splitResult);
   free(zeroData);
   free(templateNums);
   free(grayImg.data);
   grayImg.release();
   return dataList;
}
list<TradeDelegateData> TradeListCapture::captureSimpleTradeDelegateInfo()
{
   HWND win = THSActionUtil::getTradeSimpleDelegateWindow();
   //刷新数据,按F5刷新
   Win32Util::virtualKeyboard(win, VK_F5);
   cv::Mat oimg = CaptureUtil::capture(trade_simple_delegate_win);
   if (oimg.cols < 10 || oimg.rows < 10) {
      throw string("截图出错");
   }
   list<TradeDelegateData> codes = captureSimpleTradeDelegateInfo(oimg);
   return codes;
}
string TradeListCapture::getAvaiableMoney()
{
   HWND hwnd = THSActionUtil::getTradeDelegateWindow();
@@ -753,7 +1093,7 @@
   HWND temp = FindWindowEx(hwnd, NULL, TEXT("#32770"), NULL);
   HWND avaiableMoneyHWND = 0;
   for (int i = 0;i < 20;i++) {
   for (int i = 0; i < 20; i++) {
      if (IsWindowVisible(temp)) {
         HWND tempW = FindWindowEx(temp, NULL, TEXT("Static"), TEXT("可用"));
         if (tempW > 0) {
@@ -772,6 +1112,34 @@
   return text;
}
string TradeListCapture::getSimpleAvaiableMoney()
{
   HWND hwnd = THSActionUtil::getTradeSimpleDelegateWindow();
   if (hwnd <= 0) {
      throw   string("委托窗口未打开");
   }
   HWND win = FindWindowExA(hwnd, NULL, "AfxMDIFrame140s", NULL);
   HWND child = NULL;
   HWND avaiableMoneyHWND = 0;
   for (int i = 0; i < 5; i++) {
      child = FindWindowExA(win, child, "#32770", NULL);
      if (child > 0 && Win32Util::isWindowShow(child)) {
         HWND table = FindWindowExA(child, NULL, NULL, "HexinScrollWnd");
         if (table > 0) {
            child = FindWindowExA(child, NULL, "#32770", NULL);
            avaiableMoneyHWND = GetDlgItem(child, 0x000003F8);
            break;
         }
      }
   }
   if (avaiableMoneyHWND <= 0) {
      throw   string("未查找到可用余额控件");
   }
   string text = Win32Util::getWindowName(avaiableMoneyHWND);
   return text;
}
bool TradeListCapture::isInited() {
   return inited;
}