PHP: распознать цифры, буквы с картинки

Author Роман Чернышов    Category PHP     Tags , Комментариев 0 Дата 19 Июл

capcha1 PHP: распознать цифры, буквы с картинкиПриветствую вас дорогие читатели! В этой небольшой статья я поделюсь с вами своими небольшими наработками, по распознанию цифр и букв, а впрочем и любых других символов с картинки. Наверняка многие из вас задумывались о том, как бы распознать код с capcha в автоматическом режиме. Написать для этого скрипт и творить свои темные делишки;) Мне же предстояла задача, распознать с нескольких тысяч картинок текст и сделать это было нужно с помощью PHP (впрочем инструмент может быть и другим С, C++, delphi и т.д.)

Для начала вкратце расскажу о логике работы нашего скрипта, все достаточно просто и можно разделить на следующие этапы:
1) Загрузка картинки в память
2) Перебор всех пикселей картинки с получением значения цвета пикселя и запись значения в многомерный массив или одномерный линейный массив в зависимости от алгоритма сверки (я использовал второй вариант).
3) Приведение пикселей «шума» на изображение в нулевое значение, чтобы далее не путаться с ним.
4) Сверка элементов массива(матрицы) с эталонным массивом, содержащим значения той или иной буквы символа. В случаи максимального совпадения значений, фиксируем букву — как распознанную.

Например, вот так выглядит цифра 2 первого шрифта:
charsb PHP: распознать цифры, буквы с картинки

Сложность заключается в том, что шрифт в тексте может быть разным, а также разного размера, в результате эталонный массив со значениями должен включать данные и их. Т.е. основная работа сводится к подготовке именно такого эталонного массива со значениями всех символов, с разным шрифтом и размером.

Картинка для распознания
10845phone PHP: распознать цифры, буквы с картинки

Код скрипта выглядит следующим образом, (в листинге присутствует много лишнего кода, для вывода результатов в браузер, надеюсь в процессе разбора вам будет все понятно)

// эталонные маски, цифры от 0 до 9
$mask=array(
 
0 => array(0 => '1',1 => '1',2 => '1',3 => '1',4 => '1',5 => '1',6 => '1',7 => '1',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '1',13 => '1',14 => '0',15 => '0',16 => '1',17 => '1',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '0',24 => '0',25 => '0',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '0',34 => '0',35 => '0',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '0',45 => '0',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '1',52 => '1',53 => '1',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '1'),
1 => array(
	0 => '0',1 => '1',2 => '1',3 => '1',4 => '0',5 => '0',6 => '0',7 => '0',8 => '0',9 => '0',
	10 => '1',11 => '1',12 => '1',13 => '0',14 => '0',15 => '0',16 => '0',17 => '0',18 => '0',19 => '0',
	20 => '1',21 => '1',22 => '1',23 => '1',24 => '1',25 => '1',26 => '1',27 => '1',28 => '1',29 => '1'),
2 => array(0 => '1',1 => '1',2 => '0',3 => '0',4 => '0',5 => '0',6 => '0',7 => '0',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '0',13 => '0',14 => '0',15 => '0',16 => '0',17 => '1',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '0',24 => '0',25 => '0',26 => '1',27 => '1',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '0',34 => '0',35 => '1',36 => '1',37 => '1',38 => '0',39 => '1',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '1',45 => '1',46 => '1',47 => '0',48 => '0',49 => '1',
	50 => '1',51 => '1',52 => '1',53 => '1',54 => '1',55 => '1',56 => '0',57 => '0',58 => '0',59 => '1'),
3 => array(0 => '1',1 => '1',2 => '0',3 => '0',4 => '0',5 => '0',6 => '0',7 => '0',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '0',13 => '0',14 => '0',15 => '0',16 => '0',17 => '0',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '0',24 => '1',25 => '0',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '1',34 => '1',35 => '0',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '1',52 => '1',53 => '1',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '1'),
4 => array(
	0 => '0',1 => '0',2 => '0',3 => '0',4 => '0',5 => '0',6 => '1',7 => '1',8 => '0',9 => '0',
	10 => '0',11 => '0',12 => '0',13 => '0',14 => '1',15 => '1',16 => '1',17 => '1',18 => '0',19 => '0',
	20 => '0',21 => '0',22 => '1',23 => '1',24 => '1',25 => '1',26 => '0',27 => '1',28 => '0',29 => '0',
	30 => '1',31 => '1',32 => '1',33 => '1',34 => '0',35 => '0',36 => '0',37 => '1',38 => '0',39 => '0',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '0',51 => '0',52 => '0',53 => '0',54 => '0',55 => '0',56 => '0',57 => '1',58 => '0',59 => '0'),
5 => array(0 => '1',1 => '1',2 => '1',3 => '1',4 => '1',5 => '1',6 => '0',7 => '0',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '1',13 => '1',14 => '1',15 => '1',16 => '0',17 => '0',18 => '1',19 => '1',
	20 => '1',21 => '0',22 => '0',23 => '0',24 => '1',25 => '1',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '0',32 => '0',33 => '0',34 => '1',35 => '1',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '0',42 => '0',43 => '0',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '0',52 => '0',53 => '0',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '1'),
6 => array(0 => '1',1 => '1',2 => '1',3 => '1',4 => '1',5 => '1',6 => '1',7 => '1',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '1',13 => '1',14 => '1',15 => '1',16 => '1',17 => '0',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '0',24 => '1',25 => '1',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '0',34 => '1',35 => '1',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '1',42 => '0',43 => '0',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '1',52 => '0',53 => '0',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '1'),
7 => array(0 => '1',1 => '0',2 => '0',3 => '0',4 => '0',5 => '0',6 => '0',7 => '0',8 => '0',9 => '0',
	10 => '1',11 => '0',12 => '0',13 => '0',14 => '0',15 => '1',16 => '1',17 => '1',18 => '1',19 => '1',
	20 => '1',21 => '0',22 => '0',23 => '1',24 => '1',25 => '1',26 => '1',27 => '1',28 => '1',29 => '1',
	30 => '1',31 => '0',32 => '1',33 => '1',34 => '1',35 => '1',36 => '0',37 => '0',38 => '0',39 => '0',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '0',45 => '0',46 => '0',47 => '0',48 => '0',49 => '0',
	50 => '1',51 => '1',52 => '0',53 => '0',54 => '0',55 => '0',56 => '0',57 => '0',58 => '0',59 => '0'),
8 => array(0 => '1',1 => '1',2 => '1',3 => '1',4 => '1',5 => '1',6 => '1',7 => '1',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '1',13 => '1',14 => '1',15 => '1',16 => '1',17 => '0',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '1',24 => '1',25 => '1',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '1',34 => '1',35 => '1',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '1',52 => '1',53 => '1',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '1'),
9 => array(
	0 => '1',1 => '1',2 => '1',3 => '1',4 => '1',5 => '1',6 => '0',7 => '0',8 => '1',9 => '1',
	10 => '1',11 => '1',12 => '0',13 => '1',14 => '1',15 => '1',16 => '0',17 => '0',18 => '1',19 => '1',
	20 => '1',21 => '1',22 => '0',23 => '0',24 => '1',25 => '1',26 => '0',27 => '0',28 => '1',29 => '1',
	30 => '1',31 => '1',32 => '0',33 => '0',34 => '1',35 => '1',36 => '0',37 => '0',38 => '1',39 => '1',
	40 => '1',41 => '1',42 => '1',43 => '1',44 => '1',45 => '1',46 => '1',47 => '1',48 => '1',49 => '1',
	50 => '1',51 => '1',52 => '1',53 => '1',54 => '1',55 => '1',56 => '1',57 => '1',58 => '1',59 => '0')
);
 
echo '<h2>Загрузка значений пикселей в массив:</h2>';
 
$images = 'image.png';//
$img = imagecreatefrompng($images);
$size = getimagesize($images);
 
$w= $size[0];//x
$h= $size[1];//y
 
$a=0;$arrnum=array();$ret=array();
echo '<table><tr><td>';
 
for($i=0;$i<$w;$i++){
   $a++;
   $ret=array();
   $b=0;
	for($d=3;$d<($h-2);$d++){ //минус 3 px сверху, минус 2px снизу
			//запись в масив каждой точки ее значения
	$pix=imagecolorat($img,$i,$d);
	if($pix==16777215)$ret[]=0; else {$ret[]=1;$b=1;} //белый фон записываем как 0, все остальные пиксели как 1
	}
 
   if($b==1) { 
	$arrnum[]=$ret;
 
	$t=0;$cnr=0;
	foreach($ret as $r) {// для наглядности выводим значения полученного массива в браузер
		$t++;
		echo "$r<br/>";
		if($t==10) {echo '</td><td>';$t=0;}
		$cnr++;
	}
   }
}
echo '</td></tr></table>';
 
echo '<h2>Процесс распознования:</h2>';
$out='';$nullarr=array();
foreach($arrnum as $ar) {
 
	foreach($ar as $it) {	
		$nullarr[]=$it;
	}
 
	foreach($mask as $key => $mk) {	
		if(count($nullarr)==count($mk)) {
			$i=0;$pohoj=0;
			foreach($nullarr as $nit) {
				if($nit==$mk[$i])$pohoj++;
				$i++;
			}
 
			$cnm=count($nullarr);//просто для вывода ниже, для наглядного отображения
			if($pohoj==count($mk)||($pohoj>count($mk)-3 and $pohoj<count($mk)+3)){$out.=$key;$nullarr=array();}
			echo 'count col:'.$cnm.' | test num:'.$key.' | sucess: '.$pohoj.' | out: '.$out.'<br>';
			if(count($nullarr)==0)echo '-------<br/>';
		}
	}
 
}
echo '<h2>Результат распознания:</h2>';
echo $out;

Пример работы скрипта можно посмотреть по этой ссылке.

Надеюсь вы почерпнете, что-то новое для себя из этого решения. В данном случае наиболее важен сам принцип и алгоритм реализации распознания текста с картинки, а язык программирования и сам код уже остается за вами.

Также существуют и другие способы распознания текста, например нейронные сети, о которых так много говорят;) Успехов!

Оставить комментарий

Консультации

Консультант Чернышов Р.В. Зайдайте вопрос на любую из тем:
Бесплатно и без регистрации!

Задать вопрос
Все вопросы
Последние вопросы
Поиск по блогу
Категории
Архив
Новое на сайте
Портфолио Все работы


www.detskiy-mir.net
www.detskydoctor.ru
www.betelit.ru
www.all-alliance.ru
www.videogonok.ru
www.carpfishing.by
www.property-greek.com
www.domcons.ru

с 2009 года по сегодняшний день, создано более 300 сайтов...