#include "common/pch.h" #include "ThsCodeOCR.h" #include "win32_screen_shots.h" #include "ImgDivider.h" // using namespace tesseract; cv::Mat ThsCodeOCR::grayImage(cv::Mat src) { cv::Mat grayImage; if (src.channels() == 3) { cvtColor(src, grayImage, cv::COLOR_RGB2GRAY); } else if (src.channels() == 4) { cvtColor(src, grayImage, cv::COLOR_RGBA2GRAY); } else if (src.channels() == 1) { return src; } return grayImage; } ThsCodeOCR::ThsCodeOCR() { tessApi = new tesseract::TessBaseAPI(); // ÉèÖÃÓïÑÔ if (tessApi->Init("tessdata", "eng")) { std::cerr << "Could not initialize tesseract.\n"; exit(1); } } ThsCodeOCR::~ThsCodeOCR() { if (tessApi != nullptr) { // ÇåÀí tessApi->End(); delete tessApi; } } cv::Mat ThsCodeOCR::splitForCodeImg(cv::Mat src) { int rows = src.rows; int cols = src.cols; int full_row = -1; int start_row = -1; int end_row = -1; for (int r = 0; r < rows; r++) { if (ImgDivider::isRowFull(src, r, 0, cols / 2, 1, 14, 17)) { full_row = r; if (start_row >= 0 && r - start_row > 10) { end_row = r - 1; break; } } else { if (full_row > -1) { full_row = -1; if (start_row < 0) { start_row = r; } } } } if (end_row < 0) end_row = rows - 1; if (start_row < 0) throw string("ûÕÒµ½ÉÏ·Ö¸îÏß"); int start_col = cols - 1; for (int c = cols*3/4; c >= 0; c--) { if (ImgDivider::isColFull(src, c, (start_row+ end_row)/2, end_row, 2, 14, 17)) { start_col = c + 1; break; } } int start_index = -1; int end_index = -1; list codes_pos; int max_color = 0; // ¼ÆËãÓұߺóÈý·ÖÖ®Ò»µÄ×î´óÏñËØ for (int r = start_row; r < end_row; r++) { for (int c = cols - 1; c > start_col + (cols - start_col) / 3; c--) { if (src.ptr(r)[c] > max_color) max_color = src.ptr(r)[c]; } } int thresh_hold_color = max_color * 2 / 3; for (int col = cols - 1; col > start_col; col--) { if (!ImgDivider::isColEmpty(src, col, start_row, end_row, thresh_hold_color)) { if (start_index < 0) { start_index = col; } end_index = col; } else { if (end_index >= 0 && start_index >= 0) { codes_pos.push_back(POINT({ end_index - 1, start_index + 1 })); end_index = -1; start_index = -1; if (codes_pos.size() >= 6) { break; } } } } if (codes_pos.size() < 6) { throw string("ûÓÐÕÒµ½6¸öÊý×Ö"); } codes_pos.sort([](POINT p1, POINT p2) { return p1.x < p2.x; }); start_col = codes_pos.begin()->x; int end_col = codes_pos.back().y; return cv::Mat(src, cv::Rect(start_col, start_row, end_col - start_col + 1, end_row - start_row + 1)); } string ThsCodeOCR::ocrCode(cv::Mat src) { Pix* pix = pixCreate(src.cols, src.rows, 8); for (int y = 0; y < src.rows; ++y) { for (int x = 0; x < src.cols; ++x) { pixSetPixel(pix, x, y, src.ptr(y)[x]); } } // ÉèÖÃͼÏñ tessApi->SetImage(pix); // »ñÈ¡Îı¾ char* outText = tessApi->GetUTF8Text(); string text = string(outText); std::cout << "OCR output:\n" << outText << "\n"; pixDestroy(&pix); delete[] outText; text = StringUtil::trim(text); // È¡×îºó6λ if (text.length() > 6) { text = text.substr(text.length()-6, 6); } return text; } string ThsCodeOCR::ocrCode() { RECT rect; cv::Mat mat = ThsCodeOCR::capture(ConfigUtil::getOCRWindowParams()); mat = ThsCodeOCR::splitForCodeImg(mat); string code = ocrCode(mat); return code; } HWND ThsCodeOCR::getTHSWindow() { list hwnds = Win32Util::searchWindow("ͬ»¨Ë³"); for (list::iterator e = hwnds.begin(); e != hwnds.end(); ++e) { HWND hwnd = *e; HWND child = NULL; for (int i = 0; i < 20; i++) { child = FindWindowExA(hwnd, child, NULL, NULL); if (child > 0) { RECT rect; GetWindowRect(child, &rect); if (rect.right - rect.left > 1000 && rect.bottom - rect.top > 800) { return child; } } } } return HWND(); } cv::Mat ThsCodeOCR::capture(OCRWindowParams params) { HWND hwnd = getTHSWindow(); if (hwnd <= 0) { throw string("ûÓлñÈ¡µ½Í¬»¨Ë³´°¿Ú"); } RECT rect; Win32Util::getWindowRect(hwnd, &rect); //[Éϱ߾à, ¿í¶È, ¸ß¶È, Ëõ·Å±¶Êý] int owidth = rect.right - rect.left + 1; RECT area; area.top = params.top; area.left = owidth - params.width; area.bottom = area.top + params.height - 1; area.right = owidth - 2; cv::Mat mat = _wss::get_window_bits(hwnd, &area); // »Ò¶Èת»» mat = grayImage(mat); return mat; }