2
\$\begingroup\$

In mathematics, the Thue–Morse sequence, or Prouhet–Thue–Morse sequence, is the binary sequence (an infinite sequence of 0s and 1s) obtained by starting with 0 and successively appending the Boolean complement of the sequence obtained thus far.

Wikipedia Page

I wanted to create images using the Thue–Morse sequence, my idea is very simple, since the sequence is binary, group each eight bits into a byte, and then each three bytes into a pixel, and then make the list of pixels two-dimensional, done.

It is indeed that simple, but the result is of low contrast, so I increased contrast after the image was created.

enter image description here


Code

import numpy as np
from PIL import Image, ImageEnhance
from typing import List
def abbabaab(n: int) -> str:
 return "".join(str(i.bit_count() % 2) for i in range(n))
def Thue_Morse(n: int) -> str:
 s = [0]
 for _ in range(n):
 s += [i ^ 1 for i in s]
 return "".join(map(str, s))
def abbabaab_list(n: int) -> List[int]:
 return [i.bit_count() % 2 for i in range(n)]
def abbabaab_array(n: int) -> np.array:
 bits = np.unpackbits(np.arange(n).view(np.uint8))
 bits = bits.reshape((n, bits.shape[0] // n))
 return np.sum(bits, axis=1) % 2
def Thue_Morse_array(n: int) -> np.array:
 s = np.array([False], dtype=bool)
 for _ in range(n):
 s = np.concatenate([s, s ^ True])
 return s
def log2_ceil(n: int) -> int:
 log = n.bit_length()
 return log - (1 << log - 1 == n)
def Thue_Morse_image(width: int, height: int) -> Image:
 total = width * height * 24
 pixels = Thue_Morse_array(log2_ceil(total))[:total].reshape((total // 8, 8))
 pixels = np.sum(pixels * 1 << np.arange(8)[::-1], axis=1)
 img = Image.fromarray(pixels.reshape((height, width, 3)).astype(np.uint8))
 return ImageEnhance.Contrast(img).enhance(4)
def Thue_Morse_grayscale(width: int, height: int) -> Image:
 total = width * height
 pixels = Thue_Morse_array(log2_ceil(total))[:total].reshape((height, width))
 return Image.fromarray(pixels)
def main(width: str, height: str, path: str, grayscale: str = '') -> None:
 [Thue_Morse_image, Thue_Morse_grayscale][bool(grayscale)](int(width), int(height)).save(path)
if __name__ == "__main__":
 import sys
 main(*sys.argv[1:])

As you can see I have found three ways to generate the sequence, and this is the first time I have utilized NumPy thoroughly to do something.

How can it be improved?


Edit

I removed a bug where the array generation will run for one extra iteration if the number is extractly a power of 2. I also added a grayscale version of image creation function.

enter image description here

asked Jun 6, 2023 at 19:40
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.