pixels2diagram#

[1]:
def spiral(n_cups):
    """
    Implements the asymptotic worst-case for normal_form, see arXiv:1804.07832.
    """
    x = Ty('x')
    unit, counit = Box('unit', Ty(), x), Box('counit', x, Ty())
    cup, cap = Box('cup', x @ x, Ty()), Box('cap', Ty(), x @ x)
    for box in [unit, counit, cup, cap]:
        box.draw_as_spider, box.color, box.drawing_name = True, "red", ""
    result = unit
    for i in range(n_cups):
        result = result >> Id(x ** i) @ cap @ Id(x ** (i + 1))
    result = result >> Id(x ** n_cups) @ counit @ Id(x ** n_cups)
    for i in range(n_cups):
        result = result >>\
            Id(x ** (n_cups - i - 1)) @ cup @ Id(x ** (n_cups - i - 1))
    return result
[2]:
from discopy import *
from PIL import Image

diagram = Box('f', Ty('x', 'x'), Ty('x', 'x', 'x'))\
    @ spiral(3)
rewrites = list(diagram.normalize())
diagram = rewrites[21]

params = dict(
    draw_type_labels=False,
    draw_as_nodes=True,
    draw_box_labels=False,
    margins=(0.05, 0))

diagram.draw(**params, path='../_static/imgs/test-pixels2diagram.png')
img = Image.open('../_static/imgs/test-pixels2diagram.png')
img
[2]:
../_images/notebooks_pixels2diagram_2_0.png
[3]:
import numpy as np

arr = np.array(img)
print("height, width, [red, blue, green, opacity]: {}".format(arr.shape))
height, width, [red, blue, green, opacity]: (288, 432, 4)
[4]:
from skimage import measure
from matplotlib import pyplot as plt


threshold = 200
red = np.logical_and(arr[:, :, 0] > threshold,
                     arr[:, :, 1] < threshold,
                     arr[:, :, 2] < threshold)
box_pixels, n_boxes = measure.label(red, return_num=True)
print("Found {} boxes:".format(n_boxes))

plt.figure(figsize=(8, 8))
plt.axis('off')
plt.imshow(-box_pixels, cmap='cubehelix')
plt.show()
Found 8 boxes:
../_images/notebooks_pixels2diagram_4_1.png
[5]:
wire_pixels, n_wires = measure.label(arr[:, :, 0] < threshold, return_num=True)
print("Found {} wires:".format(n_wires))

plt.figure(figsize=(6, 6))
plt.axis('off')
plt.imshow(-wire_pixels, cmap='cubehelix')
plt.show()
Found 8 wires:
../_images/notebooks_pixels2diagram_5_1.png
[6]:
box_properties = measure.regionprops(box_pixels)
wire_properties = measure.regionprops(wire_pixels)

critical_heights = np.array(
    [0] + [box['centroid'][0] for box in box_properties] + [arr.shape[0]])

def find_start_and_endpoints(wire):
    start = np.argmin(np.abs(critical_heights - wire['coords'][0][0]))
    end = np.argmin(np.abs(critical_heights - wire['coords'][-1][0]))
    return (start, end)

print("Connectivity (wires to boxes [1, ..., 9] or boundary [0, 10]):")
wires_to_boxes = {i: find_start_and_endpoints(wire) for i, wire in enumerate(wire_properties)}
wires_to_boxes
Connectivity (wires to boxes [1, ..., 9] or boundary [0, 10]):
[6]:
{0: (0, 9),
 1: (1, 7),
 2: (1, 8),
 3: (2, 8),
 4: (2, 6),
 5: (3, 6),
 6: (3, 5),
 7: (4, 7)}
[7]:
print("Connectivity (boxes/boundary to wires):")
boxes_to_wires = {i: ([wire for wire, (_, end) in wires_to_boxes.items() if end == i],
                      [wire for wire, (start, _) in wires_to_boxes.items() if start == i])
                  for i, _ in enumerate(critical_heights)}
boxes_to_wires
Connectivity (boxes/boundary to wires):
[7]:
{0: ([], [0]),
 1: ([], [1, 2]),
 2: ([], [3, 4]),
 3: ([], [5, 6]),
 4: ([], [7]),
 5: ([6], []),
 6: ([4, 5], []),
 7: ([1, 7], []),
 8: ([2, 3], []),
 9: ([0], [])}
[8]:
scan = boxes_to_wires[0][1]
result = Id(PRO(len(scan)))
for i, box_data in enumerate(box_properties):
    inputs, outputs = boxes_to_wires[i + 1]
    depth, width = map(int, box_data['centroid'])
    offset = len(set(wire_pixels[depth, :width]) - {wire + 1 for wire in inputs + outputs}) - 1
    box = Box('box_{}'.format(i), PRO(len(inputs)), PRO(len(outputs)), draw_as_spider=True)
    result = result\
        >> Id(PRO(offset)) @ box @ Id(PRO(len(scan) - len(inputs) - offset))
    scan = scan[:offset] + outputs + scan[offset + len(inputs):]
result.draw(**params)
../_images/notebooks_pixels2diagram_8_0.png
[ ]: