骰子作画
2015-08-16 18:40
381 查看
阮一峰博客中描述了骰子作画算法。
思想非常简单,也就是矢量量化:将图片分成若干个区域,每个区域经过计算以后,用1-6之间的一个整数表示,代表骰子的一个面,算法总共分4步。
将图片分割成16像素x16像素的小方块。
每个小方块内共有256个像素,将每个像素点的灰度值,存入一个数组。
计算该数组的平均值,并用1-6之间的一个整数来表示。
根据白点值,将骰子依次放入,就能模拟出全图
这种算法与使用的纹理密切相关,纹理越好,越是逼近,另外分割的小块越小越好。我在github上看到了haneuma0628的一个项目ImageToDice,下载下来,修改了一下,可以运行。
注意,该代码只能处理,比较规范大小的图片,比如512*512,若是使用时候需要对边界做一些处理,建议裁剪图像到整数倍。这里使用的纹理图不是很好,影响了效果。这里使用了7个纹理。
另外,和骰子作画很相似的一个算法,是ASCII作画,github上面有源代码。
[thead]
思想非常简单,也就是矢量量化:将图片分成若干个区域,每个区域经过计算以后,用1-6之间的一个整数表示,代表骰子的一个面,算法总共分4步。
将图片分割成16像素x16像素的小方块。
每个小方块内共有256个像素,将每个像素点的灰度值,存入一个数组。
计算该数组的平均值,并用1-6之间的一个整数来表示。
根据白点值,将骰子依次放入,就能模拟出全图
这种算法与使用的纹理密切相关,纹理越好,越是逼近,另外分割的小块越小越好。我在github上看到了haneuma0628的一个项目ImageToDice,下载下来,修改了一下,可以运行。
#include <iostream> #include <math.h> #include <opencv/cv.h> #include <opencv/highgui.h> using namespace cv; using namespace std; Mat trim(Mat src, int mag) { int cutC, cutR; cutC = src.cols % mag; cutR = src.rows % mag; Mat roi; Size rsize(src.cols - cutC, src.rows - cutR); resize(src, roi, rsize, INTER_CUBIC); return roi; } Mat mozaic(Mat src) { int sum = 0, mag = 12; Mat dst(src.size(), src.type()); for (int y = 0; y < src.rows; y += mag) { for (int x = 0; x < src.cols; x += mag) { for (int i = 0; i < mag; i++) { for (int j = 0; j < mag; j++) { sum += src.data[(y + i) * src.step + (x + j)]; } } for (int i = 0; i < mag; i++) { for (int j = 0; j < mag; j++) { dst.data[(y + i) * dst.step + (x + j)] = (int)(sum/(12*12)); } } sum = 0; } } return dst; } int main(int argc, char *argv[]) { string filename = "lena.jpg"; int cnum, rnum, mag = 12, lnum = 7; string fd[7]; Mat dmat[7]; for (int i = 0; i < lnum; i++) fd[i] = to_string((_ULonglong)i) + ".png"; for (int i = 0; i < lnum; i++) dmat[i] = imread(fd[i], 0); Mat src = imread(filename, 0); Mat dst(src.size(), src.type()); src = trim(src, mag); dst = mozaic(src); cnum = src.cols / mag; rnum = src.rows / mag; int *result= new int[rnum*cnum]; Mat *himg = new Mat[cnum]; Mat *vimg = new Mat[rnum]; for (int y = 0; y < src.rows; y += mag) { for (int x = 0; x < src.cols; x += mag) { result[y/mag * rnum + x/mag] = dst.data[(y) * dst.step + (x)]; } } int max = 0, min = 255; for (int i = 0; i < rnum; i++) { for (int j = 0; j < cnum; j++) { if (result[i*rnum+j] >= max) max = result[i*rnum+j]; if (result[i*rnum+j] <= min) min = result[i*rnum+j]; } } int ld; int level[256] = {0}; ld = (int)((max - min) / lnum); int end = 0, cnt = 0; for (int i = max; i > min+ld; i -= ld) { for (int j = 0; j < ld; j++) { level[i-j] = cnt; end = i - j; } cnt++; } while (end >= min) { level[end] = 6; end--; } cnt=0; Mat vdst; for (int i = 0; i < rnum; i++) { for (int j = 0; j < cnum; j++) { himg[j] = imread(fd[level[result[i*rnum+j]]], 0); } hconcat(himg, cnum, vimg[i]); } vconcat(vimg, rnum, vdst); namedWindow("gray", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); imshow("gray", src); namedWindow("mozaic", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); imshow("mozaic", dst); namedWindow("dice", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); imshow("dice", vdst); delete[] himg; delete[] vimg; waitKey(0); }
注意,该代码只能处理,比较规范大小的图片,比如512*512,若是使用时候需要对边界做一些处理,建议裁剪图像到整数倍。这里使用的纹理图不是很好,影响了效果。这里使用了7个纹理。
另外,和骰子作画很相似的一个算法,是ASCII作画,github上面有源代码。
效果
Licenses
作者 | 日期 | 联系方式 |
---|---|---|
风吹夏天 | 2015年8月16日 | wincoder@qq.com |
相关文章推荐
- 2.6/ 7 精确表示浮点数 + 最大公约数
- python抓取网页的一个小例子
- webservice 小记
- LOJ 1201 - A Perfect Murder(二分匹配 最大独立集)
- HDU 4303 Hourai Jeweled 树dp 所有权利和航点 dfs2次要
- (3)java棧
- ehcache集群详解二(集群的最小配置)
- cacti的搭建
- 欧拉(回)路
- 解决点击状态栏时ScrollView自动滚动到初始位置失效办法
- android-ndk 数据传递
- 苹果开发者账号的类型
- 微信公众号开发系列-网页授权获取用户基本信息
- 安卓飞机大战(六) 动态Gif图的添加
- Linux 下 安装 PHP 的 PDO_MYSQL 扩展
- Unknown Switches 模拟
- TextView加载Html内容(自定义TextView)
- (Windows)Zookeeper安装
- CocoaPods 配置环境遇到的 一些问题总结
- 利用jenv安装maven, tomcat,zookeeper等