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,7 +94,7 @@
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);
@@ -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 (...) {
@@ -174,6 +187,33 @@
      throw string("未获取到内容窗口句柄");
   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;
}
@@ -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;
@@ -295,7 +335,7 @@
   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) {
      //保存分隔结果
@@ -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,8 +383,8 @@
   //识别数字
   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++) {
      TradeSuccessData industryData = TradeSuccessData();
@@ -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,7 +528,7 @@
//顺序:委托时间-代码-委托数量-委托价格-成交均价-成效数量-操作
list<TradeDelegateData> TradeListCapture::captureTradeDelegateInfo(cv::Mat oimg) {
   cv::Mat grayImg = grayImgs(oimg);
   cv::Mat grayImg = grayImgs(oimg, openCLExcuterDelegate);
      list<TradeDelegateData> dataList;
      //分隔元素
@@ -490,7 +538,7 @@
      int data_end = -1;
      list<int*> rowData;
      for (int r = 0;r < grayImg.rows;r++) {
         if (ImgDivider::isRowEmpty(grayImg, r, 0, 50)) {
      if (ImgDivider::isRowEmpty(grayImg, r, 0, 100)) {
            if (empty_start < 0) {
               empty_start = r;
@@ -560,7 +608,7 @@
      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);
   openCLExcuterDelegate->splitPlateContentRowData(grayImg.data, grayImg.cols, grayImg.rows, rowIndex, rowData.size(), ele_count_per_line, 0, 6, splitResult);
      if (false) {
         //保存分隔结果
@@ -600,7 +648,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);
   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);
@@ -608,8 +656,8 @@
      //识别数字
      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);
   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();
@@ -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();
@@ -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;
}