为什么在使用rand()时会得到这种特殊的颜色模式? [英] Why do I get this particular color pattern when using rand()?

查看:194
本文介绍了为什么在使用rand()时会得到这种特殊的颜色模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个图像文件,如下所示:

I tried to create an image file, like this:

uint8_t raw_r[pixel_width][pixel_height];
uint8_t raw_g[pixel_width][pixel_height];
uint8_t raw_b[pixel_width][pixel_height];
uint8_t blue(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x+y)%rand() : ((x*y%1024)%rand())%2 ? (x-y)%rand() : rand();
}
uint8_t green(uint32_t x, uint32_t y)
{
    return (rand()%2)? (x-y)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}
uint8_t red(uint32_t x, uint32_t y)
{
    return (rand()%2)? (y-x)%rand() : ((x*y%1024)%rand())%2 ? (x+y)%rand() : rand();
}

for (y=0; y<pixel_height; ++y)
{
    for (x=0; x<pixel_width; ++x)
    {
        raw_b[x][y]=blue(x, y);
        raw_g[x][y]=green(x, y);
        raw_r[x][y]=red(x, y);
    }
}

我希望得到一些随机的东西(白噪声).但是,输出很有趣:

I expected to get something random (white noise). However, the output is interesting:

你知道为什么吗?

现在,很明显,它与rand()没有关系.

Now, it is clear that it has nothing to do with rand().

也请尝试以下代码:

for (x=0; x<pixel_width; ++x)
    for (y=0; y<pixel_height; ++y)
    {
        r[x][y] = (x+y);
        g[x][y] = (y-x);
        /* b[x][y] = rand()%2? x : y; */
    }

推荐答案

最初,我将获得与其他所有人相同的答案,并将其归因于rand()的问题.但是,我认为这样做更好,而是分析了您的数学实际产生的分布.

I was initially going to have the same answer as everyone else had and chalk this up to the issues with rand(). However, I thought better of doing so and instead analyzed the distribution your math is actually producing.

TL; DR:您看到的模式与底层随机数生成器无关,而仅仅是由于程序处理数字的方式.

TL;DR: The pattern you see has nothing to do with the underlying random number generator and instead is simply due to the way your program is manipulating the numbers.

我将继续使用您的蓝色功能,因为它们都很相似.

I'll stick to your blue function since they're all similar.

uint8_t blue(uint32_t x, uint32_t y) {
    return (rand() % 2)                  ? (x + y) % rand() :
           ((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
                                           rand();
}

每个像素值均选自以下三个功能之一:(x + y) % rand()(x - y) % rand()rand();

Each pixel value is selected from one of three functions: (x + y) % rand(), (x - y) % rand(), and rand();

让我们看看它们单独产生的图像.

Let's look at images produced by each of these alone.

  • rand()

这就是您所期望的,只是噪音.将此称为图片C"

This is what you would expect, just noise. Call this "Image C"

  • (x + y) % rand()

在这里,您要将像素坐标加在一起,然后将其余部分除以随机数.如果图像为1024x1024,则总和在[0-2046]范围内.您要通过的随机数范围为[0,RAND_MAX],其中RAND_MAX至少为32k,在某些系统上为20亿.换句话说,最多有十分之一的机会,其余的不仅仅是(x + y).因此,在大多数情况下,此功能只会产生向+ x + y方向递增的蓝色渐变.

Here you're adding the pixel coordinates together and taking the remainder from dividing by a random number. If the image is 1024x1024 then the sum is in the range [0-2046]. The random number you're diving by is in the range [0,RAND_MAX], where RAND_MAX is at least 32k and on some systems is 2 billion. In other words there's at best a 1 in 16 chance that the remainder isn't just (x + y). So for the most part this function will just produce a gradient of increasing blue toward the +x +y direction.

但是您只使用最低的8位,因为您返回了uint8_t,因此您将拥有256像素宽的渐变条纹.

However you're only using the lowest 8 bits, because you return a uint8_t, so you'll have stripes of gradients 256 pixels wide.

将此称为图片A"

  • (x - y) % rand()

在这里您执行类似的操作,但要减去.只要x大于y,您将拥有与上一张图像相似的图像.但是在y较大的情况下,结果是一个非常大的数字,因为xy是无符号的(负结果环绕在无符号类型范围的顶部),然后% rand()插入,您实际上发出声音.

Here you do something similar, but with subtraction. As long as x is greater than y you'll have something similar to the previous image. But where y is greater, the result is a very large number because x and y are unsigned (negative results wrap around to the top of the unsigned type's range), and then the the % rand() kicks in and you actually get noise.

将其称为图片B"

使用功能rand() % 2((x * y % 1024) % rand()) % 2从这三个图像之一中获取最终图像中的每个像素.其中的第一个可以理解为以50%的概率进行选择(忽略rand()及其低阶位的问题.)

Each pixel in your final image is taken from one of these three images using functions rand() % 2 and ((x * y % 1024) % rand()) % 2. The first of these can be read as choosing with 50% probability (ignoring issues with rand() and its low order bits.)

下面是rand() % 2为真(白色像素)的特写,因此选择了图像A.

Here's a closeup of where rand() % 2 is true (white pixels) so Image A is selected.

第二个函数((x * y % 1024) % rand()) % 2再次遇到一个问题,其中rand()通常大于您要划分的对象(x * y % 1024),最多为1023.然后(x*y%1024)%2不会相等地产生0和1经常.任何奇数乘以任何偶数就是偶数.任何偶数乘以任何偶数也是偶数.只有奇数乘以一个奇数才是奇数,因此%2在四分之三时间的值上将四分之三的时间产生0.

The second function ((x * y % 1024) % rand()) % 2 again has the issue where rand() is usually greater than the thing you're dividing, (x * y % 1024), which is at most 1023. Then (x*y%1024)%2 doesn't produce 0 and 1 equally often. Any odd number multiplied by any even number is even. Any even number multiplied by any even number is also even. Only an odd number multiplied by an odd number is odd, and so %2 on values that are even three quarters of the time will produce 0 three quarters of the time.

这里是((x * y % 1024) % rand()) % 2正确的地方的特写镜头,因此可以选择图像B.正是在选择两个坐标都是奇数的地方.

Here's a closeup of where ((x * y % 1024) % rand()) % 2 is true so that Image B could be selected. It's selecting exactly where both coordinates are odd.

这是可以选择图像C的特写:

And here's a closeup of where Image C could be selected:

最后结合条件,在这里选择了图像B:

Finally combining the conditions here's where Image B is selected:

在选择图片C的地方:

生成的组合可以读取为:

The resulting combination can be read as:

以50%的概率使用图像A中的像素.其余时间在图像B和图像C之间选择,两个坐标均为奇数的B,两个坐标均为偶数的C.

With 50% probability use the pixel from Image A. The rest of the time pick between Image B and Image C, B where both coordinates are odd, C where either one is even.

最后,由于您要对三种不同的颜色进行相同的操作,但方向不同,因此每种颜色的图案取向不同,并会产生您所看到的交叉带或网格图案.

Finally, since you're doing the same for three different colors, but with different orientations the patterns are oriented differently in each color and produce the crossing strips or grid pattern you're seeing.

这篇关于为什么在使用rand()时会得到这种特殊的颜色模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆