Python的随机性是随机的

问题描述 投票:65回答:4

我正在使用Python生成图像,使用虚线进行点画。潇洒的时期是恒定的,什么变化是破折号/空间比。这产生了这样的东西:

enter image description here

然而,在该图像中,潇洒具有均匀的原点,这产生难看的垂直檐槽。所以我试着将原点随机化以去除排水沟。这种作品有一个明显的模式:

enter image description here

想知道这是从哪里来的,我做了一个非常简单的测试用例,带有叠加的虚线直线:

  • 破折号:50%
  • 冲刺期20px
  • 使用random.uniform(-10.,+10.)(*)将原点从-10px转换为+ 10px(在最初的random.seed()之后)

enter image description here

并增加了随机性:

enter image description here

所以还有模式。我不明白的是,要获得一个可见的排水沟,你需要有6或7个连续的值落在相同的范围内(说,总范围的一半),这应该是1/64的概率,但似乎发生了很多更经常在200行中生成。

我误会了什么吗?只是我们的人类大脑才能看到没有的模式吗?有没有更好的方法来生成更“视觉上随机”的东西(python 2.7,最好没有安装任何东西)?

(*)部分像素在该上下文中有效

附件:我使用的代码(这是一个Gimp脚本):

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

# Python script for Gimp (requires Gimp 2.10)
# Run on a 400x400 image to see something without having to wait too much
# Menu entry is in "Test" submenu of image menubar

import random,traceback
from gimpfu import *

def constant(minShift,maxShift):
    return 0

def triangle(minShift,maxShift):
    return random.triangular(minShift,maxShift)

def uniform(minShift,maxShift):
    return random.uniform(minShift,maxShift)

def gauss(minShift,maxShift):
    return random.gauss((minShift+maxShift)/2,(maxShift-minShift)/2)

variants=[('Constant',constant),('Triangle',triangle),('Uniform',uniform),('Gauss',gauss)]

def generate(image,name,generator):
    random.seed()
    layer=gimp.Layer(image, name, image.width, image.height, RGB_IMAGE,100, LAYER_MODE_NORMAL)
    image.add_layer(layer,0)
    layer.fill(FILL_WHITE)
    path=pdb.gimp_vectors_new(image,name)

    # Generate path, horizontal lines are 2px apart, 
    # Start on left has a random offset, end is on the right edge right edge
    for i in range(1,image.height, 2):
        shift=generator(-10.,10.)
        points=[shift,i]*3+[image.width,i]*3
        pdb.gimp_vectors_stroke_new_from_points(path,0, len(points),points,False)
    pdb.gimp_image_add_vectors(image, path, 0)

    # Stroke the path
    pdb.gimp_context_set_foreground(gimpcolor.RGB(0, 0, 0, 255))
    pdb.gimp_context_set_stroke_method(STROKE_LINE)
    pdb.gimp_context_set_line_cap_style(0)
    pdb.gimp_context_set_line_join_style(0)
    pdb.gimp_context_set_line_miter_limit(0.)
    pdb.gimp_context_set_line_width(2)
    pdb.gimp_context_set_line_dash_pattern(2,[5,5])
    pdb.gimp_drawable_edit_stroke_item(layer,path)

def randomTest(image):
    image.undo_group_start()
    gimp.context_push()

    try:
        for name,generator in variants:
            generate(image,name,generator)
    except Exception as e:
        print e.args[0]
        pdb.gimp_message(e.args[0])
        traceback.print_exc()

    gimp.context_pop()
    image.undo_group_end()
    return;

### Registration
desc="Python random test"

register(
    "randomize-test",desc,'','','','',desc,"*",
    [(PF_IMAGE, "image", "Input image", None),],[],
    randomTest,menu="<Image>/Test",
)

main()
python random
4个回答
46
投票

可以这样想:在它被阻挡(或几乎如此)之前,沟槽是可感知的。这只发生在两条连续的线几乎完全异相的情况下(第一条线中的黑色区段几乎位于下一条线的白色区段上方)。这种极端情况仅发生在每10行中的一行中,因此可见的排水沟在被阻挡之前似乎延伸约10行。

看另一种方式 - 如果你打印出图像,那里确实有很长的白色通道,通过它可以轻松地用笔画线。为什么你的头脑不会察觉到它们?

为了获得更好的视觉随机性,找到一种方法来使连续的线依赖而不是独立,以便更频繁地出现几乎异相的行为。


27
投票

我们在“随机”图片中看到一个模式至少有一个明显的原因:400x400像素是重复20次的20x400像素。

enter image description here

因此,每个明显的运动平行重复20次,这真的有助于大脑分析图像。

实际上,相同的10px宽图案重复40次,在黑色和白色之间交替:

enter image description here

您可以为每一行单独随机化短划线时段(例如,在12到28之间):

enter image description here

这是相应的代码:

import numpy as np
import random

from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [13, 13]

N = 400

def random_pixels(width, height):
    return np.random.rand(height, width) < 0.5

def display(table):
    plt.imshow(table, cmap='Greys', interpolation='none')
    plt.show()

display(random_pixels(N, N))

def stripes(width, height, stripe_width):
    table = np.zeros((height, width))
    cycles = width // (stripe_width * 2) + 1
    pattern = np.concatenate([np.zeros(stripe_width), np.ones(stripe_width)])
    for i in range(height):
        table[i] = np.tile(pattern, cycles)[:width]
    return table

display(stripes(N, N, 10))

def shifted_stripes(width, height, stripe_width):
    table = np.zeros((height, width))
    period = stripe_width * 2
    cycles = width // period + 1
    pattern = np.concatenate([np.zeros(stripe_width), np.ones(stripe_width)])
    for i in range(height):
        table[i] = np.roll(np.tile(pattern, cycles), random.randrange(0, period))[:width]
    return table

display(shifted_stripes(N, N, 10))

def flexible_stripes(width, height, average_width, delta):
    table = np.zeros((height, width))
    for i in range(height):
        stripe_width = random.randint(average_width - delta, average_width + delta)
        period = stripe_width * 2
        cycles = width // period + 1
        pattern = np.concatenate([np.zeros(stripe_width), np.ones(stripe_width)])
        table[i] = np.roll(np.tile(pattern, cycles), random.randrange(0, period))[:width]
    return table

display(flexible_stripes(N, N, 10, 4))

8
投票

发布我的最终解决方案作为答案,但请提升其他人。

当约翰科尔曼说:

为了获得更好的视觉随机性,找到一种方法来使连续的线依赖而不是独立,以便更频繁地出现几乎异相的行为。

因此,最后,避免排水沟的最佳方法是放弃随机性并采用非常固定的轮班方案,而且运行良好的方法是4阶段0,25%,75%,50%周期:

enter image description here

好吧,仍然有轻微的钻石图案,但它比我尝试的随机方案引入的图案更不明显。


7
投票

这有点违反直觉,但随着随机元素的加入,随机性变得越来越小。如果我正确地遵循每个元素的范围是10px - 30px。所以10个元素的总大小是100px到300px,但是在该范围内的分布甚至都不是。极端情况非常不可能,平均而言将非常接近200px,因此将出现基本的20px模式。您的随机分布需要避免这种情况。

编辑:我看到我有点误解,所有破折号都是20px随机偏移。因此,我认为查看任何一个垂直的破折号组都会出现随机,但是在整个页面上重复相同的随机集,给出了模式。

© www.soinside.com 2019 - 2024. All rights reserved.