最新消息:蔓草札记的微信公众号开通了,赶紧在微信通讯录公众号中搜索“蔓草札记”关注下吧 :)

骰子作画的算法

图像处理 xhhjin 1299浏览 2评论

程序员Scott MacDonald做了一个很有趣的项目 —-骰子作画,他用黑底白点的骰子,模拟出一张人像照片。clip_image0011clip_image001

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

clip_image0018

他一共用了2500多颗骰子。

clip_image001101

最后的成品就是这样。

clip_image001121

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

具体来说,

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

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[i];

     }

     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 (x < 206 && x <= 247) return 6;

     else return 6;
}

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

这种算法早在1981年就有人提出,当时用的是1~9个白点的多米诺骨牌。

clip_image00114

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

bg20111126101

此外,不用编程,使用Photoshop也可以得到类似效果。

bg2011112613

 

文章来源:阮一峰的网络日志——骰子作画的算法


欢迎转载,转载请注明出处:蔓草札记 » 骰子作画的算法

♥ 喜欢 0 赞赏
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 很有趣,有很多类似的网站 下面这个网站是计算图片灰度值,用数字或字母来用代替的 http://www.text-image.com/
    CtrlFU5年前 (2011-12-09)回复