Казалось бы, причем здесь распознавание текстов?
Как и чем обычно тестируют и автоматизируют
Подобные способы не всегда подходят, например когда пользователь работает с приложением через удаленный рабочий стол, или Web приложение «нашпигованно» сторонними контроллами (ActiveX, Java applets и т. п.).
Очень хорошо данная проблематика описана здесь, а список софта — здесь.
Идея
мы пойдем другим путем ©Маяковский
А что, если сделать снимок экрана, запомнить некоторую область и в качестве проверки распознать текст в этой области. Если в заданной области есть ожидаемый текст, то можно туда кликнуть.
Звучит неплохо, надо пробовать.
И тернистый путь реализации
Для начала необходимо выбрать движок для распознавания текстов или написать его самому. Писать самому — задача нетривиальная, поэтому возьмем что-то готовое и желательно Open Source. Ну что ж, для начала почитаем мануалы.
Есть такое чудо под названием Tesseract OCR. И к нему есть API-обертка на .NET! Звучит просто, но не все так просто: фоткаем, распознаем и… ничего — Tesseract не увидел в нашем снимке текста! Если быть точнее, не увидел на куске снимка.
public static Bitmap GetAreaFromScreen(Rectangle area)
{
var rect = new Rectangle(area.X, area.Y, area.Width, area.Height);
var bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb);
using (var g = Graphics.FromImage(bmp))
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
return bmp;
}
public string RecognizeText(Bitmap source)
{
try
{
using (var page = engine.Process(source, PageSegMode.SingleLine))
{
var text = page.GetText();
var conf = page.GetMeanConfidence();
threshold = conf;
return text;
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
return "";
}
}
Покопавшись немного
Получается, надо сначала сделать:
1. fix DPI (if needed) 300 DPI is minimum
2. fix text size (e.g. 12 pt should be ok)
3. try to fix text lines (deskew and dewarp text)
4. try to fix illumination of image (e.g. no dark part of image
5. binarize and de-noise image
А уже потом пробовать что-то там распознавать!
Тут нам на помощь пришла библиотека AForge.NET. Она, кстати, Open Source, как и Tesseract.
public string RecognizeText(Bitmap source)
{
try
{
var seq = new FiltersSequence();
seq.Add(new ResizeBilinear(source.Width * 2, source.Height * 2));
seq.Add(new Grayscale(0.2126, 0.7152, 0.0722));
seq.Add(new OtsuThreshold());
seq.Add(new Threshold(100));
temp = seq.Apply(source);
using (var page = engine.Process(temp, PageSegMode.SingleLine))
{
var text = page.GetText();
var conf = page.GetMeanConfidence();
threshold = conf;
return text;
}
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
return "";
}
}
Поясню по пунктам:
- DPI — у скриншота DPI норм, нам хватит;
- fix text size — тут зависит от размера шрифта, иногда надо увеличить, иногда сделать потолще или повыше. ResizeBilinear в помощь;
- try to fix text lines — тут зависит от точности выделенной области экрана. Выделяем текст прицельно, стараясь не зацепить «артефакты» — ручная работа;
- try to fix illumination of image — Grayscale да и все тут!
- binarize and de-noise image — бинаризуем и дешумизуем (!) OtsuThreshold и Threshold(100).
Теперь гораздо лучше.
Ядро программки уже готово, осталось
В итоге, соединяя все вместе, получился и простенький дизайнер тестов и простенький проигрыватель.
А теперь скриншот из которого ничего непонятно и видео без звука
Это скриншот той части программки, которую я называю Тест дизайнер!
А это видео работы программки — записываем простенький тест и запускаем его!
Вот собственно и всё!
Ах да!
Исходники, ТТХ и прочее
Исходники проекта: github.com/skaeff/miranda-tester
Собранная версия с английским и русским словарями: github.com/skaeff/miranda-tester/blob/master/miranda-tester-net40-compiled.7z
Краткое резюме:
- Tesseract OCR github.com/tesseract-ocr/tesseract — библиотека оптического распознавания текстов;
- AForge.Net www.aforgenet.com — библиотека обработки изображений;
- Немного логики, написанной на C#.
И да, для скриншота нажимаем Shift+Esc.
Комментарии (13)
redmanmale
05.04.2016 15:03Selenium и для десктопа есть, от 2gis.
skaeff
05.04.2016 15:14Это и хорошо. Вот только в софте от 2gis используется UIAutomation Framework, который кстати говоря, не всегда применим, даже к Desktop приложениям.
В статье же я попытался описать совсем другой подход к автоматизации тестирования — не нужно никаких фреймворков, просто PrintScreen + OCR
kmikeru
05.04.2016 17:41+2Но ведь уже давно есть Sikuli, что с ним не так?
skaeff
05.04.2016 17:47Да, Sikuli это классный фреймворк судя по описанию, но там используется другой механизм — матчинг паттернов без распознавания текста. Т. е. «если эта картинка выглядит как шаблон, то кликаем».
Описанный механизм OCR на мой взгляд дает больше свободы — можно брать информацию с экранной формы.
Кстати, template matching неплохо реализован и в AForge.
VanKrock
06.04.2016 07:53В подходе я вижу проблему в том, что элемент UI может поменять свое положение и не всегда понятно, как предсказать, где должен быть элемент, простой пример, вы ищете хаб «Программирование» и он всегда у вас на первом месте, и тут вдруг добавили хаб «Администрирование» и он стал на первом месте, а «Программирование» ушло на второе место и как это обработать, это ошибка интерфейса или придется переделать тест? Сам пользуюсь Coded UI Test для автоматизации тестирования GUI.
skaeff
06.04.2016 08:06Определенно, элементы могут менять положение. В данном случае это лишь добавить шагов проверки «если не здесь, то здесь». В тест придется добавить проверку всех положений или обрабатывать данную ситуацию как-то особенно (используя тот же UIAutomation если это возможно).
Ошибка или не ошибка интерфейса — это вопрос скорее по usability и дизайну. На мой взгляд каждый раз произвольное положение каких-то контроллов — это плохая usability.VanKrock
06.04.2016 19:53Ну допустим вы добавили пост на Хабрахабр и хотите проверить, что он отобразился, но сразу после вашего поста другой тест, который запущен на другом агенте добавил еще один пост, то есть ваш пост стал вторым, вопрос, как вы определите положение вашего поста, ведь высота поста из второго теста может быть любой?
TheGodfather
06.04.2016 19:55+1Вообще для тестирования GUI приложений куда более логично использовать Accessebility технологии, как уже вышеупомянутые MSAA или UI Automation. Т.е. процесс выглядит как «опросить систему и получить список диалогов -> зная ожидаемые контролы на диалоге, определить, какой диалог из этих нам нужен (без всякого распознавания, простой обход деревьев) -> из полученной информации получить информацию о конкретном контроле „Next“ -> послать эвент по нажатию этой кнопки». Да, с таким подходом на линуксе и маке немного посложнее, чем на винде, но все равно применимо. И меня уже долгое время мучает вопрос — почему все пытаются написать свой велосипед, использующий графическое распознавание, нежели использовать Accessebility?
xtraroman
Может где то и нужно оптическое распозравание текста, но не в том примере, который показан в статье. Сайт хабра можно потестить и без этого. Распознавать капчу пробовали?
skaeff
Такой задачи не стояло. Задача именно в автоматизации рутинных действий с GUI приложения со сбором статистики.
mantyr
Tesseract OCR очень плохо распознаёт искажённые тексты, коими чаще всего капча и является. Конечно можно сделать поверх изображения кучу фильтров, выровнять некоторые символы, но попадание будет очень низким. Для таких целей подойдёт что-то более специализированное.
У себя распознаём мульти-язычные pdf с в целом вменяемым качеством снимков страниц и то приходится делать несколько попыток что бы найти в тексте то что нужно на произвольном документе. Чуть что отличное от прямого текста — разметка (порядок) символов превращается в кашу с кучей пробелов. А так в целом хорошая библиотека.