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

Author Автор: Роман Чернышов    Опубликовано: 19 июля 2013

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

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

Например, вот так выглядит цифра 2 первого шрифта:

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

Картинка для распознания
Картинка для распознания' /><noscript><img src=Просмотр кода 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;

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

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

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

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

  • Алексей 28.02.2021 в 12:38 пп

    спасибо очень помогло распознать номер с картинки,

    правда пришлось из твоего же кода, сделать сначала определить пикселей чтоб сделать свои цифры, так как у меня картинка была в разы больше по пикселям

    А потом переделать под себя.

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

Автор блога
Чернышов Роман
Роман Чернышов
Веб-разработчик, Full Stack
Senior, Architector
PHP, JavaScript, Python, HTML 5, CSS 3, MySQL, Bash, Linux Admin
Заказать работу
предложить оффер

Последние вопросы
Список вопросов
Последние комментарии
Меню

Archive

Мои проекты
Insurance CMS Love Crm CMS Совместные покупки Мой PHP Framework Хостинг для моих клиентов Лицензии на мой софт и поддержка