image-processing - vectorizer - vectorized graphics
¿Convertir la imagen BMP en un conjunto de instrucciones para un trazador? (1)
La tarea que tengo que implementar es la conversión de BMP de 24 bits a un conjunto de instrucciones para este trazador. En el plotter puedo cambiar 16 colores comunes. La primera complejidad que enfrento es la reducción de colores. La segunda complejidad que enfrento es cómo transformar píxeles en un conjunto de instrucciones de dibujo.
Como herramienta de dibujo se utilizará pincel con pintura al óleo. Significa que las líneas de dibujo del trazador no serán tan pequeñas y serán relativamente cortas.
¿Sugiere algoritmos que se puedan usar para resolver este problema de conversión de datos de imagen?
Algunos resultados iniciales:
Tramado
Bueno, tengo algo de tiempo para esto hoy, así que aquí está el resultado. No proporcionó su paleta de colores del trazador, así que la extraje de sus imágenes resultantes, pero puede usar cualquiera. La idea detrás del tramado es simple: nuestra percepción integra el color en el área, no los píxeles individuales, por lo que debe usar un acumulador de diferencia de color de lo que se procesa y lo que se debe renderizar, y agregar esto al siguiente píxel ...
De esta manera, el área tiene aproximadamente el mismo color, pero solo se utiliza un número discreto de colores en el real. La forma de cómo actualizar esta información puede diferenciar el dithering de ramificación de resultados en muchos métodos. El simple y sencillo es este:
- restablecer el acumulador de color a cero
-
procesar todos los píxeles
- para cada píxel agregue su color al acumulador
- encuentre la coincidencia más cercana del resultado en su paleta
- renderizar el color de la paleta seleccionada
- restar el color de la paleta seleccionada del acumulador
Aquí su imagen de entrada (los puse juntos):
Aquí imagen del resultado para su fuente:
Los cuadrados de color en la esquina superior izquierda son solo la paleta que utilicé (extraída de su imagen).
Aquí el código ( C ++ ) hago esto con:
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;
donde
picture
es mi clase de imagen, así que aquí algunos miembros:
-
resolución
xs,ys
-
color p[ys][xs]
acceso directo a píxeles (formato de píxeles de 32 bits, 8 bits por canal) -
clear(DWORD c)
llena la imagen con colorc
El
color
es solo la
union
de
DWORD dd
y
BYTE db[4]
para un acceso simple al canal.
La
List<>
es mi plantilla (matriz dinámica / lista>
-
List<int> a
es lo mismo queint a[]
. -
add(b)
agregar b al final de la lista -
num
es el número de elementos en la lista
Ahora, para evitar demasiados puntos (durante la vida útil de su plotter), puede usar diferentes patrones de línea, etc., pero eso requiere mucha prueba / error ... Por ejemplo, puede contar cuántas veces se usa un color en alguna área y a partir de esa proporción, use diferentes patrones de relleno (basados en líneas). Debe elegir entre calidad de imagen y velocidad de renderizado / durabilidad ...
Sin más información sobre las capacidades de su trazador (velocidades, método de cambio de herramienta, comportamiento de combinación de colores) es difícil decidir el mejor método para formar un flujo de control. Mi apuesta es que cambie los colores manualmente para que renderice cada color a la vez. Entonces, extraiga todos los píxeles con el color de la primera herramienta, combine los píxeles adyacentes en líneas / curvas y renderice ... luego muévase al siguiente color de herramienta ...