<jupyter_start><jupyter_text>Table of Contents 1&nbsp;&nbsp;Many ways to create a chess-like image in Python/Numpy1.1&nbsp;&nbsp;Programming styles1.1.1&nbsp;&nbsp;C style programming1.1.2&nbsp;&nbsp;Image coordinates1.1.3&nbsp;&nbsp;Image coordinates and broadcast1.1.4&nbsp;&nbsp;List implicit loop (list comprehension)1.1.5&nbsp;&nbsp;Slice1.1.6&nbsp;&nbsp;Line and column replication1.1.7&nbsp;&nbsp;Tile1.1.8&nbsp;&nbsp;Resize1.2&nbsp;&nbsp;Comparing execution times1.3&nbsp;&nbsp;Conclusions  Many ways to create a chess-like image in Python/NumpyThis demonstration illustrates many different ways to create a chess-like image in Python.Each way has a different concept, but most of them uses the property that each pixel is 0or 1 depending if the sum of its coordinates is even or odd.The most efficient way is the technique using slices and the most general one is the one that uses indices.These examples below is a good introduction to program Python efficiently for image processing applications and verify that processing arrays in Python is very efficient.The image that we want to generate can be describe in the following equation:$$   f(row,col) = (row+col) \bmod 2 $$  Programming stylesWe show below seven different programs, some very efficient as uses intrinsic implementation in NumPy, others not so efficient.<jupyter_code>import numpy as np<jupyter_output><empty_output><jupyter_text>C style programmingThis is the traditional way that a C programmer would solve the problem - scanevery pixel and apply the equation.<jupyter_code>def chessCstyle(H,W):
   f = np.empty((H,W),'uint8')
   for row in range(H):
     for col in range(W):
       f[row,col] = (row+col)%2
   return f

print("C Style:\n", chessCstyle(4,8))<jupyter_output>C Style:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>Image coordinatesThis is a general way to create images when we can write the equation of each pixel valuebased on its coordinates. The function *indices* is very handy to create arrays of each coordinatemake possible the array processing of the whole image without the explicit scanning of the pixels in the image.<jupyter_code>def chessIndice(H,W):
    row,col = np.indices((H,W), 'uint16')
    return (row+col)%2

print("Indices:\n", chessIndice(4,8))<jupyter_output>Indices:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>Image coordinates and broadcastIn the previous indices example, the arrays row and col are two-dimensional arrays. It is possible touse the broadcast facility of NumPy. We create a row as one column 2D array and col as a one row 2D arrayand let the arithmetic operation create the full 2D array using broadcast.<jupyter_code>def chessIndiceBroad(H,W):
    row = np.arange(H).reshape(H,1).astype('uint16')
    col = np.arange(W).reshape(1,W).astype('uint16')
    return (row+col)%2

print("IndiceBroad:\n", chessIndiceBroad(4,8))<jupyter_output>IndiceBroad:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>List implicit loop (list comprehension)This solution uses the native implicit loop in list generation.The list is then converted to array.<jupyter_code>import numpy as np
def chessIter(H,W):
   f = [[ (row+col)%2 for col in range(W) ] for row in range(H) ]
   return np.array(f,'uint8')

print("Iter:\n", chessIter(4,8))<jupyter_output>Iter:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>SliceSlicing is a powerful index access to elements of an array available in *numpy*.This solution is one of the most efficient. The image is initially create with zeros andlater filled with ones in the even lines and after in odd lines, always scanning the imageevery two pixels.<jupyter_code>def chessSlice(H,W):
    f = np.zeros((H,W), 'uint8')
    f[0::2,1::2] = 1
    f[1::2,0::2] = 1
    return f

print("Slice:\n", chessSlice(4,8))<jupyter_output>Slice:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>Line and column replicationThis solution has three main parts: in the first a 4 pixel basic pattern is created; in the secondthis pattern is replicated line-wise and the last and third part, the replication is done column-wise.Use the functions *vstack* and *hstack*.<jupyter_code>def chessRep(H,W):
    p = np.array([[0,1],
                  [1,0]],'uint8')
    fCol = p 

    # First column
    for row in range (1, H//2):
        fCol = np.vstack((fCol , p))
    f = fCol
    # Column replication
    for col in range (1, W//2):
        f = np.hstack((f, fCol))
    return f

print("Replication:\n", chessRep(4,8))<jupyter_output>Replication:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>TileThis solution uses the properties of the Numpy function *tile*. It replicates the 4-pixel pattern overthe image according to the number of replication in the vertical and horizontal directions.<jupyter_code>def chessTile(H,W):
    p = np.array([[0,1],
                  [1,0]], 'uint8')    
    f = np.tile(p, (H//2, W//2))
    return f

print("Tiling:\n", chessTile(4,8))<jupyter_output>Tiling:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>ResizeThis solution uses the Numpy function *resize* to increase the image until the desired size, replicatingthe initial raster image contents. We first create two lines of the image and then rezise it until thefinal dimension.<jupyter_code>def chessResize(H,W):
    # create two lines and then apply resize
    row1 = np.arange(W).astype('uint8') % 2
    row2 = np.array([row1, 1 - row1])
    f = np.resize(row2, (H,W))
    return f

print("Resize:\n", chessResize(4,8))<jupyter_output>Resize:
 [[0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]
 [0 1 0 1 0 1 0 1]
 [1 0 1 0 1 0 1 0]]<jupyter_text>Comparing execution timesWe compare the speed efficiency of the implementation above. We can see that slicing, tiling and resize are the most efficientimplementations because it is intrinsic to Numpy. Slicing is very efficient and is very recommending in most image processingmanipulation. Coordinate processing and replication have medium efficiency with coordinate processing being a very generalway to create images. Lastly list processing and C style programming present the worst efficiency because of its explicitpixel scanning. For comparison, the result of the chess image is always of an array of type *uint8*, except for the coordinates methodwhere the result is in *uint16* as the coordinate values are greater than 255.<jupyter_code>H,W = 2000,2000
funlist = (chessResize, chessSlice, chessTile, chessIndiceBroad, chessIndice,   chessIter,         chessRep,      chessCstyle)
fundesc = ("Resize",    "Slicing",  "Tiling",  "CoordBroad"    , "Coordinates", "List processing", "Replication", "C style")
for fun,fundesc in zip(funlist,fundesc):
    print(fundesc)
    %timeit f = fun(H,W)<jupyter_output>Resize
100 loops, best of 3: 1.6 ms per loop
Slicing
100 loops, best of 3: 2.69 ms per loop
Tiling
100 loops, best of 3: 14.1 ms per loop
CoordBroad
10 loops, best of 3: 54.1 ms per loop
Coordinates
10 loops, best of 3: 68.3 ms per loop
List processing
1 loop, best of 3: 860 ms per loop
Replication
1 loop, best of 3: 1.85 s per loop
C style
1 loop, best of 3: 1.76 s per loop
{'fraction_non_alphanumeric': 0.09549035588155393, 'fraction_numerical': 0.0571855474055963, 'mean_word_length': 4.050068587105624, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '135398', 'license': 'MIT', 'n_tokens_mistral': 2719, 'n_tokens_neox': 2387, 'n_words': 1061, 'path': 'master/chess.ipynb', 'repo_name': 'lrittner/ia979', 'size': '7362'}