basic of image dithering Is just read about image-dithering ? So I tried to implement that. Here is my result. Can someone verify it?

My code :

import numpy as np
from numpy.random import default_rng
import matplotlib.pyplot as plt

n = 300
real = np.random.randint(low = 0, high=256, size=(n,n), dtype='l')
#print(real)

dn = 3
rng = default_rng()
dither = rng.choice(dn*dn, size=(dn,dn), replace=False)
print(dither)

res = np.zeros((n,n))
for y in range (0,n):
    for x in range (0,n):
        i = x % dn
        j = y % dn
        res[x][y] = 255 if (real[x][y] &gt; dither[i][j]) else 0
#print(res)


fig = plt.figure()

ax1 = plt.subplot(1, 3, 1)
ax1.title.set_text('Real Image(300x300)')
plt.imshow(real, cmap="gray")

ax2 = plt.subplot(1, 3, 2)
ax2.title.set_text('Dithering Matrix(3x3)')
plt.imshow(dither, cmap="gray")

ax3 = plt.subplot(1, 3, 3)
ax3.title.set_text('Resultant Image(300x300)')
plt.imshow(res, cmap="gray")

plt.show()


reduced value of  n to 6, so that image may become easily understandable.

Result :
There is a small issue in the original code. Indeed, real array values ranging between [0, 255]. However, the mask values ranging between [0, 3*3] (as dn = 3 in the example above).

After fixing the issue:


The correct code (with image reading and all data normalized between [0, 1.0]):

import numpy as np
from numpy.random import default_rng
import matplotlib.pyplot as plt
from PIL import Image

# Read an image from the disk
real = Image.open("example.jpeg")
real = np.array(real) / 255.0
# If it is a RGB image, transform it to a gray image
# TODO: Could use any function (like luminance)
real = (real[:,:,0] + real[:,:,1] + real[:,:,2]) / 3.0

# Create the mask by shuffling
dn = 6
rng = default_rng()
# In the original code, there was a problem here.
# Indeed, the mask values ranging between [0, dn*dn]
# So the generated mask needs to be properly normalized
dither = rng.choice(dn*dn, size=(dn,dn), replace=False) / float(dn*dn)
print(dither)

# Generate the results
res = np.zeros_like(real)
width, height = res.shape[1], res.shape[0]
for y in range (0,width):
    for x in range (0,height):
        i = x % dn
        j = y % dn
        res[x][y] = 1.0 if (real[x][y] &gt; dither[i][j]) else 0.0

# Display the result
fig = plt.figure()
ax1 = plt.subplot(1, 3, 1)
ax1.title.set_text('Real Image(300x300)')
plt.imshow(real, cmap="gray")
ax2 = plt.subplot(1, 3, 2)
ax2.title.set_text('Dithering Matrix(3x3)')
plt.imshow(dither, cmap="gray")
ax3 = plt.subplot(1, 3, 3)
ax3.title.set_text('Resultant Image(300x300)')
plt.imshow(res, cmap="gray")
plt.show()