|
| 1 | +import numpy as np |
| 2 | +import matplotlib.pyplot as plt |
| 3 | +import scipy.misc |
| 4 | +import itertools |
| 5 | + |
| 6 | +def show(image): |
| 7 | + fig, ax = plt.subplots() |
| 8 | + img = ax.imshow(image, cmap='Greys', aspect=1, interpolation='none') |
| 9 | + plt.colorbar(img) |
| 10 | + return fig, ax |
| 11 | + |
| 12 | +class Image(object): |
| 13 | + """Class to identify boundaries between black and white pixels in image. |
| 14 | + """ |
| 15 | + def __init__(self, image, from_file=False): |
| 16 | + #self.cutoff = cutoff |
| 17 | + if from_file: |
| 18 | + try: |
| 19 | + self._image_orig = scipy.misc.imread(image, "mode=L") |
| 20 | + except FileNotFoundError: |
| 21 | + raise f"Unable to load from {image}" |
| 22 | + else: |
| 23 | + self._image_orig = scipy.misc.bytescale(image) |
| 24 | + image_shape = self._image_orig.shape |
| 25 | + if len(image_shape) == 1: |
| 26 | + self._Nx = int(np.sqrt(image_shape)) |
| 27 | + self._Ny = self._Nx |
| 28 | + self._image_flat = self._image_orig |
| 29 | + else: |
| 30 | + self._Nx, self._Ny = self._image_orig.shape |
| 31 | + self._image_flat = self._image_orig.flatten() |
| 32 | + self._image = np.reshape(1 - self._image_flat / 255.0, |
| 33 | + (self._Nx, self._Ny)) |
| 34 | + self._image_cropped = None |
| 35 | + self._image_bw = None |
| 36 | + self._image_links = None |
| 37 | + #self._original = self._image.copy() |
| 38 | + |
| 39 | + def crop(self, x_start, y_start, x_end, y_end): |
| 40 | + """Crop image from (x_start, y_start) to (x_end, y_end).""" |
| 41 | + cropped_image = self._image[x_start:x_end, y_start:y_end] |
| 42 | + self._image_cropped = cropped_image |
| 43 | + #self._image = cropped_image |
| 44 | + return cropped_image |
| 45 | + |
| 46 | + def _cutoff(self, cutoff, image=None): |
| 47 | + """Convert image from greyscale to exclusively black and white, |
| 48 | + determined by the value of cutoff.""" |
| 49 | + if image is None: |
| 50 | + image = self._image |
| 51 | + image_flat = np.ndarray.flatten(image) |
| 52 | + Nx, Ny = image.shape |
| 53 | + #n_sites = image.shape[0] * image.shape[1] |
| 54 | + image_bw = np.array([-1 if i < cutoff else 1 for i in image_flat]) |
| 55 | + image_bw = (np.reshape(image_bw, (Nx, Ny)) + 1) / 2.0 |
| 56 | + self._image_bw = image_bw |
| 57 | + return image_bw |
| 58 | + |
| 59 | + def get_boundaries(self, cutoff, image=None): |
| 60 | + """Identify boundaries separating black and white regions of image.""" |
| 61 | + if image is None: |
| 62 | + image = self._image |
| 63 | + image_bw = self._cutoff(cutoff, image) |
| 64 | + Nx, Ny = image_bw.shape |
| 65 | + links_arr = np.zeros((Nx, Ny, 2)) |
| 66 | + for x, y in itertools.product(range(Nx), range(Ny)): |
| 67 | + links_arr[(x+1)%Nx, y, 1] = (int(round(image_bw[x, y])) |
| 68 | + + int(round(image_bw[(x+1)%Nx, y])))%2 |
| 69 | + links_arr[x, (y+1)%Ny, 0] = (int(round(image_bw[x, y])) |
| 70 | + + int(round(image_bw[x, (y+1)%Ny])))%2 |
| 71 | + image_links = np.zeros((2*Nx, 2*Ny), dtype=int) |
| 72 | + for x, y in itertools.product(range(Nx), range(Ny)): |
| 73 | + image_links[2*x+1, 2*y] = links_arr[x, y, 0] |
| 74 | + image_links[2*x, 2*y+1] = links_arr[x, y, 1] |
| 75 | + link_sum = (links_arr[x, y, 0] + links_arr[x, y, 1] |
| 76 | + + links_arr[(x-1)%Nx, y, 0] + links_arr[x, (y-1)%Ny, 1]) |
| 77 | + if link_sum != 0: |
| 78 | + image_links[2*x, 2*y] = 1 |
| 79 | + self._image_links = image_links |
| 80 | + return image_links |
0 commit comments