以编程方式生成复合肖像马赛克

时间:2017-09-19 10:53:59

标签: javascript image-processing graphics

我需要创建复合肖像马赛克(即用其他肖像制作的肖像)。见下面的参考文献。

另一个很好的参考是AndreaMosaic。 http://www.andreaplanet.com/andreamosaic/samples/

或者这个youtube教程(跳到5分钟标记) https://www.youtube.com/watch?v=9cy2gVm_ztQ

寻找最佳方法,然后生成一个可以下载的jpeg文件。 理想情况下,我希望使用Node / Javascript进行此操作,但可以使用PHP或其他任何方式。

有关从哪里开始的任何建议?这里和那里有一些库,但没有什么比我想做的更适合。

enter image description here

1 个答案:

答案 0 :(得分:0)

伪造的马赛克很简单。好吧,我尝试了一个简单的乘法,看起来像是作品。

  1. 创建覆盖输入图像大小的照片纹理图案
  2. 调制灰度照片图案和原始图像

    简单的乘法就可以了。

  3. 这两个步骤可以合并为一个...这里简单的 C ++ 代码:

    // globals
    const int txrs=41; // number of textures for mosaic
    picture txr[txrs]; // mosaic textures
    picture pic0,pic1; // input and output images
    
    // init
    pic0.load("MonaLisa.jpg");
    int sz=32; // mosaic grid size
    for (int i=0;i<txrs;i++) // load/resize/grayscale textures
        {
        txr[i].load(AnsiString().sprintf("textures\\%03i.jpg",i));  // load image
        txr[i].resize_fit(sz,sz,0x00000000);                        // resize to tile size
        txr[i].enhance_range();
        txr[i].pixel_format(_pf_u);                                 // convert to grayscale <0,765>
        txr[i].pixel_format(_pf_rgba);                              // convert to grayscale RGBA
        }
    pic0.resize_fit((pic0.xs/sz)*sz,(pic0.ys/sz)*sz,0x00000000);    // cut not full tile size part of pic1
    
    // mosaic
    int xx,yy,x,y,i,j,sz=txr[0].xs,a,b;
    color c0,c1;
    pic1=pic0;  // copy source image to destination
    // process all regions
    for (y=0;y<pic1.ys;y+=sz)
     for (x=0;x<pic1.xs;x+=sz)
        {
        // select random texture
        i=Random(txrs);
        // proces region
        for (yy=0;yy<sz;yy++)
         for (xx=0;xx<sz;xx++)
            {
            // grayscale texture and original color image pixels
            c0=txr[i].p[yy][xx];
            c1=pic1.p[y+yy][x+xx];
            // mutiply them
            for (j=0;j<3;j++)
                {
                a=BYTE(c0.db[j]);
                b=BYTE(c1.db[j]);
                a=(a*b)>>8;
                c0.db[j]=a;
                }
            // store to destinatio image
            pic1.p[y+yy][x+xx]=c0;
            }
        }
    pic1.save("out.png");
    

    我将自己的图片类用于图片,因此有些成员是:


    xs,ys是图像的大小(以像素为单位)
    p[y][x].dd(x,y)位置的像素,为32位整数类型
    clear(color)使用color清除整个图像
    resize(xs,ys)将图片调整为新分辨率
    bmp VCL 已封装 GDI 具有Canvas访问权限的位图
    pf保存图像的实际像素格式:

    enum _pixel_format_enum
        {
        _pf_none=0, // undefined
        _pf_rgba,   // 32 bit RGBA
        _pf_s,      // 32 bit signed int
        _pf_u,      // 32 bit unsigned int
        _pf_ss,     // 2x16 bit signed int
        _pf_uu,     // 2x16 bit unsigned int
        _pixel_format_enum_end
        };
    


    color和像素编码如下:

    union color
        {
        DWORD dd; WORD dw[2]; byte db[4];
        int i; short int ii[2];
        color(){}; color(color& a){ *this=a; }; ~color(){}; color* operator = (const color *a) { dd=a->dd; return this; }; /*color* operator = (const color &a) { ...copy... return this; };*/
        };
    

    这些乐队是:

    enum{
        _x=0,   // dw
        _y=1,
    
        _b=0,   // db
        _g=1,
        _r=2,
        _a=3,
    
        _v=0,   // db
        _s=1,
        _h=2,
        };
    

    我使用的输入图像是:

    input

    结果如下:

    output

    可能需要进行一些亮度调整以匹配原始输入图像属性。