PHP: распознать цифры, буквы с картинки
Приветствую вас дорогие читатели! В этой небольшой статья я поделюсь с вами своими небольшими наработками, по распознанию цифр и букв, а впрочем и любых других символов с картинки. Наверняка многие из вас задумывались о том, как бы распознать код с capcha в автоматическом режиме. Написать для этого скрипт и творить свои темные делишки;) Мне же предстояла задача, распознать с нескольких тысяч картинок текст и сделать это было нужно с помощью PHP (впрочем инструмент может быть и другим С, C++, delphi и т.д.)
Для начала вкратце расскажу о логике работы нашего скрипта, все достаточно просто и можно разделить на следующие этапы:
1) Загрузка картинки в память
2) Перебор всех пикселей картинки с получением значения цвета пикселя и запись значения в многомерный массив или одномерный линейный массив в зависимости от алгоритма сверки (я использовал второй вариант).
3) Приведение пикселей «шума» на изображение в нулевое значение, чтобы далее не путаться с ним.
4) Сверка элементов массива(матрицы) с эталонным массивом, содержащим значения той или иной буквы символа. В случаи максимального совпадения значений, фиксируем букву — как распознанную.
Например, вот так выглядит цифра 2 первого шрифта:
Сложность заключается в том, что шрифт в тексте может быть разным, а также разного размера, в результате эталонный массив со значениями должен включать данные и их. Т.е. основная работа сводится к подготовке именно такого эталонного массива со значениями всех символов, с разным шрифтом и размером.
Картинка для распознания
Просмотр кода 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; |
Пример работы скрипта можно посмотреть по этой ссылке.
Надеюсь вы почерпнете, что-то новое для себя из этого решения. В данном случае наиболее важен сам принцип и алгоритм реализации распознания текста с картинки, а язык программирования и сам код уже остается за вами.
Также существуют и другие способы распознания текста, например нейронные сети, о которых так много говорят;) Успехов!
спасибо очень помогло распознать номер с картинки,
правда пришлось из твоего же кода, сделать сначала определить пикселей чтоб сделать свои цифры, так как у меня картинка была в разы больше по пикселям
А потом переделать под себя.