摘要:你能否在一个像素平面上提出一个数学-theh算法,这个算法会生成一个中等有趣的图像,最好是一个总体上类似的图像?
到目前为止的故事:
曾几何时,我决定努力减少我(无可否认的)众多计算机上的周期浪费,并着手以适度的方式生成图像。使用PRNG和一些聪明的数学来创建整体上类似于的图像。
或者至少,那是计划。事实证明,聪明的数学需要成为一个聪明的数学家;我不是。
在某种程度上,我找到了一种偏好直线的方法(因为这些通常是我们世界的组成部分),可能过于强烈。结果是温和地有趣;或许像城市网格一样:
City grids, maybe? http://totlandweb.info/imggen.out.png
现在问题是正确的:给出这个小程序的源代码;你可以改进它并提出一种方法,给出更有趣的结果吗? (例如,不是城市网格,但也许是面孔,动物,地理,你有什么)
这也是一种挑战;我想,因此我已经制定了一些完全随意且同样可选的规则:
代码中的注释说明了这一切。建议和“解决方案”应该 编辑算法本身,而不是周围的框架,除了修复 阻止样本编译的错误。
代码应该使用标准问题C编译器干净地编译。 (如果 提供的示例没有,哎呀!告诉我,我会解决的。 :)
该方法应该是可选的,不需要从中获取帮助 您友好的邻居数学图书馆,并且整体上使用(P)RNG作为其 主要数据输入渠道。
解决方案应该可以通过简单地解决之间的任何问题来实现 剪辑线(表示你不应分别在上方和下方编辑的那些), 声明你需要特别添加到序言中的内容。
编辑:有时很容易忘记互联网上的人无法阅读我的内容 心神;但你去了。该计划应该至少需要人为干预 生成图像,除了评估结果并选择最佳 的。
代码需要C编译器和libpng来构建;我不完全相信MinGW编译器提供了必需品,但如果没有,我会感到惊讶。对于Debian,你需要libpng-dev软件包,对于Mac OS X,你需要XCode工具..
源代码可以是downloaded here。
警告:大量代码挥霍传入!
// compile with gcc -o imggen -lpng imggen.c
// optionally with -DITERATIONS=x, where x is an appropriate integer
// If you're on a Mac or using MinGW, you may have to fiddle with the linker flags to find the library and includes.
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#ifdef ITERATIONS
#define REPEAT
#endif // ITERATIONS
// YOU MAY CHANGE THE FOLLOWING DEFINES
#define WIDTH 320
#define HEIGHT 240
// YOU MAY REPLACE THE FOLLOWING DEFINES AS APPROPRIATE
#define INK 16384
void writePNG (png_bytepp imageBuffer, png_uint_32 width, png_uint_32 height, int iteration) {
char *fname;
asprintf(&fname, "out.%d.png", iteration);
FILE *fp = fopen(fname, "wb");
if (!fp) return;
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
png_init_io(png_ptr, fp);
png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, PNG_FILTER_NONE);
png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_rows(png_ptr, info_ptr, imageBuffer);
png_set_invert_mono(png_ptr); /// YOU MAY COMMENT OUT THIS LINE
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
free(fname);
}
int main (int argc, const char * argv[]) {
png_uint_32 height = HEIGHT, width = WIDTH;
int iteration = 1;
#ifdef REPEAT
for (iteration = 1; iteration <= ITERATIONS; iteration++) {
#endif // REPEAT
png_bytepp imageBuffer = malloc(sizeof(png_bytep) * height);
for (png_uint_32 i = 0; i < height; i++) {
imageBuffer[i] = malloc(sizeof(png_byte) * width);
for (png_uint_32 j = 0; j < width; j++) {
imageBuffer[i][j] = 0;
}
}
/// CUT ACROSS THE DASHED LINES
/// -------------------------------------------
/// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED
int ink = INK;
int x = rand() % width, y = rand() % height;
int xdir = (rand() % 2)?1:-1;
int ydir = (rand() % 2)?1:-1;
while (ink) {
imageBuffer[y][x] = 255;
--ink;
xdir += (rand() % 2)?(1):(-1);
ydir += (rand() % 2)?(1):(-1);
if (ydir > 0) {
++y;
} else if (ydir < 0) {
--y;
}
if (xdir > 0) {
++x;
} else if (xdir < 0) {
--x;
}
if (x == -1 || y == -1 || x == width || y == height || x == y && x == 0) {
x = rand() % width; y = rand() % height;
xdir = (rand() % 2)?1:-1;
ydir = (rand() % 2)?1:-1;
}
}
/// NO EDITING BELOW THIS LINE
/// -------------------------------------------
writePNG(imageBuffer, width, height, iteration);
for (png_uint_32 i = 0; i < height; i++) {
free(imageBuffer[i]);
}
free(imageBuffer);
#ifdef REPEAT
}
#endif // REPEAT
return 0;
}
注意:虽然严格来说这个问题似乎并不是“可回答的”;我仍然认为它可以产生一些“正确”的答案。也许
快乐狩猎。
答案 0 :(得分:10)
Fractals?它们不再仅仅用于股票市场分析(Mandelbrot joke,对不起)。
有些Fractal images往往让人联想到现实世界的地理位置。特别是IFS分形可用于相当逼真的plants和trees以及terrain。
fractal.c是一个简单的单色Mandelbrot集,默认为缩放。
添加了:
Context-free语法可用于表达能够绘制出美学上令人愉悦的图像的方程式。 Jared Tarbell有一个由程序生成的一些精彩图像的相关图库。 Aza的Algorithm Ink
第二次补充:
代数或计算艺术的另一种主要形式来自Cellular automaton(CA),例如(John)Conway's Game of Life,由Martin Gardner撰写的1970 Scientific American文章着称。 2002年,斯蒂芬·沃尔夫勒姆(Stephen Wolfram)自我出版A New Kind of Science(NKS),将CA重新引入公众。这些系统往往是封闭的动态系统,基于一套简单的规则“活”或“死”。
与分形相关的是chaotic systems,或非线性动态系统,如果你想听起来很聪明。它们可以在物理系统上建模,例如weather forecasting,并且可以提供非真实随机但难以预测的数字输出,可以将其显示为strange attractor(和SA) 。
答案 1 :(得分:2)
嗯。我记得很久以前在徽标中制作了一个国家发电机。基本的策略是用每种颜色的画家播种它,并有规则,“颜色画家,随机移动,但可能不会在任何被绘制的区域移动,除非它是用自己的颜色绘制的。”结果是几个连续绘制的区域。画家在4个方向上随机移动,网格大小为50x50左右。
一旦完成,我拍摄了我的50x50图像,将它(与最近邻居)扩展为更大的图像,并使用一些标准图形滤镜(模糊等)使其看起来不错。如果你想要一个单色图像,只需将任何边框变成黑色,其他所有边框都变白。
这种策略根本不支持直线。
答案 2 :(得分:2)
你问的问题是审美。一个人认为“好”或“美丽”或“适度有趣”的事物因人而异,我认为不能找到最佳答案。
我知道很多人会发现你在问题中发布的图片令人作呕而且毫无根据,充斥着城市规划的社会政治束缚的想法。但是,我认为它看起来很有趣。
答案 3 :(得分:1)
这可能是解决问题的必然结果,而不是解决问题的方法,但我从不同角度看待同样的想法后看到了有趣的结果:
取一个网格(从正方形,六边形或有你的东西构建它)并在其上生成一个随机的点域。现在,检查使用网格后面的行连接固定点集的所有可能方法。拍摄具有相似主题的图片(例如,树叶)的片段,并将它们转换为“线条艺术”样式以将它们缩小为轮廓。对于每组几个点,查看您的大纲片段库并尝试找到一个可以连接点(或至少靠近,这可能需要旋转,镜像等)。您会发现有无数可能的输出,但如果正确完成,您最终可能会看到许多看似叶子的东西(即使它们是以前从未见过的'新'叶子类型)!
答案 4 :(得分:1)
您可以为行为添加一些琐碎的状态,而不是直接随机性。例如,您可以根据条件方程式选择它们,而不是根据x
y
基本上P
来选择P
和rand % 2
做什么。举个简单的例子:
two-state http://img121.imageshack.us/img121/9018/twostate.png
如果您允许状态1
表示“保持当前路径”并且0
为“更改方向”,则通过调整Q
阈值来控制更改方向的频率。添加状态会增加复杂性,但通过为P
和Q
精心选择的值,您可能会得到适度有趣的结果。
答案 5 :(得分:0)
本着彻底粉碎自己的精神(公认的任意规则,我已经走在前面,自己创造了一个答案!
代码使用了一些非常简单的bezier曲线代码,我昨晚把它拼凑在一起,虽然答案不那么引人注目,但它仍然有点有趣。可以在here和here找到贝塞尔码的代码。
除了编辑剪辑字段外,我当然还添加了
#include "bezier.h"
没有这条线,它不能很好地工作。 ;)
/// NO EDITING ABOVE THIS LINE; EXCEPT AS NOTED
Bezier *path = newBezier(newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height), newPoint(rand() % width,rand() % height));
float t;
Point *point = NULL;
for (t = 0.0; t <= 1.0; t += 0.00000006) {
point = bezierPoint(path, t, point);
int32_t x = point->x, y = point->y;
if (x >= 0 && x < width && y >= 0 && y < height)
imageBuffer[y][x] = 255;
}
destroyPoint(point);
/// NO EDITING BELOW THIS LINE