Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "CaptchaApplication.h"
- cv::Mat CaptchaApplication::getCaptcha() {
- // квадрат с капчей посередине, который можно спокойно вращать на хую
- cv::Mat captcha(250, 250, CV_8UC1, cv::Scalar(255));
- // загрузить капчу и захуярить ее посередине
- cv::imread(qPrintable(arguments().at(1)), cv::IMREAD_GRAYSCALE).copyTo(captcha(cv::Rect(35, 85, 180, 80)));
- return captcha;
- }
- cv::Mat CaptchaApplication::getDigit(Digit digit) {
- QString fpath = QString("/home/wolph/captcha/digit_%1.png").arg(digit);
- cv::Mat digitMat = cv::imread(qPrintable(fpath), cv::IMREAD_GRAYSCALE);
- return digitMat;
- }
- std::array<CaptchaApplication::DigitData, 10> CaptchaApplication::getDigits(const cv::Mat &captcha)
- {
- std::array<DigitData, 10> result;
- for (size_t i=0; i<result.size(); ++i) {
- Digit digit = static_cast<Digit>(i);
- QString fpath = QString("/home/wolph/captcha/digit_%1.png").arg(digit);
- result[i].digitMat = cv::imread(qPrintable(fpath), cv::IMREAD_GRAYSCALE);
- result[i].maskMat = cv::Scalar::all(255) - result[i].digitMat;
- result[i].matchMat = cv::Mat(captcha.rows - result[i].digitMat.rows + 1, captcha.cols - result[i].digitMat.cols + 1, CV_32FC1);
- }
- return result;
- }
- void CaptchaApplication::findZero(double angle) {
- // загрузить капчу
- static cv::Mat captcha = getCaptcha();
- static auto digits = getDigits(captcha);
- // матрица поворота на 45 градусов
- cv::Mat rotMat = cv::getRotationMatrix2D(cv::Point2f(124.5, 124.5), angle, 1.0);
- cv::Mat captcha_rotated = captcha.clone();
- cv::warpAffine(captcha, captcha_rotated, rotMat, captcha.size(), cv::INTER_LANCZOS4, cv::BORDER_CONSTANT, cv::Scalar(255));
- auto findDigit = [&captcha_rotated, this](Digit curDigit, cv::Mat &digitMat, cv::Mat &maskMat, cv::Mat &matchMat){
- double maxVal;
- cv::Point maxLoc;
- cv::matchTemplate( captcha_rotated, digitMat, matchMat, CV_TM_CCORR_NORMED, maskMat);
- cv::minMaxLoc(matchMat, NULL, &maxVal, NULL, &maxLoc, cv::Mat() );
- if (maxVal > 0.915) {
- cv::Point2f signCenter(maxLoc.x + digitMat.cols / 2.0, maxLoc.y + digitMat.rows / 2.0);
- cv::Point2f captchaCenter(captcha.cols / 2.0, captcha.rows / 2.0);
- double r = (signCenter.x < captchaCenter.x ? -1 : 1) * cv::norm(captchaCenter - signCenter);
- // флаг, свидетельствующий о том, что эта цифра в капче уже была найдена
- bool thisDigitExists = false;
- // пробежимся по всем найденным цифрам
- for (DigitPos &digitPos: foundDigits) {
- // если найдена такая цифра
- if (digitPos.first == curDigit) {
- // считаем среднюю дистанцию
- double averageDist = 0.0;
- for (double dist: digitPos.second) {
- averageDist += dist;
- }
- averageDist /= digitPos.second.size();
- averageDist = qAbs(averageDist - r);
- // точка по расстоянию явно из этой группы
- if (averageDist < 2.0) {
- // то добавить расстояние в группу - еще усреднится
- digitPos.second += r;
- // пометить что цифра - уже была найдена ранее
- thisDigitExists = true;
- // и прервать поиск
- break;Не нравится мне эта хрень. Но мы же можем написать
- }
- }
- }
- // если раньше на капче такая цифра не была обнаружена
- if (!thisDigitExists) {
- // добавить ее
- foundDigits += qMakePair(curDigit, QVector<double>{r});
- }
- //cv::rectangle(captcha_rotated, {maxLoc, digit.size()}, {0, 255, 0}, 1, cv::LINE_AA);
- //qDebug() << angle << maxVal << r;
- }
- };
- for (size_t i=0; i<digits.size(); ++i) {
- findDigit(static_cast<Digit>(i), digits[i].digitMat, digits[i].maskMat, digits[i].matchMat);
- }
- //auto matchResult = findDigit(digit, mask);
- //cv::putText(captcha_rotated, QString::number(maxVal, 'f', 2).toStdString(), cv::Point(5, 15), cv::FONT_ITALIC, 0.4, cv::Scalar(0));
- // показать капчу на экране
- // cv::imshow("captcha", captcha_rotated);
- // cv::waitKey(200 * 1);
- // cv::destroyWindow("captcha");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement