骰子作畫的算法

jopen 13年前發布 | 38K 次閱讀 算法

程序員 Scott MacDonald 做了一個很有趣的項目---- 骰子作畫

他用黑底白點的骰子。

模擬出一張人像照片。

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

他一共用了2500多顆骰子。

最后的成品就是這樣。

任何一張圖片都可以用骰子模擬出來,算法非常簡單:將圖片分成若干個區域,每個區域經過計算以后,用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之間的一個整數來表示。

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個白點的多米諾骨牌。

如果區域劃分得越小,模擬圖的生成效果就越好。

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

來自: 阮一峰的網絡日志

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!