<?php
class POGO_imageAnalyzer {
var $debug = true;
var $image = false;
var $image_path = false;
/**
*
* @param type $url
*/
function __construct( $url ) {
require_once( get_stylesheet_directory() . '/vendor/autoload.php');
$this->tesseract = new Ddeboer\Tesseract\Tesseract();
$this->result = (object) array(
'gym' => false,
'eggLevel' => false,
'pokemon' => false,
'date' => false,
'error' => false,
);
$this->start = microtime(true);
if( $this->debug ) $this->_log('========== Début du traitement '.$url.' ==========');
$this->image_url = $url;
$this->_saveImage();
$this->_createImageForBasicIdentification();
if( ( $this->_isRaidAnnounceImg() ) && empty( $this->result->error ) ) {
$this->_createImageForGymSearch();
$this->_createImageForTimeSearch();
if( $this->_isPokemonImg() ) {
$this->_createImageForPokemonsearch();
}
$this->_perform();
}
$this->_close();
}
/**
* =========================================================================
* GENERATES IMAGES & MAIN METHODS
* =========================================================================
*/
private function _log( $text ) {
if( is_array( $text ) ) {
error_log( print_r($text, true) );
} else {
error_log( $text );
}
}
/**
*
*/
private function _saveImage() {
$ext = pathinfo($this->image_url, PATHINFO_EXTENSION);
if( $this->debug ) $this->_log('Img extension : ' . $ext);
$this->filename = 'capture-' . time();
$this->image_path = get_stylesheet_directory() . '/captures/' . $this->filename . '.jpg';
if( $ext == "jpg" || $ext == "jpeg" ) {
$this->image = imagecreatefromjpeg($this->image_url);
} elseif( $ext == "png" ) {
$this->image = imagecreatefrompng($this->image_url);
} else {
$this->result->error = 'File type not allowed';
}
imagejpeg($this->image, $this->image_path);
$size = getimagesize($this->image_path);
$this->image_height = $size[1];
$this->image_width = $size[0];
if( $this->_getImageRatio() >= 1 ) {
$this->result->error = 'Le ratio de l\'image ne semble pas correct';
}
}
/**
*
*/
private function _createImageForBasicIdentification() {
if( !$this->image_path ) {
return false;
}
$this->image_basic = imagecreatefromjpeg($this->image_path);
$this->image_basic_path = get_stylesheet_directory() . '/captures/' . $this->filename . '-basic.jpg';
imagefilter($this->image_basic, IMG_FILTER_PIXELATE, $this->image_width / 2 );
imagejpeg($this->image_basic, $this->image_basic_path);
imagedestroy($this->image_basic);
}
/**
*
*/
private function _createImageForGymSearch() {
$this->image_gym = imagecrop($this->image, ['x' => $this->image_width * 0.2037, 'y' => $this->image_height * 0.03125, 'width' => $this->image_width - $this->image_width * 0.2037, 'height' => $this->image_height * 0.1]);
$this->image_gym_path = get_stylesheet_directory() . '/captures/' . $this->filename . '-gym.jpg';
imagejpeg($this->image_gym, $this->image_gym_path);
imagedestroy($this->image_gym);
}
/**
*
*/
private function _createImageForPokemonsearch() {
$this->image_pokemon = imagecrop($this->image, ['x' => 0, 'y' => $this->image_height * 0.2474, 'width' => $this->image_width, 'height' => $this->image_height * 0.072916]);
$this->image_pokemon_path = get_stylesheet_directory() . '/captures/' . $this->filename . '-pokemon.jpg';
imagejpeg($this->image_pokemon, $this->image_pokemon_path);
imagedestroy($this->image_pokemon);
}
/**
*
*/
private function _createImageForTimeSearch() {
$margin_top = $this->image_height * 0.185;
if( $this->_hasAndroidNavigationBar() ) {
$margin_top -= ($this->image_height * 0.075) * 0.3;
}
$this->image_time = imagecrop($this->image, ['x' => $this->image_width * 0.3, 'y' => $margin_top, 'width' => $this->image_width * 0.4, 'height' => $this->image_height * 0.0625]);
$this->image_time_path = get_stylesheet_directory() . '/captures/' . $this->filename . '-time.jpg';
imagefilter($this->image_time, IMG_FILTER_BRIGHTNESS, -130 );
imagefilter($this->image_time, IMG_FILTER_GRAYSCALE );
imagefilter($this->image_time, IMG_FILTER_CONTRAST, -70 );
imagejpeg($this->image_time, $this->image_time_path);
imagedestroy($this->image_time);
}
/**
*
* @return type
*/
private function _perform() {
$this->result->gym = $this->_getGym();
$this->result->eggLevel = $this->_getEggLevel();
$this->result->date = $this->_getTime();
if( $this->image_pokemon_path ) {
$this->result->pokemon = $this->_getPokemon();
}
}
/**
*
*/
private function _close() {
imagedestroy($this->image);
$time_elapsed_secs = microtime(true) - $this->start;
if( $this->debug ) $this->_log('========== Fin du traitement '.$this->image_url.' ('.round($time_elapsed_secs, 3).'s) ==========');
}
/**
* =========================================================================
* EXTRACT DATA METHODS
* =========================================================================
*/
private function _isRaidAnnounceImg() {
if( $this->debug ) $this->_log('---------- Check if image is Raid Announce ----------');
$image = imagecreatefromjpeg($this->image_basic_path);
$rgb = imagecolorsforindex($image, imagecolorat($image, $this->image_width * 0.1, $this->image_height *0.7 ));
if( $this->debug ) $this->_log('Test pixel at x:'.$this->image_width * 0.1.' & y:'.$this->image_height *0.7);
if(
( $rgb['red'] > 40 && $rgb['red'] < 85 )
&& ( $rgb['green'] > 95 && $rgb['green'] < 160 )
&& ( $rgb['blue'] > 55 && $rgb['blue'] < 90 )
) {
if( $this->debug ) $this->_log('Img seems to be a raid announce');
return true;
}
$result = $this->_isPokemonImg();
if( $result == true ) {
if( $this->debug ) $this->_log('Img seems to be a raid announce');
return true;
}
if( $this->debug ) $this->_log('Img does not seem to be a raid announce');
$this->result->error = 'Img does not seem to be a raid announce';
return false;
}
/**
*
* @return type
*/
private function _getGym() {
if( $this->debug ) $this->_log('---------- Gym Extraction ----------');
//Step 1 - basic OCR
if( $this->debug ) $this->_log('First attempt (config 1)' );
$return = $this->tesseract->recognize( $this->image_gym_path, null, 7 );
if( $this->debug ) $this->_log('OCR value : ' . $return );
if( $this->_looksValidGymName($return) ) {
if( $this->debug ) $this->_log('Value looks valid gym name' );
$text = strtolower( POGO_helpers::deleteAccents( $return ) );
if( $this->debug ) $this->_log('Searched text : ' . $text );
$result = $this->_findExstingGym($text);
if( $result ) {
if( $this->debug ) $this->_log('Gym finded in database : ' . $result->getNameFr() );
return $result;
}
if( $this->debug ) $this->_log('Nothing found in database :(' );
}
if( $this->debug ) $this->_log('Value does not seem to be a correct gym name' );
//Step 2
if( $this->debug ) $this->_log('New attempt with other image settings (config 2)' );
$image = imagecreatefromjpeg($this->image_gym_path);
imagefilter($image, IMG_FILTER_EMBOSS );
$this->image_gym_path2 = get_stylesheet_directory() . '/captures/' . $this->filename . '-gym-2.jpg';
imagejpeg($image, $this->image_gym_path2);
imagedestroy($image);
$return = $this->tesseract->recognize( $this->image_gym_path2, null, 7 );
if( $this->debug ) $this->_log('OCR value : ' . $return );
if( $this->_looksValidGymName($return) ) {
if( $this->debug ) $this->_log('Value looks valid gym name' );
$text = strtolower( POGO_helpers::deleteAccents( $return ) );
if( $this->debug ) $this->_log('Searched text : ' . $text );
$result = $this->_findExstingGym($text);
if( $result ) {
if( $this->debug ) $this->_log('Gym finded in database : ' . $result->getNameFr() );
return $result;
}
if( $this->debug ) $this->_log('Nothing found in database :(' );
}
if( $this->debug ) $this->_log('Value does not seem to be a correct gym name' );
//Step 3
if( $this->debug ) $this->_log('New attempt with other image settings (config 3)' );
$image = imagecreatefromjpeg($this->image_gym_path);
imagefilter($image, IMG_FILTER_BRIGHTNESS, -130 );
imagefilter($image, IMG_FILTER_GRAYSCALE );
imagefilter($image, IMG_FILTER_CONTRAST, -70 );
//imagefilter($image, IMG_FILTER_EMBOSS );
$this->image_gym_path3 = get_stylesheet_directory() . '/captures/' . $this->filename . '-gym-3.jpg';
imagejpeg($image, $this->image_gym_path3);
imagedestroy($image);
$return = (new thiagoalessio\TesseractOCR\TesseractOCR($this->image_gym_path3))
->whitelist( $this->_getOcrWhiteList() )
->psm(7)
->run();
if( $this->debug ) $this->_log('OCR value : ' . $return );
if( $this->_looksValidGymName($return) ) {
if( $this->debug ) $this->_log('Value looks valid gym name' );
$text = strtolower( POGO_helpers::deleteAccents( $return ) );
if( $this->debug ) $this->_log('Searched text : ' . $text );
$result = $this->_findExstingGym($text);
if( $result ) {
if( $this->debug ) $this->_log('Gym finded in database : ' . $result->getNameFr() );
return $result;
}
if( $this->debug ) $this->_log('Nothing found in database :(' );
}
if( $this->debug ) $this->_log('Value does not seem to be a correct gym name' );
//Step 4
if( $this->debug ) $this->_log('New attempt with other image settings (config 4)' );
$size = getimagesize($this->image_gym_path);
$height = $size[1];
$width = $size[0];
$image = imagecreatefromjpeg($this->image_gym_path);
$image_to_save = imagecreatefromjpeg($this->image_gym_path);
$this->image_gym_path4 = get_stylesheet_directory() . '/captures/' . $this->filename . '-gym-4.jpg';
// start from the top-left pixel and keep looping until we have the desired effect
for($y = 0;$y < $height;$y += 1) {
for($x = 0;$x < $width;$x += 1) {
// get the color for current pixel
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y));
// get the closest color from palette
if( $rgb['red'] > 210 && $rgb['blue'] > 210 && $rgb['green'] > 210 ) {
$color = imagecolorallocate ( $image , $rgb['red'] , $rgb['green'] , $rgb['blue'] );
imagefilledrectangle($image, $x-1, $y-1, $x, $y, $color);
} else {
$color = imagecolorallocate ( $image , 0 , 0 , 0 );
imagefilledrectangle($image, $x-1, $y-1, $x, $y, $color);
}
}
}
imagejpeg($image, $this->image_gym_path4);
imagedestroy($image);
$return = (new thiagoalessio\TesseractOCR\TesseractOCR($this->image_gym_path3))
->whitelist( $this->_getOcrWhiteList() )
->psm(6)
->run();
if( $this->debug ) $this->_log('OCR value : ' . $return );
if( $this->_looksValidGymName($return) ) {
if( $this->debug ) $this->_log('Value looks valid gym name' );
$text = strtolower( POGO_helpers::deleteAccents( $return ) );
if( $this->debug ) $this->_log('Searched text : ' . $text );
$result = $this->_findExstingGym($text);
if( $result ) {
if( $this->debug ) $this->_log('Gym finded in database : ' . $result );
return $result;
}
if( $this->debug ) $this->_log('Nothing found in database :(' );
}
if( $this->debug ) $this->_log('Value does not seem to be a correct gym name' );
return false;
}
/**
*
* @return boolean
*/
private function _getTime() {
if( $this->debug ) $this->_log('---------- Date Extraction ----------');
//$time = $this->tesseract->recognize( $this->image_time_path, null, 7 );
$time = (new thiagoalessio\TesseractOCR\TesseractOCR($this->image_time_path))
->psm(7)
->run();
if( $this->debug ) $this->_log( 'OCR Value : ' . $time );
$time = preg_replace('/[^0-9]/', '',$time);
if( $this->debug ) $this->_log( 'Sanitized value : ' . $time );
if( !empty($time) ) {
$minutes = substr($time, 1, 2 );
if( $this->debug ) $this->_log( 'Minutes : ' . $minutes );
$date = new DateTime();
$date->setTimezone(new DateTimeZone('Europe/Paris'));
$date->modify('+'.$minutes.' minutes');
return $date->format('Y-m-d H:i:s');
}
return false;
}
/**
*
* @return boolean
*/
private function _getPokemon() {
if( $this->debug ) $this->_log('---------- Pokemon Extraction ----------');
$size = getimagesize($this->image_pokemon_path);
$height = $size[1];
$width = $size[0];
$image = imagecreatefromjpeg($this->image_pokemon_path);
$image_to_save = imagecreatefromjpeg($this->image_pokemon_path);
$this->image_pokemon_path2 = get_stylesheet_directory() . '/captures/' . $this->filename . '-pokemon-2.jpg';
// start from the top-left pixel and keep looping until we have the desired effect
for($y = 0;$y < $height;$y += 1) {
for($x = 0;$x < $width;$x += 1) {
// get the color for current pixel
$rgb = imagecolorsforindex($image, imagecolorat($image, $x, $y));
// get the closest color from palette
if( $rgb['red'] > 250 && $rgb['blue'] > 250 && $rgb['green'] > 250 ) {
$color = imagecolorallocate ( $image , $rgb['red'] , $rgb['green'] , $rgb['blue'] );
imagefilledrectangle($image, $x-1, $y-1, $x, $y, $color);
} else {
$color = imagecolorallocate ( $image , 0 , 0 , 0 );
imagefilledrectangle($image, $x-1, $y-1, $x, $y, $color);
}
}
}
imagejpeg($image, $this->image_pokemon_path2);
imagedestroy($image);
error_log( get_template_directory() . '/ocr/user-words.txt' );
$pokemon = (new thiagoalessio\TesseractOCR\TesseractOCR($this->image_pokemon_path2))
->whitelist( range('a','z'), 'é' )
//->lang('en')
//->userWords( get_template_directory() . '/ocr/en.user-words')
->config('load_system_dawg', 'F')
->config('load_freq_dawg', 'F')
->config('user_words_file', get_template_directory() . '/ocr/en.user-words' )
->config('language_model_penalty_non_dict_word', 0.9)
->psm(7)
->run();
$this->_SearchMatchingPokemon();
if( $this->debug ) $this->_log($pokemon);
return $pokemon;
}
/**
*
* @return int
*/
private function _getEggLevel() {
$egg_level = 0;
if( $this->debug ) $this->_log('---------- Egg level Extraction ----------');
foreach( $this->_getEggLevelCoordinates() as $coor ) {
if( $this->debug ) $this->_log('Test pixel at x:'.$coor[0].' & y:'.$coor[1]);
$rgb = imagecolorsforindex($this->image, imagecolorat($this->image, $coor[0], $coor[1] ));
if( $this->_isEgglevelColor($rgb) ) {
$egg_level += 1;
if( $this->debug ) $this->_log('Pixel matches');
} else {
if( $this->debug ) $this->_log('Pixel does not match');
}
}
if( $this->debug ) $this->_log($egg_level . ' matching pixels');
return $egg_level;
}
/**
* =========================================================================
* HELPER METHODS
* =========================================================================
*/
/*
function optimizeImageForGymSearch() {
$size = getimagesize($this->image_path);
$height = $size[1];
$width = $size[0];
$this->image_gym = imagecrop($this->image, ['x' => 250, 'y' => 80, 'width' => 800, 'height' => 200]);
$this->image_gym_path = get_stylesheet_directory() . '/captures/' . $this->filename . '-gym.jpg';
// start from the top-left pixel and keep looping until we have the desired effect
for($y = 0;$y < $height;$y += 1) {
for($x = 0;$x < $width;$x += 1) {
// get the color for current pixel
$rgb = imagecolorsforindex($this->image_gym, imagecolorat($this->image, $x, $y));
// get the closest color from palette
if( $rgb['red'] > 220 && $rgb['blue'] > 220 && $rgb['green'] > 220 ) {
$color = imagecolorallocate ( $this->image_gym , $rgb['red'] , $rgb['green'] , $rgb['blue'] );
imagefilledrectangle($this->image_gym, $x-1, $y-1, $x, $y, $color);
} else {
$color = imagecolorallocate ( $this->image_gym , 0 , 0 , 0 );
imagefilledrectangle($this->image_gym, $x-1, $y-1, $x, $y, $color);
}
}
}
imagejpeg($this->image_gym, $this->image_gym_path);
imagedestroy($this->image_gym);
}
*/
private function _ocrGymName( $image_path ) {
}
/**
*
* @return type
*/
private function _getEggLevelCoordinates() {
/*return array(
array( 328, 570 ),
array( 434, 570 ),
array( 487, 570 ),
array( 539, 570 ),
array( 592, 570 ),
array( 645, 570 ),
array( 751, 570 ),
);*/
$margin_top = $this->image_height * 0.296875;
if( $this->debug ) $this->_log( 'Margin top : ' . $margin_top );
if( $this->_hasAndroidNavigationBar() ) {
$margin_top -= ($this->image_height * 0.075) * 0.25;
if( $this->debug ) $this->_log('Img has Android navigation bar');
if( $this->debug ) $this->_log( 'Ajusted margin top : ' . $margin_top );
}
$return = array(
array( $this->image_width * 0.3037, $margin_top ),
array( $this->image_width * 0.4019, $margin_top ),
array( $this->image_width * 0.4509, $margin_top ),
array( $this->image_width * 0.4990, $margin_top ),
array( $this->image_width * 0.5481, $margin_top ),
array( $this->image_width * 0.5972, $margin_top ),
array( $this->image_width * 0.6954, $margin_top ),
);
return $return;
}
/**
*
* @param type $rgb
* @return boolean
*/
private function _isEgglevelColor( $rgb ) {
if( $rgb['red'] > 240 && $rgb['green'] > 240 && $rgb['blue'] > 240 ) {
return true;
}
return false;
}
/**
*
* @param type $string
* @return type
*/
private function _sanitizeTime( $string ) {
$string = str_replace(array(' ', '('), '', $string);
return $string;
}
/**
*
* @param type $string
* @return boolean
*/
private function _looksValidGymName( $string ) {
if( empty( $string ) ) return false;
if( strlen($string) < 5 ) return false;
return true;
}
/**
*
* @return type
*/
private function _getImageRatio() {
return $this->image_width / $this->image_height;
}
/**
*
* @return boolean
*/
private function _hasAndroidNavigationBar() {
$rgb = imagecolorsforindex($this->image, imagecolorat($this->image, $this->image_width - 1, $this->image_height - 1 ));
if( $rgb['red'] == 0 && $rgb['green'] == 0 && $rgb['blue'] == 0 ) {
return true;
}
return false;
}
/**
*
* @param type $text
* @return boolean|\POGO_gym
*/
private function _findExstingGym( $text ) {
foreach (POGO_helpers::getGyms() as $gym_id) {
$gym = new POGO_gym($gym_id);
foreach( $gym->getSearhPatterns() as $pattern ) {
if( strstr($text, $pattern) ) {
return $gym;
}
}
}
return false;
}
/**
*
* @return string
*/
private function _getOcrWhiteList() {
return 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMEOPQRSTUVWXYZ;:!-éèêà';
}
/**
*
* @return boolean
*/
private function _isPokemonImg() {
//if( $this->debug ) $this->_log('---------- Check if announce if Egg or Pokemon ----------');
//if( $this->debug ) $this->_log('Test pixel at x:'.$this->image_width * 0.92592.' & y:'.$this->image_height* 0.611979);
$rgb = imagecolorsforindex($this->image, imagecolorat($this->image, $this->image_width * 0.92592 , $this->image_height* 0.611979 ));
if( $rgb['red'] == 255 && $rgb['green'] == 120 && $rgb['blue'] == 55 ) {
//if( $this->debug ) $this->_log('Img seems to include a pokemon');
return true;
}
//if( $this->debug ) $this->_log('Img seems to include an egg');
return false;
}
private function _SearchMatchingPokemon( $pokemon ) {
$bosses = POGO_helpers::getRaidBosses();
foreach( $bosses as $boss_id ) {
$boss = new POGO_pokemon($boss_id);
}
}
}