Search code examples
pythonmatrixscalingbinary-data

How to scale a binary mask pattern


DISCLAIMER:

I am doing this for an art project that combines history with mathematics.

QUESTION:

Let's say I have a binary mask pattern like

mask = [1,0,1,1,1],[1,0,1,0,0],[1,1,1,1,1],[0,0,1,0,1],[1,1,1,0,1]

it is a 5 rows 5 columns matrix that represents a swastika pattern

enter image description here

I am wondering if there are any quick ways of obtaining an "enlarged-scaled" version of the pattern

enlarged_mask = [1,0,0,1,1,1,1], [1,0,0,1,0,0,0], [1,0,0,1,0,0,0], [1,1,1,1,1,1,1], [0,0,0,1,0,0,1], [0,0,0,1,0,0,1], [1,1,1,1,0,0,1]

that in this case has now 7 rows and 7 columns and preserves the overall logic of the original pattern.

enter image description here

What could be a possible handy method for the case?

Any help would be highly appreciated


Solution

  • preserves the overall logic of the original pattern.

    This is the hard bit, assuming you want an arbitrary pattern. You're basically after an AI capable of discerning this pattern, a very much non-trivial task. For example, consider the 3x3 pattern (zeros are rendered blank for readabilty):

    111
    1 1
    111
    

    Is this pattern "outer units set" or is it "inner unit clear"? The difference between those two is vast as the former is what you want but the latter will end up with a much thicker border line. In other words, it will be one of:

    Outer-set       Inner-clear
    =========       ===========
      11111            11111
      1   1            11111
      1   1            11 11
      1   1            11111
      11111            11111
    

    That's even before you examine other possibilities such as simply scaling the image itself, so that you work on sub-unit resolution.


    However, since it appears you're after a specific pattern (known in advance), you can generate a single-pixel width swastika with the following code:

    def swastika(n):
        # Ignore requests for malformed images.
    
        if n < 1 or n % 2 == 0: return []
        matrix = [[0 for _ in range(n)] for _ in range(n)]
    
        # Do the cross bit.
    
        for i in range(n):
            matrix[n//2][i] = 1
            matrix[i][n//2] = 1
    
        # Do the outer arms.
    
        for i in range(n//2,n):
            matrix[0][i] = 1
            matrix[i][n-1] = 1
            matrix[n-1][n-i-1] = 1
            matrix[n-i-1][0] = 1
    
        return matrix
    
    # Test harness for various sizes.
    
    for i in range(5, 10, 2):
        s = swastika(i)
        for j in range(i):
            print(s[j])
        print()
    

    The output of that is (modified for readability, yet again):

                         1   11111
             1  1111     1   1
    1 111    1  1        1   1
    1 1      1  1        1   1
    11111    1111111     111111111
      1 1       1  1         1   1
    111 1       1  1         1   1
             1111  1         1   1
                         11111   1