算法:如何用骰子作画?

点击上方 "程序员小乐" ,关注公众号

8点20分,第一时间与你相约

每日英文

Never give up on something you really want. It’s difficult to wait, but worse to regret.

永远不要放弃你真正想要的东西。等待虽难,但后悔更甚。


每日掏心话

有什么信念,就选择什么态度;有什么态度,就会有什么行为;有什么行为,就产生什么结果。要想结果变得好,必须选择好的信念。


来自:阮一峰 | 责编:乐乐

链接:ruanyifeng.com/blog/2011/11/dice_portrait.html

640?wx_fmt=jpeg

图片来自网络



   正文   



给大家分享一个有趣的项目---骰子作画。


程序员 Scott MacDonald 做了一个很有趣的项目----骰子作画。


他用黑底白点的骰子。

640?wx_fmt=png

模拟出一张人像照片。


640?wx_fmt=png


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


640?wx_fmt=png


他一共用了2500多颗骰子。


640?wx_fmt=png


最后的成品就是这样。


640?wx_fmt=png


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


 
   


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


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


640?wx_fmt=png

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


640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=png


640?wx_fmt=png


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


640?wx_fmt=png

欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。


欢迎各位读者加入程序员小乐技术群,在公众号后台回复“加群”或者“学习”即可。

640?wx_fmt=png


猜你还想看


阿里、腾讯、百度、华为、京东最新面试题汇集

统一异常处理介绍及实战,看了都说好!

高中就开始学的正态分布,原来如此重要

什么?黑科技?Android 可以异步加载布局?

百度地震了,也许早晚的事

看完感觉我 RecyclerView 白学了!

640?wx_fmt=png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值