Преобразование изображения BMP в набор инструкций для плоттера?

У меня есть такой плоттер: Устройство PloterXY

Задача, которую я должен реализовать, - преобразование 24-битного BMP в набор инструкций для этого плоттера. В плоттере я могу изменить 16 общих цветов. Первая сложность, с которой я сталкиваюсь, - это уменьшение цвета. Вторая сложность, с которой я сталкиваюсь, заключается в том, как преобразовать пиксели в набор инструкций для рисования.

В качестве инструмента для рисования будет использоваться кисть с масляной краской. Это означает, что линии рисования плоттера не будут такими маленькими и будут относительно короткими.

Пожалуйста, предложите алгоритмы, которые могут быть использованы для решения этой проблемы преобразования данных изображения?

Некоторые начальные результаты:

Цветок 1 - уменьшение цвета

Цветок 2 - уменьшение цвета

Цветок 3 - уменьшение цвета

1 ответ

Решение

Смешение

Ну, у меня есть время для этого сегодня, так что вот результат. Вы не предоставили свою цветовую палитру плоттера, поэтому я извлек ее из ваших полученных изображений, но вы можете использовать любую. Идея, лежащая в основе сглаживания, проста: наше восприятие объединяет цвет в области, а не в отдельных пикселях, поэтому вы должны использовать некоторый аккумулятор разницы в цвете того, что визуализируется и что должно быть визуализировано, и добавлять это к следующему пикселю...

Таким образом, область имеет примерно одинаковый цвет, но в реальности используется только дискретное количество цветов. Форма обновления этой информации может дифференцировать разветвление результата во многих методах. Простое простое это:

  1. сбросить накопитель цвета на ноль
  2. обработать все пиксели
    1. для каждого пикселя добавьте свой цвет в аккумулятор
    2. найти наиболее близкое соответствие результата в вашей палитре
    3. сделать выбранный цвет палитры
    4. вычесть выбранный цвет палитры из аккумулятора

Вот ваше входное изображение (я их собрал):

вход

Вот результат изображения для вашего источника:

результат

Цветные квадраты в верхнем левом углу - это просто палитра, которую я использовал (извлечено из вашего изображения).

Здесь код (C++) я делаю это с:

picture pic0,pic1,pic2;
    // pic0 - source img
    // pic1 - source pal
    // pic2 - output img
int x,y,i,j,d,d0,e;
int r,g,b,r0,g0,b0;
color c;
List<color> pal;
// resize output to source image size clear with black
pic2=pic0; pic2.clear(0);
// create distinct colors pal[] list from palette image
for (y=0;y<pic1.ys;y++)
 for (x=0;x<pic1.xs;x++)
    {
    c=pic1.p[y][x];
    for (i=0;i<pal.num;i++) if (pal[i].dd==c.dd) { i=-1; break; }
    if (i>=0) pal.add(c);
    }
// dithering
r0=0; g0=0; b0=0;   // no leftovers
for (y=0;y<pic0.ys;y++)
 for (x=0;x<pic0.xs;x++)
    {
    // get source pixel color
    c=pic0.p[y][x];
    // add to leftovers
    r0+=WORD(c.db[picture::_r]);
    g0+=WORD(c.db[picture::_g]);
    b0+=WORD(c.db[picture::_b]);
    // find closest color from pal[]
    for (i=0,j=-1;i<pal.num;i++)
        {
        c=pal[i];
        r=WORD(c.db[picture::_r]);
        g=WORD(c.db[picture::_g]);
        b=WORD(c.db[picture::_b]);
        e=(r-r0); e*=e; d =e;
        e=(g-g0); e*=e; d+=e;
        e=(b-b0); e*=e; d+=e;
        if ((j<0)||(d0>d)) { d0=d; j=i; }
        }
    // get selected palette color
    c=pal[j];
    // sub from leftovers
    r0-=WORD(c.db[picture::_r]);
    g0-=WORD(c.db[picture::_g]);
    b0-=WORD(c.db[picture::_b]);
    // copy to destination image
    pic2.p[y][x]=c;
    }
// render found palette pal[] (visual check/debug)
x=0; y=0; r=16; g=pic2.xs/r; if (g>pal.num) g=pal.num;
for (y=0;y<r;y++)
 for (i=0;i<g;i++)
  for (c=pal[i],x=0;x<r;x++)
   pic2.p[y][x+(i*r)]=c;

где picture мой класс изображения, поэтому здесь некоторые члены:

  • xs,ys разрешающая способность
  • color p[ys][xs] прямой доступ к пикселям (32-битный формат пикселей, 8 бит на канал)
  • clear(DWORD c) заполняет изображение цветом c

color просто union из DWORD dd а также BYTE db[4] для простого доступа к каналу.

List<> мой шаблон (динамический массив / список>

  • List<int> a такой же как int a[],
  • add(b) добавить b к нему в конце списка
  • num количество элементов в списке

Теперь, чтобы избежать слишком большого количества точек (для срока службы вашего плоттера), вы можете использовать вместо этого различные линейные шаблоны и т. Д., Но это требует большого количества проб / ошибок... Например, вы можете подсчитать, сколько раз цвет используется в некоторой области и из этого соотношения используйте различные шаблоны заполнения (на основе линий). Вам нужно выбирать между качеством изображения и скоростью рендеринга / долговечностью...

Без дополнительной информации о возможностях вашего плоттера (скорости, метод смены инструмента, поведение сочетания цветов) трудно определить лучший метод формирования потока управления. Держу пари, вы меняете цвета вручную, поэтому вы будете рендерить каждый цвет сразу. Поэтому выделите все пиксели цветом первого инструмента, объедините смежные пиксели с линиями / кривыми и визуализируйте... затем перейдите к следующему цвету инструмента...

Другие вопросы по тегам