Advertisement
Guest User

Untitled

a guest
Dec 4th, 2016
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.94 KB | None | 0 0
  1. #include "CaptchaApplication.h"
  2.  
  3. cv::Mat CaptchaApplication::getCaptcha() {
  4.     // квадрат с капчей посередине, который можно спокойно вращать на хую
  5.     cv::Mat captcha(250, 250, CV_8UC1, cv::Scalar(255));
  6.     // загрузить капчу и захуярить ее посередине
  7.     cv::imread(qPrintable(arguments().at(1)), cv::IMREAD_GRAYSCALE).copyTo(captcha(cv::Rect(35, 85, 180, 80)));
  8.  
  9.     return captcha;
  10. }
  11.  
  12. cv::Mat CaptchaApplication::getDigit(Digit digit) {
  13.     QString fpath = QString("/home/wolph/captcha/digit_%1.png").arg(digit);
  14.     cv::Mat digitMat = cv::imread(qPrintable(fpath), cv::IMREAD_GRAYSCALE);
  15.     return digitMat;
  16. }
  17.  
  18. std::array<CaptchaApplication::DigitData, 10> CaptchaApplication::getDigits(const cv::Mat &captcha)
  19. {
  20.     std::array<DigitData, 10> result;
  21.  
  22.     for (size_t i=0; i<result.size(); ++i) {
  23.         Digit digit = static_cast<Digit>(i);
  24.         QString fpath = QString("/home/wolph/captcha/digit_%1.png").arg(digit);
  25.         result[i].digitMat = cv::imread(qPrintable(fpath), cv::IMREAD_GRAYSCALE);
  26.         result[i].maskMat = cv::Scalar::all(255) - result[i].digitMat;
  27.         result[i].matchMat = cv::Mat(captcha.rows - result[i].digitMat.rows + 1, captcha.cols - result[i].digitMat.cols + 1, CV_32FC1);
  28.     }
  29.  
  30.     return result;
  31. }
  32.  
  33. void CaptchaApplication::findZero(double angle) {    
  34.     // загрузить капчу
  35.     static cv::Mat captcha = getCaptcha();
  36.     static auto digits = getDigits(captcha);
  37.  
  38.     // матрица поворота на 45 градусов
  39.     cv::Mat rotMat = cv::getRotationMatrix2D(cv::Point2f(124.5, 124.5), angle, 1.0);
  40.  
  41.     cv::Mat captcha_rotated = captcha.clone();
  42.     cv::warpAffine(captcha, captcha_rotated, rotMat, captcha.size(), cv::INTER_LANCZOS4, cv::BORDER_CONSTANT, cv::Scalar(255));
  43.  
  44.     auto findDigit = [&captcha_rotated, this](Digit curDigit, cv::Mat &digitMat, cv::Mat &maskMat, cv::Mat &matchMat){
  45.         double maxVal;
  46.         cv::Point maxLoc;
  47.  
  48.         cv::matchTemplate( captcha_rotated, digitMat, matchMat, CV_TM_CCORR_NORMED, maskMat);
  49.         cv::minMaxLoc(matchMat, NULL, &maxVal, NULL, &maxLoc, cv::Mat() );
  50.  
  51.         if (maxVal > 0.915) {
  52.  
  53.             cv::Point2f signCenter(maxLoc.x + digitMat.cols / 2.0, maxLoc.y + digitMat.rows / 2.0);
  54.             cv::Point2f captchaCenter(captcha.cols / 2.0, captcha.rows / 2.0);
  55.  
  56.             double r = (signCenter.x < captchaCenter.x ? -1 : 1) * cv::norm(captchaCenter - signCenter);
  57.  
  58.             // флаг, свидетельствующий о том, что эта цифра в капче уже была найдена
  59.             bool thisDigitExists = false;
  60.  
  61.             // пробежимся по всем найденным цифрам
  62.             for (DigitPos &digitPos: foundDigits) {
  63.                 // если найдена такая цифра
  64.                 if (digitPos.first == curDigit) {
  65.                     // считаем среднюю дистанцию
  66.                     double averageDist = 0.0;
  67.                     for (double dist: digitPos.second) {
  68.                         averageDist += dist;
  69.                     }
  70.                     averageDist /= digitPos.second.size();
  71.                     averageDist = qAbs(averageDist - r);
  72.  
  73.                     // точка по расстоянию явно из этой группы
  74.                     if (averageDist < 2.0) {
  75.                         // то добавить расстояние в группу - еще усреднится
  76.                         digitPos.second += r;
  77.  
  78.                         // пометить что цифра - уже была найдена ранее
  79.                         thisDigitExists = true;
  80.  
  81.                         // и прервать поиск
  82.                         break;Не нравится мне эта хрень. Но мы же можем написать
  83.                     }
  84.                 }
  85.             }
  86.  
  87.             // если раньше на капче такая цифра не была обнаружена
  88.             if (!thisDigitExists) {
  89.                 // добавить ее
  90.                 foundDigits += qMakePair(curDigit, QVector<double>{r});
  91.             }
  92.  
  93.  
  94.             //cv::rectangle(captcha_rotated, {maxLoc, digit.size()}, {0, 255, 0}, 1, cv::LINE_AA);
  95.             //qDebug() << angle << maxVal << r;
  96.         }
  97.  
  98.     };
  99.  
  100.     for (size_t i=0; i<digits.size(); ++i) {
  101.         findDigit(static_cast<Digit>(i), digits[i].digitMat, digits[i].maskMat, digits[i].matchMat);
  102.     }
  103.  
  104.     //auto matchResult = findDigit(digit, mask);
  105.  
  106.  
  107.  
  108.  
  109.  
  110.     //cv::putText(captcha_rotated, QString::number(maxVal, 'f', 2).toStdString(), cv::Point(5, 15), cv::FONT_ITALIC, 0.4, cv::Scalar(0));
  111.  
  112.     // показать капчу на экране
  113. //    cv::imshow("captcha", captcha_rotated);
  114. //    cv::waitKey(200 * 1);
  115. //    cv::destroyWindow("captcha");
  116. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement