Re[7]: Подзадача: цепочка пикселов => кривая Безье
От: Рома Мик Россия http://romamik.com
Дата: 01.10.03 12:21
Оценка:
Здравствуйте, Mika Soukhov, Вы писали:

MS>Здравствуйте, Рома Мик, Вы писали:


MS>Народ, можно как нить по проще и понятнее (без воды ). Я математику уже стал поздзабывать, так, плиз, еще и по доходчивее

Да вроде никакой воды...
А расписать все подробно и по пунктам — это как код написать, а код написать — это за деньги и потом, или за большие деньги...
... << RSDN@Home 1.1 beta 2 >>
Re[6]: Подзадача: цепочка пикселов => кривая Безье
От: Кирилл Осенков Украина
Дата: 01.10.03 15:49
Оценка: 45 (2)
КО>>попали в сказку и кто-то подарил нам такую цепочку пикселов (массив пикселов от 1 до n, причем у каждого пиксела кроме концов ровно два соседа (если брать 8-связность)),
РМ>Ну составить такую цепочку было бы не проблематично, но ИМХО она и не нужна. И можно брать больше чем 8-связности.
Если честно, я плохо представляю себе, а как без цепочки?
Было бы классно знать более-менее конструктивный способ, использующий такой массив с утолщениями и аномалиями (а не цепочку):


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

А связности — да, согласен, я порассматривал Микину картинку через лупу — конечно, ужас Но ты прав, отчаиваться не стоит — вон люди из Adobe как умеют, не говоря уже об орлах из Abbyy... Понятно, задача решаемая. Но сложная.

Так вот. Предлагаю взять такую связность:

01110
11111
11*11
11111
01110


Здесь для пиксела "*" соседними будут считаться пикселы "1". Так мы соединим разрывы в 1 пиксел, но не более (а этого и достаточно, остальные разрывы будем считать двумя кусками).

РМ>Совсем точно не найдем, найдем менее точно: кусочки кривой безье будут покороче, но все равно будут. А искать, я бы искал так: берем прямую, проходящую нашу точку и вращаем ее ( вариантов углов поворота не так много, так как прямая наша довольно коротка ), какой вариант покрывает наибольшее число точек нашей кривой, тот и есть искомое направление. Кроме того количество покрытых пикселей явно должно коррелировать с длиной вектора от первой ко второй точке. А более точного направления нам не надо, так как его просто и нет в природе, поскольку задана то нам только множество точек в которое можно вписать сколько хочешь кривых.

Да, вообще да. Я подумал, твой фокус с прямой можно оптимизировать. Подбирать ее не нужно — ее можно восстановить по алгоритму Брезенхема. Смотри — прямая рисуется как набор горизонтальных или вертикальных отрезков примерно равной длины. Я имею ввиду:

0000000*00
0000000*00
000000*-00
0000**0000
00+*000000
0000000000


Здесь на рисунке + это начало нашей будущей кривой, а звездочки — пикселы, которые надо покрыть. Минусом на рисунке отмечен пиксел, где цепочка начинает уклоняться от прямой. Смотрим — ага, первое время это состыкованные горизонтальные отрезки по два пиксела — вот и будем продолжать этот "паттерн" (узор), пока вписываемся в алгоритм Брезенхема. Как получим очередной отрезок неправильной длины (там, где минус — горизонтальная полоска из 1 пиксела, а не из двух) — значит цепочка отклонилась от прямой. Теперь то, что уже насчитали (от плюса до минуса) — часть нужной нам касательной прямой. Ее уравнение найти просто — она проходит через исходную точку (+ на рисунке) и угловой коэффициент — разделить разность игреков плюса и минуса на разность иксов.

КО>>
  • Мои воздушные рассуждения о том, что поиск второго конца можно прерывать после нахождения третьего обнуления кривизны.
    РМ>ИМХО поиск можно прерывать, когда например из десяти наскоро посчитанных точек кривой две окажутся вне множетсва точек.
    Это эмпирика. К тому же мне кажется, ты как-то скромно берешь — с таким же успехом отлично можно и отрезками приближать.

    КО>>
  • Опять же, достаточно точно оценить кривизну в нашей дискретной задаче скорее всего не удастся.
    КО>>
  • Как искать удаление направляющих точек от концов кривой — вообще неясно (ну т.е. мне не ясно )
    РМ>Я там выше писал про покрытие точек прямой, так вот их кол-во после какого-то несложного преобразования ( возможно по таблице, полученной эмпирически ) должно дать примерное значение, вокруг которого можно искать перебором или даже оставить так.
    Да, но перебор все-таки достаточно большой...

    РМ>Ну использование более чем 8-связности от маленьких разрывов убережет, а большие пусть и остаются — получится две линии вместо одной и все.

    ОК.

    КО>>изломы, самопересечения,

    РМ>В принципе при вращении кривой эти штуки опредятся как два максимума только в одной стороне ( изломы ) два максимума с обеих сторон ( пересечения ). В изломах можно и прервать кривую, а в пересечениях продолжатьь в нужном направлении.
    Щас, я не понял. Что ты имеешь ввиду? Здесь можешь поподробнее плз?

    КО>>замкнутость в кольцо,

    РМ>Где тут проблема?
    ОК ОК согласен

    КО>>толщина в 2 и больше пиксела (а толщина в два пиксела, зараза, сплошь и рядом встречается на приведенной картинке),

    РМ>Не страшна. Какие проблемы она создает?
    Да понимаешь — вот у нас массив пар (x,y) от 1 до 10000. Больше ничего не знаем. И что с этим делать? Как ты поймешь, что кривую нужно направлять в "самую тонкую сторону"? И глянь на рисунок — там есть жирные перекрестки из пяти и больше таких "кишок"... Че с ними делать, я не знаю...

    КО>>раздавленные комары, пыль и вообще все плохо

    РМ>Комаров я там не заметил, а пыль — можно просто выкидывать слишком мелкие куски.
    Не знаю. Там кусок 6х6 — мы-то с тобой понимаем, что его надо выкинуть, а компу как объяснить?

    КО>>О блин... Одни слабые места

    РМ>Ну, это пессимистичный взгляд — люди и не такое оцифровывают...
    Согласен, у страха глаза велики

    РМ>Кстати не обязательно использовать именно Безье. Можно и квадратичными кривыми обойтись в данном случае, а считать и перебирать уже меньше.

    Ну да, это Mika просто упомянул, что ему кривые Безье нужны — а так конечно, с квадратичными проблем гораздо меньше. Дело в том, что квадратичная кривая — это кривая Безье, у которой две направляющие точки совпадают, а следовательно, находятся на пересечении двух касательных прямых в концах кривой. Все наши рассуждения остаются, более того: как только мы отыщем касательные прямые в концах с достаточной точностью, сразу появится третья точка (в точке их пересечения) — и квадратичная кривая найдена.
  • Re: Растр ==> Вектор
    От: Кирилл Осенков Украина
    Дата: 01.10.03 17:12
    Оценка: 6 (1)
    Есть одно из лучших собраний алгоритмов компьютерной графики: пятитомник Graphics Gems. Очень советую. И еще, говорят, что в пятом томе на стр. 323 лежит то, что тебе нужно

    Кстати, я еще погуглил "vectorization line tracing algorithm" — вроде кое-что там есть, хотя алгоритма я пока не видел.

    Вот глянь например:
    http://gis.esri.com/library/userconf/proc97/proc97/to200/pap193/p193.htm
    http://geopro.cic.ipn.mx/Extended%20Abstract%20EB.pdf
    http://www.penguin.cz/~fojtik/vectoris/vektoris.htm
    http://www.rfai.li.univ-tours.fr/RFAI/rapports/ram98b.pdf
    Re[7]: Подзадача: цепочка пикселов => кривая Безье
    От: Рома Мик Россия http://romamik.com
    Дата: 01.10.03 18:55
    Оценка: 12 (1)
    Здравствуйте, Кирилл Осенков, Вы писали:

    КО>>>попали в сказку и кто-то подарил нам такую цепочку пикселов (массив пикселов от 1 до n, причем у каждого пиксела кроме концов ровно два соседа (если брать 8-связность)),

    РМ>>Ну составить такую цепочку было бы не проблематично, но ИМХО она и не нужна. И можно брать больше чем 8-связности.
    КО>Если честно, я плохо представляю себе, а как без цепочки?
    КО>Было бы классно знать более-менее конструктивный способ, использующий такой массив с утолщениями и аномалиями (а не цепочку):
    Как определить направление в данной точке без цепочки я уже писал. Вторая проблема — это движение вдоль линии. Но имея направление, разве это проблема? Третья проблема — это выкидывать те точки, для которых кривая уже построена, так как при движении вдоль мы будем проходить не через все точки. Но в принципе и это не проблема, так как можно помечать все находящиеся рядом с проходимыми.

    КО>Так вот. Предлагаю взять такую связность:

    Ну это вопрос не принципиальный имхо, но я себе именно такую и представлял.

    КО>Я подумал, твой фокус с прямой можно оптимизировать. Подбирать ее не нужно — ее можно восстановить по алгоритму Брезенхема.

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

    КО>>>
  • Мои воздушные рассуждения о том, что поиск второго конца можно прерывать после нахождения третьего обнуления кривизны.
    РМ>>ИМХО поиск можно прерывать, когда например из десяти наскоро посчитанных точек кривой две окажутся вне множетсва точек.
    КО>Это эмпирика. К тому же мне кажется, ты как-то скромно берешь — с таким же успехом отлично можно и отрезками приближать.
    Ну это я так, к примеру, а вообще изначально мне казалось, что надо всю кривую в масшатабе рисунка восстанавливать и чтобы она вся укладывалась в наши точки.

    КО>>>
  • Опять же, достаточно точно оценить кривизну в нашей дискретной задаче скорее всего не удастся.
    КО>>>
  • Как искать удаление направляющих точек от концов кривой — вообще неясно (ну т.е. мне не ясно )
    РМ>>Я там выше писал про покрытие точек прямой, так вот их кол-во после какого-то несложного преобразования ( возможно по таблице, полученной эмпирически ) должно дать примерное значение, вокруг которого можно искать перебором или даже оставить так.
    КО>Да, но перебор все-таки достаточно большой...
    В том-то и штука, что перебор вокруг приблизительного значения, то есть сильно меньший, чем мог бы быть.
    А вообще отказавшись от Безье, в пользу кривых второго порядка, можно избежать перебора вообще.

    КО>>>изломы, самопересечения,

    РМ>>В принципе при вращении кривой эти штуки опредятся как два максимума только в одной стороне ( изломы ) два максимума с обеих сторон ( пересечения ). В изломах можно и прервать кривую, а в пересечениях продолжатьь в нужном направлении.
    КО>Щас, я не понял. Что ты имеешь ввиду? Здесь можешь поподробнее плз?
    Если мы имеем излом, и попытаемся найти направление фокусом с кривой, то ничего не выйдет, направления будет два и односторонних, а для пересечения будет просто два направления. Оба случая можно корректно обработать.

    КО>>>толщина в 2 и больше пиксела (а толщина в два пиксела, зараза, сплошь и рядом встречается на приведенной картинке),

    РМ>>Не страшна. Какие проблемы она создает?
    КО>Да понимаешь — вот у нас массив пар (x,y) от 1 до 10000. Больше ничего не знаем. И что с этим делать? Как ты поймешь, что кривую нужно направлять в "самую тонкую сторону"?
    А фокус с прямой зачем?
    КО>И глянь на рисунок — там есть жирные перекрестки из пяти и больше таких "кишок"... Че с ними делать, я не знаю...
    Не начинать с перекрестков. А на ходу, когда уже известно предыдущее направление проще выбрать правильное.

    КО>>>раздавленные комары, пыль и вообще все плохо

    РМ>>Комаров я там не заметил, а пыль — можно просто выкидывать слишком мелкие куски.
    КО>Не знаю. Там кусок 6х6 — мы-то с тобой понимаем, что его надо выкинуть, а компу как объяснить?
    Выкидывать те, где не прошел фокус с кривой...

    РМ>>Кстати не обязательно использовать именно Безье. Можно и квадратичными кривыми обойтись в данном случае, а считать и перебирать уже меньше.

    КО>Ну да, это Mika просто упомянул, что ему кривые Безье нужны — а так конечно, с квадратичными проблем гораздо меньше. Дело в том, что квадратичная кривая — это кривая Безье, у которой две направляющие точки совпадают, а следовательно, находятся на пересечении двух касательных прямых в концах кривой. Все наши рассуждения остаются, более того: как только мы отыщем касательные прямые в концах с достаточной точностью, сразу появится третья точка (в точке их пересечения) — и квадратичная кривая найдена.
    Во-во, и я о том же.
    ... << RSDN@Home 1.1 beta 2 >>
  • Re[8]: Подзадача: цепочка пикселов => кривая Безье
    От: Кирилл Осенков Украина
    Дата: 02.10.03 21:16
    Оценка:
    РМ>Как определить направление в данной точке без цепочки я уже писал. Вторая проблема — это движение вдоль линии. Но имея направление, разве это проблема? Третья проблема — это выкидывать те точки, для которых кривая уже построена, так как при движении вдоль мы будем проходить не через все точки. Но в принципе и это не проблема, так как можно помечать все находящиеся рядом с проходимыми.
    Ну, от этих рассуждений до алгоритма еще довольно далеко (еще много неясностей), но путь ты указал — и я с тобой согласен. Теперь уже наверное можно пробовать кодить

    P.S. Здесь очень важны дизайн и структуры данных — в процессе написания алгоритм будет сильно эволюционировать.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.