killer8080
Как дела?)
Цитата (Zzepish @ 9.03.2013 - 23:46) |
killer8080 Как дела?) |
<?php
$file = //'1.jpg';
"IMG_0847.JPG";
$level_trash_hold = 50;
?>
<style type="text/css">
img {
margin: 3px;
border: 1px solid red;
/*width: 300px;*/
}
</style>
<img src="<?=$file?>" />
<?php
$size = getimagesize($file);
$im = imagecreatefromjpeg($file);
imagefilter($im, IMG_FILTER_GRAYSCALE);
imagefilter($im, IMG_FILTER_CONTRAST, -50);
imagejpeg($im, 'test.jpg');
?>
<img src="test.jpg?<?=time()?>" />
<?php
$black_level = 255;
// определяем минимальный уровень черного в картинке
for($y = 0; $y < $size[1]; $y++)
for($x = 0; $x < $size[0]; $x++)
$black_level = min( (imagecolorat($im, $x, $y) & 0xff), $black_level);
$matrix = array();
$black_level += $level_trash_hold;
// строим матрицу изображения, все что выше порога ноль
// что ниже - единица (соответствует черным линиям)
for($y = 0; $y < $size[1]; $y++)
for($x = 0; $x < $size[0]; $x++)
$matrix[$y][$x] = (imagecolorat($im, $x, $y) & 0xff) > $black_level ? 0 : 1;
imagedestroy($im);
/*
* тут пытался отфильтровать мусор, не эффективно :(
*
foreach($matrix as $row){
$row_count = count($row) - 1;
foreach ($row as $i => &$pixel)
if($i > 0 && $i < $row_count
&& $pixel == 1 && $row[$i - 1] == 0
&& $row[$i + 1] == 1 && $row[$i + 2] == 0
)
$pixel = $row[$i + 1] = 0;
}
*/
/*
* тут строим визуализацию матрицы, для контроля
*/
$im = imagecreatetruecolor($size[0], $size[1]);
$black = imagecolorallocate($im, 0, 0, 0);
$white = imagecolorallocate($im, 255, 255, 255);
foreach($matrix as $y => $row)
foreach($row as $x => $pixel)
imagesetpixel ($im, $x, $y, ($pixel ? $black : $white));
imagejpeg($im, 'test2.jpg');
imagedestroy($im);
?>
<img src="test2.jpg?<?=time()?>" />
<?php
/*
* определяем частоты переходов для каждой строки матрицы
* получаем массив где ключ = номер строки матрицы
* значение = частота переходов
*/
$freq_count = array();
foreach($matrix as $y => $row){
$prev = null;
$freq_count[$y] = 0;
foreach($row as $x => $pixel){
if($prev !== null && $prev ^ $pixel)
$freq_count[$y]++;
$prev = $pixel;
}
}
/*
* подсчитываем вертикальные линии штрихкода
* получаем массив где ключ = частота
* значение = количество строк матрицы с частотой соответствующей ключу
*/
$lines_counter = array();
foreach ($freq_count as $n)
$lines_counter[$n] = isset($lines_counter[$n]) ? $lines_counter[$n] + 1 : 1;
/*
* определяем какая частота встречается чаще всего
* она будет соответствовать числу переходов белое/черно черное/белое
* в линиях штрихкода
*/
$total_lines_freq = array_search(max($lines_counter), $lines_counter);
/*
* получаем число линий в штрихкоде (белых и черных)
*/
$total_lines = round($total_lines_freq / 2);
/*
* фильтруем матрицу, удаляем строки не содержащие штрихкод или с помехами
*/
foreach ($freq_count as $i => $count)
if($count != $total_lines_freq)
unset($matrix[$i]);
/*
* обрезаем матрицу с верху и с низу на 10 пикселей (строк) т.к. на границах
* большая неравномерность ширины линий
*/
$matrix = array_slice($matrix, 10, count($matrix) - 20);
/*
* строим двумерный массив, каждый элемент массива соответствует линии штрихкода
* и содержит дочерний массив ширины линии в пикселях, по строкам
*/
$lines = array();
foreach ($matrix as $row){
$i = 0;
$prev = null;
$count = 0;
foreach ($row as $pixel){
if($prev === null && !$pixel)
continue;
if($prev === null)
$prev = 1;
if($prev == $pixel){
$count++;
}
else {
$lines[$i++] []= $count;
$count = 1;
$prev = $pixel;
}
}
}
/*
* преобразуем массив линий, каждый элемент массива соответствуют определенной
* линии штрихкода, значение преобразовывается из массива в число, соответствующее
* наиболее часто встречающемся значению ширины для этой линии
*/
foreach ($lines as &$line) {
$counter = array();
foreach ($line as $count)
$counter[$count] = isset($counter[$count]) ? $counter[$count] + 1 : 1;
$line = array_search(max($counter), $counter);
}
unset($line);
/*
* строим изображение по матрице для визуального контроля
*/
$im = imagecreatetruecolor($size[0], count($matrix));
foreach($matrix as $y => $row)
foreach($row as $x => $pixel)
imagesetpixel ($im, $x, $y, ($pixel ? $black : $white));
imagejpeg($im, 'test3.jpg');
imagedestroy($im);
?>
<img src="test3.jpg?<?=time()?>" />
<?php
/*
* строим изображение из полученного массива линий, для контроля
*/
$im = imagecreatetruecolor(array_sum($lines), 200);
$offset = 0;
foreach($lines as $i => $line){
imagefilledrectangle($im, $offset, 0, $line + $offset, 200, ($i % 2 ? $white : $black));
$offset += $line;
}
imagejpeg($im, 'test4.jpg');
imagedestroy($im);
?>
<img src="test4.jpg?<?=time()?>" />
<?php
/*
* разделяем массив на два, черные и белые линии
*/
$black_lines = $white_lines = array();
foreach($lines as $i => $line){
if($i % 2)
$white_lines []= $line;
else
$black_lines []= $line;
}
/*
* определяем минимальную ширину для черных и белых линий в отдельности
* исходим из того что в коде должна встречаться хотя бы одна комбинация 1010
* минимальную линию берем как ширину одного бита в пикселях
*/
$black_line_width = min($black_lines);
$white_line_width = min($white_lines);
echo '<p>black line width: '.$black_line_width.'<br>'
.'white line width: '.$white_line_width.'</p>';
/*
* общая минимальная ширина линии
*/
$line_width = min($lines);
/*
* строим строку кода
*/
$code = '';
foreach($lines as $i => $line)
$code .= str_pad(
'',
round($line / ($i % 2 ? $white_line_width : $black_line_width)),
$i % 2 ? 0 : 1
);
echo '<p>line width: '.$line_width.' pixels<br>length: '.strlen($code) .' bits<br>code: '.$code.'</p>';
echo '<pre>'.print_r($lines, 1)."\ntotal lines: $total_lines ".'</pre>';
echo max($freq_count), ' ', round(array_sum($freq_count) / count($freq_count)).'<br>';
echo 'black level; '.$black_level.'<br>memory usage: '. memory_get_usage().' bytes';