我正在使用Python使用虚线为点画生成图像。破折号的周期是恒定的,改变的是破折号/空间比。产生这样的东西:
但是,在该图像中,虚线的起点是一致的,这会产生难看的垂直槽。因此,我尝试将原点随机化以去除排水沟。这种工作,但是有一个明显的模式:
想知道这是从哪里来的,我做了一个非常简单的测试用例,它用了堆积的虚线:
random.uniform(-10.,+10.)
(*)(在最初的random.seed()
之后,原点从-10px变为+ 10px 并增加了随机性:
因此仍然存在模式。我不明白的是,要获得可见的装订线,您需要使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()
答案 0 :(得分:46)
这样想:直到排水沟被阻塞(或几乎被阻塞),才可以察觉。仅当两条连续的线几乎完全异相时才发生这种情况(第一行中的黑色线段几乎位于下一条白色线段的上方)。这样的极端情况每10行中只有大约1行发生,因此可见的排水沟似乎在绕行10行之前就被阻塞了。
从另一种角度来看-如果您打印出图像,则确实存在较长的白色通道,您可以通过这些通道轻松地用笔画一条线。为什么您的大脑不应该感知它们?
要获得更好的视觉随机性,请找到一种使连续的行依赖而不是独立的方式,这种方式使得几乎异相的行为更经常出现。
答案 1 :(得分:27)
我们在“随机”图片中看到图案至少有一个明显的原因:400x400像素与20x400像素重复20次相同。
因此,每个明显的动作都平行重复20次,这确实有助于大脑分析图片。
实际上,相同的10px宽的图案会重复40次,黑白交替:
您可以为每行分别随机设置破折号(例如12到28之间):
这是相应的代码:
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))
答案 2 :(得分:8)
发布我的最终解决方案作为答案,但请支持其他人。
约翰·科尔曼(John Coleman)说:
要获得更好的视觉随机性,请找到一种方法,使连续的行相互依存,而不是相互独立,从而使几乎异相的行为更加频繁出现。
因此,最后,避免发生装订线的最佳方法是放弃随机性,并采用非常固定的移位方案,而效果较好的方案是4相0.25%,75%,50%循环:>
好的,仍然有轻微的菱形图案,但是它比我尝试的随机方案引入的图案更不可见。
答案 3 :(得分:7)
这有点违反直觉,但是当您将随机元素加在一起时,随机性就会变小。如果我正确遵循,则每个元素的范围是10px-30px。因此,10个元素的总大小为100像素到300像素,但是分布甚至不在该范围内。极端情况不太可能出现,平均而言,它将接近200像素,因此将出现基本的20像素模式。您的随机分布需要避免这种情况。
编辑:我看到我有点误解了,所有的破折号都是20px,带有随机偏移。因此,我认为查看任意1个垂直破折号看起来都是随机的,但是在页面上重复相同的随机破折号,得到了图案。