用骰子给心爱的人作幅画吧(原题:骰子作画的算法)

  • 望君珍重
    程序员Scott MacDonald做了一个很有趣的项目----骰子作画(http://www.elusivesnark.com/2008/11/carolines-dice-portrait.html)。

    他用黑底白点的骰子。



    模拟出一张人像照片。



    把图像放大,就可以看得更清楚。



    他一共用了2500多颗骰子。



    最后的成品就是这样。



    任何一张图片都可以用骰子模拟出来,算法非常简单:将图片分成若干个区域,每个区域经过计算以后,用1-6之间的一个整数表示,代表骰子的一个面。这种将连续的量转化成不连续的整数的算法,属于vector quantization(矢量量化)(http://en.wikipedia.org/wiki/Vector_quantization)的一个应用。

    具体来说,

    第一步,将图片分割成16像素x16像素的小方块。


    for (int i=0; i < (pic_width/16); ++i) {

    for (int j=0; j < (pic_height/16); ++j) {

    patch = cropped_img.get(i*16, j*16, 16, 16);

    }

    }

    第二步,每个小方块内共有256个像素,将每个像素点的灰度值,存入一个数组。


    for (int k=0; k < patch.pixels.length; ++k) {

    x[k] = rgb2gray(patch.pixels[k]);

    }

    int rgb2gray(int argb) {

    int _alpha = (argb >> 24) & 0xFF;

    int _red = (argb >> 16) & 0xFF;

    int _green = (argb >> 8 ) & 0xFF;

    int _blue = (argb) & 0xFF;

    return int(0.3*_red + 0.59*_green + 0.11*_blue);

    }

    第三步,计算该数组的平均值,并用1-6之间的一个整数来表示。


    int dice_num = six_step_gray(mean(x));

    int mean(int[] x) {

    float m = 0;

    for (int i=0; i < x.length; ++i) {

    m += x;

    }

    m = m/x.length;

    return int(m);

    }

    int six_step_gray(int x) {

    if (0 <= x && x <= 41) return 1;

    if (41 < x && x <= 83) return 2;

    if (83 < x && x <= 124) return 3;

    if (124 < x && x <= 165) return 4;

    if (165 < x && x <= 206) return 5;

    if (206 < x && x <= 247) return 6;

    else return 6;
    }

    整数1,表示骰子朝上的一面有1个白点;整数2,表示有2个白点;以此类推。白点越少,表示这个区域越接近全黑;白点越多,表示越接近全白。根据白点值,将骰子依次放入,就能模拟出全图。

    这种算法早在1981年就有人提出(http://4c.ucc.ie/~hcambaza/page5/page5.html),当时用的是1~9个白点的多米诺骨牌。



    如果区域划分得越小,模拟图的生成效果就越好。













    此外,不用编程,使用Photoshop(http://www.attackofdesign.com/ho ... ce-using-photoshop/)也可以得到类似效果。



    (完)

    文档信息
    •版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
    •原文网址:http://www.ruanyifeng.com/blog/2011/11/dice_portrait.html
    •最后修改时间:2011年12月 3日 22:08
    •付费支持(说明): |
  • 2
    20011004
    正常骰子只有6个点,这里面还需要0、7、8、9点的骰子啊...

    BTW:
    有那时间多陪陪妞多好,整个一典型的宅男行为,干这种浪费时间不实用的事情,
    他要是做这个之前先去“how are you doing”一下就省事了。

    [本帖最后由 20011004 于 2011-12-9 10:30 编辑]
  • 无面
    一篇论文还是核心的就这样搞定了,顺带还能泡妹子。

    你还别说妹子就吃这一套,啪啪啪妥妥的
  • 望君珍重
    你说的是第二种算法

    第一种算法用1到6完全可以实现

    我觉得这东西跟十字绣挺像的

    制作一个跟图里差不多的画,作为礼物送人不是很有意义么?
  • 哎哟大白
    这才是死程序员该干的事啊!
  • 我爱一条柴啊
    @我爱一条柴啊 mark
  • 砒霜含笑吞
    点阵图是骨灰玩家的浪漫
  • b
    babyone
    点阵图是骨灰玩家的浪漫+1