From a17738e1545ff7dbef6398b8ec1eab93ab59c9a1 Mon Sep 17 00:00:00 2001 From: admin <weikou2014> Date: 星期四, 30 六月 2022 19:14:47 +0800 Subject: [PATCH] '功能完善' --- ConsoleApplication/THSActionUtil.cpp | 536 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 456 insertions(+), 80 deletions(-) diff --git a/ConsoleApplication/THSActionUtil.cpp b/ConsoleApplication/THSActionUtil.cpp index 3506f84..331e092 100644 --- a/ConsoleApplication/THSActionUtil.cpp +++ b/ConsoleApplication/THSActionUtil.cpp @@ -2,6 +2,23 @@ #include "ImgDivider.h" #include "Win32Util.h" +RecognitionManager* THSActionUtil::recognitionManager; + +bool isMainScreen(string str) { + if (str.find("同花顺(") != string::npos) { + cout << str << endl; + if (str.find("副屏") == string::npos) { + if (str.find("热门股") != string::npos || str.find("我的板块") != string::npos) { + return true; + } + } + } + return false; +} + +bool isSecondScreen(string str) { + return str.find("同花顺(") != string::npos && str.find("副屏") != string::npos; +} //获取副屏 HWND getSecondWindow() { @@ -10,12 +27,59 @@ for (ele = wlist.begin();ele != wlist.end();ele++) { HWND hwnd = *ele; string str = Win32Util::getWindowName(hwnd); - if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos) + if (isSecondScreen(str)) { return hwnd; } } return 0; +} + +HWND THSActionUtil::getL2Win() { + 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 (isMainScreen(str)) { + return hwnd; + } + + } + return 0; +} +bool THSActionUtil::checkEnv() { + + list<HWND> wlist = Win32Util::searchWindow("同花顺("); + list<HWND>::iterator ele; + bool fp = false; + bool zp = false; + for (ele = wlist.begin();ele != wlist.end();ele++) { + HWND hwnd = *ele; + string str = Win32Util::getWindowName(hwnd); + if (isSecondScreen(str)) + { + fp = true; + } + + if (isMainScreen(str)) { + zp = true; + } + + } + + if (!zp) { + throw string("同花顺主屏L2窗口未打开"); + } + + + if (!fp) { + throw string("同花顺副屏没有打开"); + } + + return true; } void THSActionUtil::openSecondScreen() { @@ -29,7 +93,7 @@ for (ele = wlist.begin();ele != wlist.end();ele++) { HWND hwnd = *ele; string str = Win32Util::getWindowName(hwnd); - if (str.find("同花顺") != string::npos && str.find("副屏") != string::npos) + if (isSecondScreen(str)) { cout << str << endl; SetForegroundWindow(hwnd); @@ -38,7 +102,7 @@ break; } - if (str.find("同花顺") != string::npos && str.find("热门股") != string::npos) { + if (isMainScreen(str)) { cout << hwnd << endl; //获取尺寸 RECT rc; @@ -51,6 +115,10 @@ } if (!open) { + if (mainPage <= 0) { + throw("未找到首页"); + } + Win32Util::focus(mainPage); //查找主窗口的工具栏 HWND tool = FindWindowExA(mainPage, NULL, "AfxControlBar100s", NULL); @@ -72,7 +140,13 @@ } } //添加股票 -void THSActionUtil::setGP(std::string quickCode, list<std::string> codeList) { +bool THSActionUtil::setGP(std::string quickCode, list<std::string> codeList) { + + list<std::string> tempCodeList; + for (std::list<string>::iterator e = codeList.begin();e != codeList.end();e++) { + tempCodeList.push_back(*e); + } + //打开副屏 HWND sw = getSecondWindow(); if (sw <= 0) @@ -84,32 +158,37 @@ if (sw <= 0) { throw("未打开副屏"); } - + Win32Util::focus(sw); //打开板块 - Win32Util::keyboardNum(quickCode); + Win32Util::keyboardNum(quickCode, 100); Win32Util::keyboard(VK_RETURN, 200); - Sleep(1000); + + Sleep(2000); //设置板块中的股票 //获取板块内容句柄 HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL); - cv::Mat img = CaptureUtil::capture(content); - if (img.cols <= 0 || img.rows <= 0) { - throw("板块截屏内容为空"); + cv::Mat oimg = CaptureUtil::capture(content); + cout << "副屏截图:" << oimg.rows << "-" << oimg.cols << endl; + + if (oimg.cols <= 0 || oimg.rows <= 0) { + throw string("板块截屏内容为空"); } + cv::Mat img = ImgUtil::grayImage(oimg); + oimg.release(); std::list<GPCodeArea> areaList = recognitionGPArea(img); std::list<string> addList; std::list<GPCodeArea> delList; std::list<GPCodeArea> resultList = recognitionNum(img, areaList); - for (std::list<GPCodeArea>::reverse_iterator ele= resultList.rbegin();ele != resultList.rend();++ele) { + for (std::list<GPCodeArea>::reverse_iterator ele = resultList.rbegin();ele != resultList.rend();++ele) { bool contains = false; std::list<string>::iterator e; - for (e = codeList.begin();e != codeList.end();e++) { + for (e = tempCodeList.begin();e != tempCodeList.end();e++) { if (*e == (*ele).code) { contains = true; break; @@ -121,33 +200,70 @@ } else { - codeList.remove((*ele).code); + tempCodeList.remove((*ele).code); } - + } //-----先删除需要删除的 //获取内容板块坐标 - RECT rect; - GetWindowRect(content, &rect); - - for (std::list<GPCodeArea>::iterator ele = delList.begin();ele != delList.end();++ele) { + + RECT rect; + GetWindowRect(sw, &rect); + Win32Util::mouseMove(rect.left + 10, rect.top + 5, 1); + Win32Util::click(10); + + for (std::list<GPCodeArea>::iterator ele = delList.begin();ele != delList.end();++ele) { + RECT rect; + GetWindowRect(content, &rect); + Win32Util::focus(sw); int x = rect.left; int y = rect.top; - x += (*ele).startx+5; - y += (*ele).starty+5; - //选中删除 - Win32Util::click(x,y,50); + x += (*ele).startx + 5; + y += (*ele).starty + 5; //选中删除 + Win32Util::mouseMove(x, y, 50); + Win32Util::click(10); Win32Util::keyboard(VK_DELETE, 50); } + img.release(); //----增加 //截图,识别出增加按钮位置,点击增加,输入内容 + for (std::list<string>::iterator ele = tempCodeList.begin();ele != tempCodeList.end();++ele) { + addGP(*ele); + Sleep(100); + } + oimg = CaptureUtil::capture(content); + if (oimg.cols <= 0 || oimg.rows <= 0) { + throw("板块截屏内容为空"); + } + img = ImgUtil::grayImage(oimg); + areaList = recognitionGPArea(img); + resultList = recognitionNum(img, areaList); + for (std::list<GPCodeArea>::iterator ele = resultList.begin();ele != resultList.end();++ele) { + bool contains = false; + std::list<string>::iterator e; + for (e = codeList.begin();e != codeList.end();e++) { + if (*e == (*ele).code) { + contains = true; + break; + } + } + if (contains) { + codeList.remove((*ele).code); + } + } + + if (codeList.size() == 0) { + return true; + } + + return false; } -void add(string code) { +void THSActionUtil::addGP(string code) { //打开副屏 HWND sw = getSecondWindow(); if (sw <= 0) @@ -161,7 +277,8 @@ } HWND content = FindWindowExA(sw, NULL, "AfxFrameOrView100s", NULL); - cv::Mat img = CaptureUtil::capture(content); + cv::Mat oimg = CaptureUtil::capture(content); + cv::Mat img = ImgUtil::grayImage(oimg); if (img.cols <= 0 || img.rows <= 0) { throw("板块截屏内容为空"); } @@ -169,13 +286,18 @@ for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();++ele) { GPCodeArea codeArea = *ele; if (codeArea.type == IMG_TYPE_ADD) { + Win32Util::focus(sw); RECT rc; - GetWindowRect(HWND(0x00161728), &rc); + GetWindowRect(content, &rc); int y = rc.top + codeArea.starty + (codeArea.endy - codeArea.starty) / 2; int x = rc.left + codeArea.startx + (codeArea.endx - codeArea.startx) / 2; Win32Util::click(x, y, 50); + Sleep(10); + Win32Util::click(x, y, 50); + Sleep(10); + Win32Util::click(x, y, 50); //输入股票代码 - Win32Util::keyboardNum(code,1000); + Win32Util::keyboardNum(code, 1000); Win32Util::keyboard(VK_RETURN, 1500); //关闭按钮 Sleep(100); @@ -186,56 +308,9 @@ } } -//识别股票代码 -std::list<GPCodeArea> THSActionUtil::recognitionGPArea(cv::Mat img) { - //获取title分隔线 - 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; - } +list<GPCodeArea> splitGPCodeArea(cv::Mat img, int start_row, int start_col, int end_row, int end_col) { - if (contentStartRow > -1) { - break; - } - } - - if (contentStartRow < 0) { - throw("起始行分隔出错"); - } - - //分隔列 - 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("内容框分隔出错"); - } - //cv::imshow("内容", cv::Mat(img, cv::Rect(startC, contentStartRow, endC - startC, rows - contentStartRow))); - std::list<GPCodeArea> resultList; - - startC += 1; - endC -= 1; + list<GPCodeArea> resultList; //分隔行内容 int emptyStartRow = -1; @@ -244,8 +319,8 @@ int endf = -1; std::list<int*> dataItemList; - for (int i = contentStartRow + 30;i < rows;i++) { - bool empty = ImgDivider::isRowEmpty(img, i, startC, startC + 50, 1, 64) && ImgDivider::isRowEmpty(img, i, startC + (endC - startC) / 2 - 40, startC + (endC - startC) / 2 + 40, 1, 64); + for (int i = start_row;i < end_row;i++) { + bool empty = ImgDivider::isRowEmpty(img, i, start_col, start_col + 50, 1, _IMG_BINARY_THRESHOLD) && ImgDivider::isRowEmpty(img, i, start_col + (end_col - start_col) / 2 - 40, start_col + (end_col - start_col) / 2 + 40, 1, _IMG_BINARY_THRESHOLD); if (empty) { if (emptyStartRow < 0) { emptyStartRow = i; @@ -264,9 +339,9 @@ //内容坐标 //LogUtil::debug("内容的高度为:%d \n", endf - startf); int* dd = (int*)malloc(sizeof(int) * 4); - *dd = startC; + *dd = start_col; *(dd + 1) = startf; - *(dd + 2) = endC; + *(dd + 2) = end_col; *(dd + 3) = endf; //行数据高大于6才为有效的行高 if (endf - startf > 6) @@ -427,6 +502,62 @@ } +//识别股票代码 +std::list<GPCodeArea> THSActionUtil::recognitionGPArea(cv::Mat img) { + + //imwrite("C:\\Users\\Administrator\\Desktop\\ocr\\test.jpg", img); + //获取title分隔线 + 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("起始行分隔出错"); + } + + //分隔列 + 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("内容框分隔出错"); + } + //cv::imshow("内容", cv::Mat(img, cv::Rect(startC, contentStartRow, endC - startC, rows - contentStartRow))); + + startC += 1; + endC -= 1; + std::list<GPCodeArea> resultList = splitGPCodeArea(img, contentStartRow + 30, startC, rows, endC); + return resultList; + +} + std::list<GPCodeArea> THSActionUtil::recognitionNum(cv::Mat img, std::list<GPCodeArea> areaList) { if (!recognitionManager) { @@ -437,11 +568,34 @@ std::list<GPCodeArea>::iterator ele; + int index = 0; for (ele = areaList.begin();ele != areaList.end();ele++) { + index++; GPCodeArea codeArea = *ele; if (codeArea.type == IMG_TYPE_GP) { cv::Mat nums = cv::Mat(img, cv::Rect(codeArea.startx, codeArea.starty, codeArea.endx - codeArea.startx + 1, codeArea.endy - codeArea.starty + 1)); - std::list<cv::Mat> list2 = ImgUtil::splitNum(nums); + //保存分隔的数据 + if (false) { + string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\"; + path.append(to_string(index)); + path.append(".jpg"); + cv::imwrite(path, nums); + } + + std::list<cv::Mat> list2 = ImgUtil::splitNum(nums, 96); + if (false) { + std::list<cv::Mat>::iterator e; + int ci = 0; + for (e = list2.begin();e != list2.end();e++) { + ci++; + string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\"; + path.append(to_string(index)).append("_").append(to_string(ci)); + path.append(".jpg"); + cv::imwrite(path, *e); + } + + } + std::list<uchar> resultList = recognitionManager->recognitionGPCode(list2); std::list<uchar>::iterator ele1; string code = ""; @@ -449,9 +603,231 @@ code.append(to_string(*ele1)); } codeArea.code = code; + cout << code << endl; codeList.push_back(codeArea); } } return codeList; +} + + +//分隔L2数据的目录 +std::list<GPCodeArea> splitL2Cate(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, 10, 200, 2, 10, 30) && ImgDivider::isRowFull(img, r, img.cols - 200, img.cols - 1, 2, 10, 30)) { + if (contentStartRow < 0) + { + contentStartRow = r; + } + else { + if (r - contentStartRow > 10) { + contentEndRow = r; + + } + + } + } + + if (contentStartRow > -1 && contentEndRow > -1) { + break; + } + } + + if (contentStartRow < 0 || contentEndRow < 0) { + throw("起始行或结束行分隔出错"); + } + + //分隔列 + 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); + + GPCodeArea area = GPCodeArea(); + area.startx = startx; + area.endx = endx; + area.starty = contentStartRow; + area.endy = contentEndRow; + areaList.push_back(area); + } + return areaList; +} + + + +std::map<int,string> THSActionUtil::getListenL2GPCodes() { + std::list<GPCodeArea> areaList = getListenL2GP(); + std::map<int, string> map; + for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) { + GPCodeArea data = (*ele); + if (map.count(data.cateIndex)==0&&data.type== IMG_TYPE_GP) { + map[data.cateIndex] = data.code; + } + } + + return map; +} + + +std::list<GPCodeArea> THSActionUtil::getListenL2GP() { + //截图当前有哪些股票代码 + list<HWND> wlist = Win32Util::searchWindow("同花顺("); + HWND mainPage = 0; + list<HWND>::iterator ele; + for (ele = wlist.begin();ele != wlist.end();ele++) { + HWND hwnd = *ele; + string str = Win32Util::getWindowName(hwnd); + if (isMainScreen(str)) { + cout << hwnd << endl; + //获取尺寸 + RECT rc; + GetWindowRect(hwnd, &rc); + if (rc.right - rc.left > 200 && rc.bottom - rc.top > 200) { + mainPage = hwnd; + break; + } + } + } + if (mainPage <= 0) { + throw string("L2监听未打开"); + } + + HWND content = FindWindowExA(mainPage, NULL, "AfxFrameOrView100s", NULL); + //截图 + cv::Mat oimg = CaptureUtil::capture(content); + cv::Mat img = ImgUtil::grayImage(oimg); + oimg.release(); + //分隔图片 + + std::list<GPCodeArea> areaList = splitL2Cate(img); + + int index = 0; + for (std::list<GPCodeArea>::iterator ele = areaList.begin();ele != areaList.end();ele++) { + GPCodeArea area = *ele; + index++; + std::list<GPCodeArea> resultList = splitGPCodeArea(img, area.starty + 20, area.startx, area.endy, area.endx); + if (false) { + std::string path = "C:\\Users\\Administrator\\Desktop\\ocr\\gpcode\\"; + path.append(std::to_string(index)).append("_listen.jpg"); + imwrite(path, cv::Mat(img, cv::Rect(area.startx, area.starty, area.endx - area.startx + 1, area.endy - area.starty + 1))); + } + + for (std::list<GPCodeArea>::iterator ele1 = resultList.begin();ele1 != resultList.end();ele1++) { + GPCodeArea areaC = *ele1; + if (areaC.type == IMG_TYPE_GP) { + list<cv::Mat> nums = ImgUtil::splitNum(cv::Mat(img, cv::Rect(areaC.startx, areaC.starty, areaC.endx - areaC.startx + 1, areaC.endy - areaC.starty + 1)), 96); + if (!recognitionManager) { + recognitionManager = new RecognitionManager(); + } + if (nums.size() != 6) { + throw string("代码分隔出错"); + } + + + list<uchar> rresult = recognitionManager->recognitionGPCode(nums); + string num; + for (std::list<uchar>::iterator e = rresult.begin();e != rresult.end();e++) { + num.append(to_string(*e)); + } + (*ele1).code = num; + (*ele1).cateIndex = index-1; + } + } + + return resultList; + } + +} +bool THSActionUtil::setListenL2GP(int p, string code) { + + + std::list<GPCodeArea> resultList = getListenL2GP(); + + HWND content = FindWindowExA(getL2Win(), NULL, "AfxFrameOrView100s", NULL); + + int index = 0; + for (std::list<GPCodeArea>::iterator ele = resultList.begin();ele != resultList.end();ele++) { + GPCodeArea result = *ele; + if (result.code == code) { + //点击 + RECT rc; + GetWindowRect(content, &rc); + int x = rc.left + result.startx + 5; + int y = rc.top + result.starty + 5; + Win32Util::focus(content); + Win32Util::click(x, y, 50); + return true; + } + } + return false; } \ No newline at end of file -- Gitblit v1.8.0