Единственный файл кода - класс Main.java принимает на вход один параметр - путь к папке с изображениями. В ответ в консоль печатается результат в виде "имя файла - карты".
Для запуска используется файл run.bat или конфигурация IntelliJ Idea (файлы настроек проекта .idea я сохранила). Запускать нужно именно тот файл, что в компилированной директории out/production, иначе нужно добавлять javac команду компиляции со всеми требуемыми ресурсами.
Для работы программы обязательны файлы:
- settings.properties
- файлы с паттернами в папке sprites
В файле settings.properties параметры цветов (черный яркий, черный затемненный и серый фон) - узнала с помощью System.out.println на соответствующих пикселях. Параметры размеров (верхние левые углы каждой зоны, размеры зон, координаты пустого символа для определения масти) - узнала, открыв файл примера в программе Windows Paint: в левой части статусной строки (под картинкой) показывают координаты курсора.
Файлы паттернов генерировала тем же Main.java, строчкой 108 - сейчас она закомментирована. Создавала паттерны, переносила в папку sprites и вручную переименовывала соответственно.
Алгоритм работы:
- Читаем параметры из файла settings.properties
- Для каждого спрайта (паттерна) создаем матрицу вероятности черного цвета:
- конвертируем спрайт в двумерный массив, где 0 - это белый, а 1 - черный. Это чтобы не заморачиваться с огромными отрицательными числами, которыми BufferedImage кодирует свои цвета
- если текущий цвет пикселя черный, то к вероятности добавляем 1
- если близлежащие соседи черные, то они добавляют к вероятности с коэффициентом 0.5
- если соседи второго круга (отстоящие от текущего пикселя на 2) черные, то они добавляют к вероятности с коэффициентом 0.25
- количество соседей первого и второго кругов посчитала вручную на бумажке - 8 и 16 соответственно. Поэтому суммы вероятностей делим на 8 и 16.
- Пишем матрицы вероятностей в HashMap для удобства последующего использования
- По всем файлам переданной в командной строке директории выделяем рабочую зону в 5 карт
- В каждой карте находим цвет писеля в правом верхнем углу немножко отстоящего от границы. На всех картах эта часть не занята, поэтому здесь мы получим цвет фона карты. Если цвет белый или background_gray из settings.properties, то работаем дальше. Если же другой, значит на выбранной зоне нет карты и просто переходим к области с другой картой.
- Определяем масть карты: если цвет масти черный яркий или затемненный черный (опять же из settings.properties), то это пики или крести, иначе бубны или черви.
- Разница между пиками и крестями: заполнен ли символ между "лепестками" крестей
- Разница между червями и бубнами: заполнен ли символ посередине-вверху
- Далее определяем значение карты. Сначала если пустой символ (см. п.5) серый, то осветляем картинку. Если этого не сделать, то преобразование в черно-белую картинку даст или черный квадрат, или очень уж жирненькие цифры, отчего распознавание дает неверный результат.
- Преобразовываем зону face (значение карты) в черно-белый растр, здесь же можно сохранить этот растр в файл, если мы только создаем файлы паттернов.
- По всем готовым паттернам сравниваем: если текущий пиксель черный, то к коэффициенту соответствия (matchKoeff) добавляем вероятность из матрицы вероятностей (см. п.2), если же белый/серый, то обратную вероятность.
- Паттерн с наибольшим коэффициентом соответствия выигрывает
- Масть я хранила полными названиями "clubs", "spades", "hearts", "diamonds", потому что иначе я в них путаюсь на этапе отладки. Для вывода на экран берем только первую букву масти
- Выводим результат в консоль
В этом алгоритме я не заморачивалась с обработкой исключений, потому что и так понятно, если путь к папке с картинками неправильный, или файлы спрайтов отсутствуют, то все равно вся программа посыплется. Так что вместо бесконечных try-catch поставила "throws IOException"
Если остались какие-либо вопросы по программе, пишите на [email protected]