Randomness of Python's random

Randomness of Python's random

I'm using Python to generate images using dashed lines for stippling. The period of the dashing is constant, what changes is dash/space ratio. This produces something like this:

I'm using Python to generate images using dashed lines for stippling. The period of the dashing is constant, what changes is dash/space ratio. This produces something like this:

However in that image the dashing has a uniform origin and this creates unsightly vertical gutters. So I tried to randomize the origin to remove the gutters. This sort of works but there is an obvious pattern:

Wondering where this comes from I made a very simple test case with stacked dashed straight lines:

  • dash ratio: 50%
  • dash period 20px
  • origin shift from -10px to +10px using random.uniform(-10.,+10.)(*) (after an initial random.seed()

And with added randomness:

So there is still pattern. What I don't understand is that to get a visible gutter you need to have 6 or 7 consecutive values falling in the same range (says, half the total range), which should be a 1/64 probability but seems to happen a lot more often in the 200 lines generated.

Am I misunderstanding something? Is it just our human brain which is seeing patterns where there is none? Could there be a better way to generate something more "visually random" (python 2.7, and preferably without installing anything)?

(*) partial pixels are valid in that context

Annex: the code I use (this is a Gimp script):

#!/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

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Basic Data Types in Python | Python Web Development For Beginners

In the programming world, Data types play an important role. Each Variable is stored in different data types and responsible for various functions. Python had two different objects, and They are mutable and immutable objects.

How To Compare Tesla and Ford Company By Using Magic Methods in Python

Magic Methods are the special methods which gives us the ability to access built in syntactical features such as ‘<’, ‘>’, ‘==’, ‘+’ etc.. You must have worked with such methods without knowing them to be as magic methods. Magic methods can be identified with their names which start with __ and ends with __ like __init__, __call__, __str__ etc. These methods are also called Dunder Methods, because of their name starting and ending with Double Underscore (Dunder).

Python Programming: A Beginner’s Guide

Python is an interpreted, high-level, powerful general-purpose programming language. You may ask, Python’s a snake right? and Why is this programming language named after it?

Hire Python Developers

Are you looking for experienced, reliable, and qualified Python developers? If yes, you have reached the right place. At **[HourlyDeveloper.io](https://hourlydeveloper.io/ "HourlyDeveloper.io")**, our full-stack Python development services...

Python any: How to Check If Element is Iterable or Not

Python any() function returns True if any element of an iterable is True otherwise any() function returns False. The syntax is any().