0

I'm not trying to make a QR code, but I am looking to make a similar type of style that is generated multiple times as an image.

This is a brief example of one of these images: it should be able to be generated randomly

Also, id also like for a chance for a how many pixels it will generate. e.g. 9 pixels = 6% chance, 18 pixels = 30% chance etc.

Thanks

wdp
  • 13
  • 3
  • Your question is not very clear about the chances of number of pixels - please click [edit] and try to improve it. What are the chances of other sizes? Is there some list of possible sizes? If it decides to generate 18 pixels, is that 6x3, or 3x6, or 9x2, or 2x9, or 18x1... – Mark Setchell Apr 17 '22 at 10:55
  • @wdp, Sorry for asking... Can you please give some feedback to my answer? – Rotem Apr 25 '22 at 17:56

2 Answers2

1
from PIL import Image
import numpy as np
size = (50,50)
threshold = 0.5 #Chance of a pixel being white
a = np.random.uniform(0, 1, size=size)
a[a>threshold] = 0
a[a>0] = 255
im = Image.fromarray(a, mode='F')
save_path = "" #Path to save the image
im.save(rf'{save_path}'+'.tiff')

Output:

enter image description here

Nin17
  • 2,821
  • 2
  • 4
  • 14
  • Thanks! But there is a problem, the image is low resolution, and when the size is increased the pixels are too small for my likings, any work around for this? – wdp Apr 16 '22 at 13:36
  • Save it as a PNG or a TIFF – Nin17 Apr 16 '22 at 14:31
  • @wdp I've changed it to provide a TIFF output which should be better resolution. – Nin17 Apr 16 '22 at 17:56
1

Basic concept:

  • Create small resolution image with random 0 and 255 values.
  • Resize the small image with NEAREST interpolation.

Setting the probabilities is not very clear from the question.
I tried creating a look up table that converts from from probability percent to the percentage of white pixels.
I used Cubic spline data interpolation in MATLAB, but the result is not good enough.
I leave you the job of tuning it (you may also find a formula instead).

Here is the list of stages:

  • Create uniformly random distribution "small image" (size 9x9 for example).

     rand_img = np.random.rand(rows, cols)
    
  • Draw a random number in range [0, 1], and convert it to percentage (multiply by 100).
    The percentage of white pixel is defined by that random number.

     p = round(random.random()*100)
    
  • Pass p through look up table P and get a threshold.
    The look up tables get a probability in percentage, and return the percentage of destination white pixels.
    Divide the result by 100 to convert from percentage to range [0, 1].

     thresh = P[p] / 100  # Pass through lookup table, and convert to threshold in range [0, 1]
    
  • Set all pixel below thresh to True, and above it to False.
    Convert True to 255 and False to 0.

     samll_img = rand_img < thresh
     samll_img = samll_img.astype(np.uint8)*255
    
  • Resize the binary image with interpolation=cv2.INTER_NEAREST:

     img = cv2.resize(samll_img, (samll_img.shape[1]*18, samll_img.shape[0]*18), interpolation=cv2.INTER_NEAREST)
    

Complete code sample:

import cv2
import numpy as np
import random

# Assume each square is 18x18, and 9x9 squares and image is 162x162

cols, rows = 9, 9

# Chance for a how many pixels it will generate. e.g. 9 pixels = 6% chance, 18 pixels = 30% chance etc.
# 9 pixels is 9/(18*18) = about 3% of total pixels - change for 0.03 should be 6%
# 18 pixels is 18/(18*18) = about 6% of total pixels - change for 0.06 should be 18%

# List of probabilities (I don't know exactly how to tune it) - used as look up table.
P = [0,   1,   3,   6,  10,  14,  18,  22,  26,  29,  33,  36,  39,  41,  44,  46,  48,  50,  52,  54,  55,  57,  58,  59,  60,  60,  61,  61,  62,  62,  62,  62,  62,  62,  62,  61,  61,  61,  60,  59,  59,  58,  57,  56,  56,  55,  54,  53,  52,  51,  50,  49,  48,  47,  46,  45,  44,  44,  43,  42,  41,  41,  40,  39,  39,  39,  38,  38,  38,  38,  38,  38,  38,  39,  39,  40,  40,  41,  42,  43,  45,  46,  48,  50,  52,  54,  56,  59,  61,  64,  67,  71,  74,  78,  82,  86,  90,  94,  97,  99, 100]

rand_img = np.random.rand(rows, cols)  # Uniform random distribution 9x9 pixels.

p = round(random.random()*100)  # Get a random number in percentage.
thresh = P[p] / 100  # Pass through lookup table, and convert to threshold in range [0, 1]

# All pixel below thresh are True, and above  it are False.
samll_img = rand_img < thresh
samll_img = samll_img.astype(np.uint8)*255  # Convert True to 255 and False to 0

# Resize the image by x18 in each axis
img = cv2.resize(samll_img, (samll_img.shape[1]*18, samll_img.shape[0]*18), interpolation=cv2.INTER_NEAREST)

cv2.imwrite('img.png', img)  # Save image for testing

Few output samples:
enter image description here


enter image description here


enter image description here

Rotem
  • 30,366
  • 4
  • 32
  • 65