将BMP图像转换为绘图仪的指令集?

Tod*_*nov 3 colors image-processing vectorization reduction

我有一个像这样的绘图仪: PloterXY设备.

我必须实现的任务是将24位BMP转换为该绘图仪的指令集.在绘图仪中,我可以改变16种常见颜色.我面临的第一个复杂性是颜色减少.我面临的第二个复杂性是如何将像素转换为一组绘图指令.

作为使用油漆的绘图工具刷将被使用.这意味着绘图仪绘制线不会那么小,而且它们会相对较短.

请提出可用于解决此图像数据转换问题的算法?

一些初步结果:

花1  - 减少颜色.

花2  - 减少颜色.

花3  - 减少颜色.

Spe*_*tre 5

抖动

好吧,今天我有一些时间,所以这里结果.您没有提供绘图仪调色板,因此我从生成的图像中提取它,但您可以使用任何颜色.抖动背后的想法很简单我们的感知在区域上集成颜色而不是单个像素,所以你必须使用一些颜色差异的累加器,而不是渲染的内容和应该渲染的内容,并将其添加到下一个像素......

这样,该区域具有大致相同的颜色,但实际上仅使用离散数量的颜色.如何更新此信息的形式可以将结果分支抖动与许多方法区分开来.简单直白的是:

  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;
Run Code Online (Sandbox Code Playgroud)

picture我的图像类在哪里所以这里有一些成员:

  • xs,ys 解析度
  • color p[ys][xs] 直接像素访问(32位像素格式,每通道8位)
  • clear(DWORD c) 用颜色填充图像 c

color只是unionDWORD ddBYTE db[4]简单的信道接入.

List<>是我的模板(动态数组/列表>

  • List<int> a是一样的int a[].
  • add(b) 在列表末尾添加b
  • num 是列表中的项目数

现在要避免过多的点(为了绘图仪的生命周期),您可以使用不同的线条图案等,但这需要大量的试验/错误...例如,您可以计算在某些区域使用颜色的次数并从该比例使用不同的填充模式(基于线).你需要在图像质量和渲染速度/耐久性之间做出选择......

如果没有关于绘图仪功能(速度,换刀方法,颜色组合行为)的更多信息,很难确定形成控制流的最佳方法.我敢打赌你手动改变颜色,这样你就可以一次渲染每种颜色.因此,使用第一个工具的颜色合并相邻像素的所有像素到线条/曲线并渲染...然后移动到下一个工具颜色...