Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
 |
[PHP][HELP] Скелетонизация изображения |

21.03.2010, 01:42
|
|
Познающий
Регистрация: 14.03.2009
Сообщений: 86
Провел на форуме: 385811
Репутация:
12
|
|
[PHP][HELP] Скелетонизация изображения
Помогите пожалуйста реализовать бинаризацию и скелетонизацию изображения с помощью GD.
Вот, что нарыл по скелетонизации http://dic.academic.ru/dic.nsf/ruwiki/683052 .
Последний раз редактировалось draliokero; 21.03.2010 в 03:23..
|
|
|

21.03.2010, 03:22
|
|
Познающий
Регистрация: 14.03.2009
Сообщений: 86
Провел на форуме: 385811
Репутация:
12
|
|
Что касается бинаризации: нашел AS сценарий, из него выдернул принцип
Код:
<?php
$im = imagecreatefrompng("php.png");
$width = imagesx($im);
$height = imagesy($im);
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
if (imagecolorat($im, $x , $y) <= 0x7FFFFF) imagesetpixel($im, $x, $y, 0x000000);
else imagesetpixel($im, $x, $y, 0xFFFFFF);
}
}
header('Content-type: image/png');
imagepng($im);
Последний раз редактировалось draliokero; 21.03.2010 в 17:45..
|
|
|

21.03.2010, 14:19
|
|
Reservists Of Antichat - Level 6
Регистрация: 25.04.2008
Сообщений: 827
Провел на форуме: 2769640
Репутация:
1304
|
|
draliokero Для малоцветных изображений (например чернобелых, или где цвета сосредоточены в узкой области) - будет возвращаться пустое изображение, наверное лучше вычислять ЧБ изображение, а потом находить среднюю яркость пиксела и уже относительно этой величины - бинаризировать изображение
__________________
Любая действущая программа устарела.
Создайте систему, которой сможет пользоваться даже дурак ,и только дурак захочет ею пользоваться.
Как правильно задавать вопросы: _http://www.yakimchuk.ru/questions.htm
|
|
|

21.03.2010, 17:48
|
|
Познающий
Регистрация: 14.03.2009
Сообщений: 86
Провел на форуме: 385811
Репутация:
12
|
|
Gifts, сразу в поиск полез, как думаете этим вопрос решится http://bubble.ro/How_to_check_if_an_image_is_grayscale_in_PHP.html ?
На Google Code нашел С++ проект с фильтром скелетонизации (алгоритм Zhang Suen PDF на Google Docs ( Редирект с tinyurl.com, потому что парсер режет [forbidden link])) переписал, получилось вот это:
PHP код:
<?php
$im = imagecreatefrompng("php.png");
$width = imagesx($im);
$height = imagesy($im);
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
if (imagecolorat($im, $x , $y) <= 0x7FFFFF) imagesetpixel($im, $x, $y, 0x000000);
else imagesetpixel($im, $x, $y, 0xFFFFFF);
}
}
// Функция скелетонизации бинарного изображения
function zhang_suen_thinning_iteration($im, $condition_switch)
{
global $width, $height;
$running = false;
for($y = 1; $y < $height - 1; $y++) {
for($x = 1; $x < $width - 1; $x++) {
$p1 = imagecolorat($im, $x, $y) > 0 ? 1 : 0;
if ($p1 > 0) {
$p2 = imagecolorat($im, $x, $y - 1) > 0 ? 1 : 0;
$p3 = imagecolorat($im, $x + 1, $y - 1) > 0 ? 1 : 0;
$p4 = imagecolorat($im, $x + 1, $y) > 0 ? 1 : 0;
$p5 = imagecolorat($im, $x + 1, $y + 1) > 0 ? 1 : 0;
$p6 = imagecolorat($im, $x, $y + 1) > 0 ? 1 : 0;
$p7 = imagecolorat($im, $x - 1, $y + 1) > 0 ? 1 : 0;
$p8 = imagecolorat($im, $x - 1, $y) > 0 ? 1 : 0;
$p9 = imagecolorat($im, $x - 1, $y - 1) > 0 ? 1 : 0;
$connectivity =
($p2 == 0 && $p3 == 1 ? 1 : 0) +
($p3 == 0 && $p4 == 1 ? 1 : 0) +
($p4 == 0 && $p5 == 1 ? 1 : 0) +
($p5 == 0 && $p6 == 1 ? 1 : 0) +
($p6 == 0 && $p7 == 1 ? 1 : 0) +
($p7 == 0 && $p8 == 1 ? 1 : 0) +
($p8 == 0 && $p9 == 1 ? 1 : 0) +
($p9 == 0 && $p2 == 1 ? 1 : 0);
$non_zero_neighbors = $p2 + $p3 + $p4 + $p5 + $p6 + $p7 + $p8 + $p9;
if (2 <= $non_zero_neighbors && $non_zero_neighbors <= 6 && $connectivity == 1) {
if ($condition_switch == true) {
if (($p2 * $p4 * $p6 == 0) && ($p4 * $p6 * $p8 == 0)) {
imagesetpixel($im, $x, $y, 0x000000);
$running = true;
}
} else {
if (($p2 * $p4 * $p8 == 0) && ($p2 * $p6 * $p8 == 0)) {
imagesetpixel($im, $x, $y, 0x000000);
$running = true;
}
}
}
}
}
}
return $running;
}
zhang_suen_thinning_iteration($im, true);
header('Content-type: image/png');
imagepng($im);
Но работает как-то криво, с точностью на оборот – происходит не скелетонизации, а ожирение o_O
Есть на Java, Perl, C++, Pas куски из OCR модулей,
вот один из них: ZhangSuen.java
Вроде все понятно, может кто-нибудь поможет тогда исправить ошибку и доделать?
Последний раз редактировалось draliokero; 23.03.2010 в 01:21..
|
|
|

21.03.2010, 21:06
|
|
Reservists Of Antichat - Level 6
Регистрация: 25.04.2008
Сообщений: 827
Провел на форуме: 2769640
Репутация:
1304
|
|
draliokero Изображение мы должны изменять только после завершения итерации. Из-за того что мы насилуем imageGD постоянно - код получается очень медленным, по хорошему - лучше при бинаризации создавать двумерный массив, а потом уже раскрашивать обратно. Работающий код, без оптимизации:
PHP код:
<?php
set_time_limit(0);
$im = imagecreatefrompng("skeleton.png");
$width = imagesx($im);
$height = imagesy($im);
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
if (imagecolorat($im, $x , $y) <= 0x7FFFFF) imagesetpixel($im, $x, $y, 0x000000);
else imagesetpixel($im, $x, $y, 0xFFFFFF);
}
}
// Функция скелетонизации бинарного изображения
function zhang_suen_thinning_iteration($condition_switch)
{
global $width, $height, $im;
$im2 = imagecreatetruecolor($width, $height);
$running = false;
for($y = 1; $y < $height - 1; $y++) {
for($x = 1; $x < $width - 1; $x++) {
$p1 = imagecolorat($im, $x, $y) > 0 ? 1 : 0;
if ($p1 > 0) {
imagesetpixel($im2,$x,$y,0xFFFFFF);
$p2 = imagecolorat($im, $x, $y - 1) > 0 ? 1 : 0;
$p3 = imagecolorat($im, $x + 1, $y - 1) > 0 ? 1 : 0;
$p4 = imagecolorat($im, $x + 1, $y) > 0 ? 1 : 0;
$p5 = imagecolorat($im, $x + 1, $y + 1) > 0 ? 1 : 0;
$p6 = imagecolorat($im, $x, $y + 1) > 0 ? 1 : 0;
$p7 = imagecolorat($im, $x - 1, $y + 1) > 0 ? 1 : 0;
$p8 = imagecolorat($im, $x - 1, $y) > 0 ? 1 : 0;
$p9 = imagecolorat($im, $x - 1, $y - 1) > 0 ? 1 : 0;
$connectivity =
($p2 == 0 && $p3 == 1 ? 1 : 0) +
($p3 == 0 && $p4 == 1 ? 1 : 0) +
($p4 == 0 && $p5 == 1 ? 1 : 0) +
($p5 == 0 && $p6 == 1 ? 1 : 0) +
($p6 == 0 && $p7 == 1 ? 1 : 0) +
($p7 == 0 && $p8 == 1 ? 1 : 0) +
($p8 == 0 && $p9 == 1 ? 1 : 0) +
($p9 == 0 && $p2 == 1 ? 1 : 0);
$non_zero_neighbors = $p2 + $p3 + $p4 + $p5 + $p6 + $p7 + $p8 + $p9;
if (2 <= $non_zero_neighbors && $non_zero_neighbors <= 6 && $connectivity == 1) {
if ($condition_switch == true) {
if (($p2 * $p4 * $p6 == 0) && ($p4 * $p6 * $p8 == 0)) {
imagesetpixel($im2, $x, $y, 0x000000);
$running = true;
}
} else {
if (($p2 * $p4 * $p8 == 0) && ($p2 * $p6 * $p8 == 0)) {
imagesetpixel($im2, $x, $y, 0x000000);
$running = true;
}
}
}
} else imagesetpixel($im2, $x, $y, 0x000000);
}
}
imagecopy($im,$im2,0,0,0,0,$width,$height);
return $running;
}
$flag = true;$count = 0;
//zhang_suen_thinning_iteration($im, $flag);
while (zhang_suen_thinning_iteration($im, $flag = !$flag) && $count++ < 60) {}
header('Content-type: image/png');
imagepng($im);
За 60 итераций получаем такое изображение из левой верхней картинки первого поста (С увеличением чиасла итераций треугольник конечно пропадет, но достаточно не быстро):
З.Ы. получить ЧБ изображение можно через среднее арифметическое трех каналов цветного (что, кстати, и будет яркостью пиксела)
__________________
Любая действущая программа устарела.
Создайте систему, которой сможет пользоваться даже дурак ,и только дурак захочет ею пользоваться.
Как правильно задавать вопросы: _http://www.yakimchuk.ru/questions.htm
Последний раз редактировалось Gifts; 21.03.2010 в 21:12..
|
|
|

22.03.2010, 23:35
|
|
Новичок
Регистрация: 16.12.2009
Сообщений: 27
Провел на форуме: 203807
Репутация:
30
|
|
Решил попробовать - вот что получилось =D
Код:
<?php
header('Content-type: image/png');
$im = imagecreatefrompng('FILE.PNG');
$im0 = imagecreatefrompng('FILE.PNG');
$w = imagesx($im);
$h = imagesy($im);
for($y=0;$y<$h;$y++) {
for($x=0;$x<$w;$x++) {
if((imagecolorat($im, $x, $y) & 0xFF)>(256/2)) {
imagesetpixel($im,$x,$y,0xFFFFFF);
imagesetpixel($im0,$x,$y,0xFFFFFF);
} else {
imagesetpixel($im,$x,$y,0x000000);
imagesetpixel($im0,$x,$y,0x000000);
}
}
}
$open = false;
for($y=0;$y<$h;$y++) {
for($x=0;$x<$w;$x++) {
if($open!=true) {
if(imagecolorat($im,$x,$y)==0xFFFFFF) {
$open=true;
$start = $x;
}
} else {
if(imagecolorat($im,$x,$y)==0x000000) {
$open=false;
$x0 = $x-1;
$c = round(($start+$x0)/2);
imageline($im,$start,$y,($c-1),$y,0x000000);
imageline($im,($c+1),$y,$x0,$y,0x000000);
}
}
}
}
$open=false;
for($x=0;$x<$w;$x++) {
for($y=0;$y<$h;$y++) {
if($open!=true) {
if(imagecolorat($im0,$x,$y)==0xFFFFFF) {
$open=true;
$start = $y;
}
} else {
if(imagecolorat($im0,$x,$y)==0x000000) {
$open=false;
$y0 = $y-1;
$c = round(($start+$y0)/2);
imagesetpixel($im,$x,$c,0xFFFFFF);
}
}
}
}
imagepng($im);
imagedestroy($im);
?>
|
|
|
|
 |
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|