Бордър на матрица

dakata__92

Super Moderator
Колеги, имам една матрица оформяща цифрата 6. Как мога да създам функция, която да остави само контура на цифрата а пълнежа от цветове да се премахне? Идеята ми е просто да очертая цифратаи да премахна ненужното. Ето матрицата и кода с който я извеждам:

PHP:
$matrix = array(
	5 => array(
		7 => "      ",
		8 => "      ",
		9 => "f0f0f0",
		10 => "f0f0f0",
		11 => "f0f0f0",
		12 => "f0f0f0",
		13 => "      ",
		14 => "      ",
	),
	6 => array(
		7 => "      ",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "f0f0f0",
		11 => "f0f0f0",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "e0e0e0",
	),
	7 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "f0f0f0",
	),
	8 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "      ",
		13 => "      ",
		14 => "      ",
	),
	9 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "      ",
		13 => "      ",
		14 => "      ",
	),
	10 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "f0f0f0",
		11 => "f0f0f0",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "      ",
	),
	11 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "e0e0e0",
		10 => "f0f0f0",
		11 => "f0f0f0",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "f0f0f0",
	),
	12 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "e0e0e0",
	),
	13 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "f0f0f0",
	),
	14 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "f0f0f0",
	),
	15 => array(
		7 => "f0f0f0",
		8 => "f0f0f0",
		9 => "f0f0f0",
		10 => "      ",
		11 => "      ",
		12 => "f0f0f0",
		13 => "f0f0f0",
		14 => "f0f0f0",
	),
	16 => array(
		7 => "e0e0e0",
		8 => "f0f0f0",
		9 => "e0e0e0",
		10 => "f0f0f0",
		11 => "f0f0f0",
		12 => "e0e0e0",
		13 => "f0f0f0",
		14 => "e0e0e0",
	),
	17 => array(
		7 => "      ",
		8 => "      ",
		9 => "f0f0f0",
		10 => "f0f0f0",
		11 => "e0e0e0",
		12 => "f0f0f0",
		13 => "      ",
		14 => "      ",
	),
);
print '<pre>';
foreach ($matrix as $y => $row) {
	print '<br>';
	foreach ($row as $x => $column) {
		print $column;
	}
}
 
Fakeheal каза:
Какъв контур и пълнеж? Нещо не разбирам добре.

Но ако е това, за което си мисля flood fill, което е вариант на обхождането в дълбочина (depth-first search) трябва да са решението на задачката ти.

Идеята ми е да останат само крайните пиксели от матрицата, очертаващи контура на цифрата 6 и да се получи примерно нещо подобно на тази единица:
1410244160_1.jpg

Пълнежа в контура просто да се премахне.


Странично от темата търся и начин да намаля така редовете, че да се изписва цифрата с една линия тоест по ред и колона вместо с всичките пиксели, което е и по-трудният варянт.
 
dakata__92 каза:
Fakeheal каза:
Какъв контур и пълнеж? Нещо не разбирам добре.

Но ако е това, за което си мисля flood fill, което е вариант на обхождането в дълбочина (depth-first search) трябва да са решението на задачката ти.

Идеята ми е да останат само крайните пиксели от матрицата, очертаващи контура на цифрата 6 и да се получи примерно нещо подобно на тази единица:
Пълнежа в контура просто да се премахне.


Странично от темата търся и начин да намаля така редовете, че да се изписва цифрата с една линия тоест по ред и колона вместо с всичките пиксели, което е и по-трудният варянт.

Какво имаш в предвид под пиксели????

"цифрата с една линия тоест по ред и колона"?

В голямата картинка, какво точно се опитваш да направиш? Тва някаква задача за работа ли е? :D
 
Fakeheal каза:
lam3r4370 каза:
//off https://jsfiddle.net/h0322cpz/

Инпута му е странен, не виждам цвят, освен някакви шестнадейситични числа, дето сигурно (евентуално) са...ъъ... цветове?
Пусни го през идеоне или в конзола и виж резултата: http://ideone.com/ml62HJ
Ако вкараш всяко число в таблица, примерно така:

PHP:
// for each column:
echo "<td bgcolor='#$column'>";
Ще получиш сигурно и по-задоволителна картинка.

Eто я, само че нарисувана наобратно: https://jsfiddle.net/Ltw7Lm8f/
 
Fakeheal каза:
Ми начи flood fill ще свърши работа.
Ама за тая цел му трябват картинки с по-висока резолюция, иначе резултатът е това: https://jsfiddle.net/az2a9dj0/
 
dakata__92 каза:
Странично от темата търся и начин да намаля така редовете, че да се изписва цифрата с една линия тоест по ред и колона вместо с всичките пиксели, което е и по-трудният варянт.
За прави линии успоредни на осите записваш двата края и после рисуваш последователно пиксели, движейки се по Х за хоризонтални и Y за вертикални линии.

PHP:
$start = [10, 2];
$end = [30, 2];

if ($start[1] == $end[1]) {
	// равни yгреци, ходиш по x от по-малкото към по-голямото
	$from = min($start[0], $end[0]);
	$to = max($start[0], $end[0]);
	/* for $from to $to {
	draw $current x $start[1]
	} */
} 
// при равни хиксове е аналогично

За прави линии пресичащи осите намираш функцията и ходиш по хикс, смятайки игрек чрез функцията.

За криви линии (каквито имаш в 23 56 89) ще ти трябва по-сложен начин за описване, но според мен можеш спокойно да си караш с precomputed пиксели, каквито със сигурност можеш да си дръпнеш от нета.


И в трите случая обаче мисля, че ще ти е по-лесно да ползваш растерни изображения, а не векторни. Или ти трябват вторите?
 
Изображенията са векторни. Нужен ми е PHP код който да филтрира самият масив и да премахва ненужните шеснасейтични цветове със 6 пъти разстояние (спейсове). Та идеята ми е ако е възможно да се намалят пикселите така, че да оформят само дадената цифра. Тоест пълнежа да се махне и да остане само контура. Та на мен ми се въртеше в акъла да се проверява около всеки пиксел колко налични цвята има. Възможните максимални бройки са 8 пиксела около пиксел.

XXX
XPX
XXX

Кординатите им са:
($y-1,$x-1) ($y-1,$x) ($y-1,$x+1)
($y,$x-1) ($y,$x) ($y,$x+1)
($y+1,$x-1) ($y+1,$x) ($y+1,$x+1)

$y - са кординатите по редове на матрицата $matrix[$y][$x]
$x - са кординатите по колони на матрицата $matrix[$y][$x]

http://ideone.com/ml62HJ

Та нужен ми е код който в цикъла да проверява тези пикселите дали са крайни и да филтрира пълнежа, тоест вероятно ще трябва в цикъла да се проверяват и премахват пикселите, които са заобиколени всичките с цветове. Незнам омешах се доста по темата :D

PHP:
foreach ($matrix as $y => $row) {
        print "\n";
        foreach ($row as $x => $column) {
                print $column;
        }
}
 
dakata__92 каза:
Та нужен ми е код който в цикъла да проверява тези пикселите дали са крайни и да филтрира пълнежа, тоест вероятно ще трябва в цикъла да се проверяват и премахват пикселите, които са заобиколени всичките с цветове. Незнам омешах се доста по темата :D

PHP:
foreach ($matrix as $y => $row) {
        print "\n";
        foreach ($row as $x => $column) {
                print $column;
        }
}
Значи просто гледаш за всеки пиксел дали е краен? Ако е краен - рисуваш, иначе бяло.

Кое те затруднява в момента?
 
anonimen каза:
dakata__92 каза:
Та нужен ми е код който в цикъла да проверява тези пикселите дали са крайни и да филтрира пълнежа, тоест вероятно ще трябва в цикъла да се проверяват и премахват пикселите, които са заобиколени всичките с цветове. Незнам омешах се доста по темата :D

PHP:
foreach ($matrix as $y => $row) {
        print "\n";
        foreach ($row as $x => $column) {
                print $column;
        }
}
Значи просто гледаш за всеки пиксел дали е краен? Ако е краен - рисуваш, иначе бяло.

Кое те затруднява в момента?

Да това искам да направя но изпълнението ми бяга. Как да определя, кои са крайните пиксели? Ако гледам къде има по един празен пиксел обикалящ пиксела в 8-те възможности, то там би трябвало да остава, но ако до него следващият е заобиколен от 8 пълни пиксеа и го премахна то третият следващият до премахнатият ще остане защото логиката е по един свободен пиксел да остават. Кажи ми как да установя кои са крайните пиксели? Нещо подобно ми се върти в главата да разпиша в двата цикъла тоест да станат 4 цикъла един в друг:

PHP:
/*
foreach ($matrix as $y => $row) {
        print "\n";
        foreach ($row as $x => $column) {
*/
$y_points = array($y-1,$y,$y+1);
		$x_points = array($x-1,$x,$x+1);
		$countEmpty = 0;
		foreach ($y_points as $y_v) {
			foreach ($x_points as $x_v) {
				if (isSet($this->matrix[$y_v][$x_v])) {
					if ($this->matrix[$y_v][$x_v] == $this->replacement) {
						$countEmpty++;
					}
				}
			}
		}
		switch ($countEmpty) {
			case 0:
				return $this->matrix[$y][$x];
				break;
			case 1:
				return $this->matrix[$y][$x];
				break;
			case 2:
				return $this->matrix[$y][$x];
				break;
			case 3:
				return $this->matrix[$y][$x];
				break;
			case 4:
				return $this->matrix[$y][$x];
				break;
			case 5:
				return $this->matrix[$y][$x] = $this->replacement;
				break;
			case 6:
				return $this->matrix[$y][$x] = $this->replacement;
				break;
			case 7:
				return $this->matrix[$y][$x] = $this->replacement;
				break;
			case 8:
				return $this->matrix[$y][$x] = $this->replacement;
				break;
			default : 
				return $this->matrix[$y][$x];
		}

/*   }
}*/
 
Мисля, че това са алгоритмите, които търсиш:
https://en.wikipedia.org/wiki/Connected-component_labeling
 
eLite каза:
Мисля, че това са алгоритмите, които търсиш:
https://en.wikipedia.org/wiki/Connected-component_labeling

Ето тази с човечето е много интересна. Някой пробвал ли се е да напише такъв код за екстракт на различни обекти от изображения?
220px-Two-pass_connected_component_labeling.svg.png
 
Лично аз не съм, но и не виждам проблем да си го напишеш сам.

Във връзката на статията, която съм ти пратил има псевдо алгоритъм, който просто трябва да имплементираш в PHP.

Имай впредвид, че става въпрос за бинарни изображения.

Ако искаш нещо по-сложно (монохромни изображения), ще трябва да почетеш: http://www.cse.msu.edu/~stockman/Book/2002/Chapters/ch3.pdf
 
eLite каза:
Лично аз не съм, но и не виждам проблем да си го напишеш сам.

Във връзката на статията, която съм ти пратил има псевдо алгоритъм, който просто трябва да имплементираш в PHP.

Имай впредвид, че става въпрос за бинарни изображения.

Ако искаш нещо по-сложно (монохромни изображения), ще трябва да почетеш: http://www.cse.msu.edu/~stockman/Book/2002/Chapters/ch3.pdf

Има ли някъде и на Български тези статии. Превеждам си ги, но понякога смисъла не ми се получава точно. :)
 
Тъй като в случая ще работиш само с 10 цифри (и то картинките едва ли ще са много големи) - мисля, че ще е достатъчно да гледаш около всеки пиксел дали има празен (бял). Ако има поне един - отбелязваш разглеждания пиксел като краен. Прилагаш това за всеки пиксел от картинката.

Да, няма да е оптимизирано, но все пак тук не ти трябва кой-знае каква бързина. Но пък ще е лесно:

Код:
за всеки ред
    за всеки пиксел -> X
        ако X е бял -> continue
        ако X e черен и наоколо има поне един бял -> отбелязваш X като краен
 
anonimen каза:
Тъй като в случая ще работиш само с 10 цифри (и то картинките едва ли ще са много големи) - мисля, че ще е достатъчно да гледаш около всеки пиксел дали има празен (бял). Ако има поне един - отбелязваш разглеждания пиксел като краен. Прилагаш това за всеки пиксел от картинката.

Да, няма да е оптимизирано, но все пак тук не ти трябва кой-знае каква бързина. Но пък ще е лесно:

Код:
за всеки ред
    за всеки пиксел -> X
        ако X е бял -> continue
        ако X e черен и наоколо има поне един бял -> отбелязваш X като краен

Можеш ли да ми го разпишеш с кода от първият ми пост в темата?
http://ideone.com/ml62HJ

Неуспявам да се справя нещо...
 
dakata__92 каза:
Можеш ли да ми го разпишеш с кода от първият ми пост в темата?
http://ideone.com/ml62HJ

Неуспявам да се справя нещо...

Ако ходиш с $x надясно и с $y надолу:

PHP:
if($data[$y-1][$x-1] && $data[$y-1][$x] && $data[$y-1][$x+1] // трите пиксела над текущия
   // сега същото, но с $y, вместо $y-1 (двата пиксела около текущия)
   // сега същото за трите пиксела под текущия, ползваш $y+1

Спестих си сравняването с празен пиксел - по-удобно ще ти е ако запазваш празните пиксели като някаква falsy стойност вместо 20 спейса.
 

Back
Горе