def test_enclosing_size(self): """Test enclosing size helper function""" sizes = [(3, 5), (1, 1), (1, 1)] pos = [(0, 0), (3, 0), (0, 5)] width, height = rpack.enclosing_size(sizes, pos) self.assertEqual(width, 4) self.assertEqual(height, 6)
def _bbox_rpack(component_sizes, pad_x=1.0, pad_y=1.0): """Compute bounding boxes for individual components by arranging them as densly as possible. Depends on `rectangle-packer`. """ try: import rpack except ImportError: raise ImportError( "Using the 'components layout' requires the installation of " "the `rectangle-packer`. You can install it with " "`pip install rectangle-packer`.") dimensions = [_get_bbox_dimensions(n, power=0.8) for n in component_sizes] # rpack only works on integers; sizes should be in descending order dimensions = [(int(width + pad_x), int(height + pad_y)) for (width, height) in dimensions[::-1]] origins = rpack.pack(dimensions) outer_dimensions = rpack.enclosing_size(dimensions, origins) aspect_ratio = outer_dimensions[0] / outer_dimensions[1] if aspect_ratio > 1: scale_width, scale_height = 1, aspect_ratio else: scale_width, scale_height = aspect_ratio, 1 bboxes = [( x, y, width * scale_width - pad_x, height * scale_height - pad_y, ) for (x, y), (width, height) in zip(origins, dimensions)] return bboxes[::-1]
def plot_circums(directory): data = load_simple(directory, 'circum') f = list() for (rec, pos) in data: w, h = rpack.enclosing_size(rec, pos) a = sum(x * y for x, y in rec) f.append(a / (w * h)) with PdfPages(os.path.join(args.output_dir, 'circum.pdf')) as pdf: fig, ax = plt.subplots(tight_layout=True) ax.plot(list(range(1, len(f) + 1)), f) ax.grid(True) ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1)) ax.xaxis.set_major_locator(mtick.MultipleLocator(10)) ax.set_title('Packing density, fixed circumference rectangles') ax.set_xlabel('Rectangle width + height (n)') pdf.savefig(figure=fig) for ext in IMG_EXT: plt.savefig(os.path.join(args.output_dir, f'circum_summary.{ext}')) fig.clf() plt.close() for n, (rec, pos) in enumerate(data, start=1): p = PlotPacking(rec, pos, title=f', nx1 ... 1xn, n={n}.') while p.feed(): pass pdf.savefig(figure=p.fig) p.fig.clf() plt.close()
def plot_enclosing(data): w = list() h = list() fig, ax = plt.subplots(tight_layout=True) ax.grid(True) m = 1_000 # the scatter plot: for n in [10, 20, 30, 50, 100]: ew = list() eh = list() for rec, pos, t in data[n, m]: w, h = rpack.enclosing_size(rec, pos) ew.append(w) eh.append(h) ew = np.array(ew) / math.sqrt(n) eh = np.array(eh) / math.sqrt(n) # f = [aa/(w*h) for aa, (w, h) in zip(a, zip(ew, eh))] color = 'black' if n == 100 else None ax.scatter(ew, eh, c=color, s=0.2, label=f'$n = {n}$') ax.legend(markerscale=5) ax.set_aspect('equal') ax.set_xlim([0, None]) ax.set_ylim([0, None]) ax.set_title('Resulting enclosings,\n' rf'$n$ = No. rectangles, side lengths ~ $Unif\{{1, {m}\}}$') ax.set_ylabel(r'Enclosing height / $\sqrt{n}$') ax.set_xlabel(r'Enclosing width / $\sqrt{n}$') for ext in IMG_EXT: plt.savefig(os.path.join(args.output_dir, f'enclosing.{ext}')) fig.clf() plt.close()
def get_packed(boxes): sizes = [(int(box[2] - box[0]), int(box[3] - box[1])) for box in boxes] heights = [int(box[3] - box[1]) for box in boxes] #arr = np.array(sizes, dtype=[('w', int), ('h', int)]) arr = np.array(heights) sorted_ind = np.argsort(arr) sorted_ind = list(sorted_ind[::-1]) sorted_sizes = sorted(sizes, key=lambda x: x[1], reverse=True) #sorted_sizes = np.sort(arr, order='h') #sorted_sizes = sorted_sizes[::-1] #sorted_sizes = list(sorted_sizes) #from IPython import embed #embed() positions = rpack.pack(sorted_sizes) shape = rpack.enclosing_size(sorted_sizes, positions) new_img = np.zeros((shape[1], shape[0], 3)) for i in range(len(positions)): x, y = positions[i] w, h = sorted_sizes[i] box = boxes[sorted_ind[i]] img = cv2.imread(box[4]) img = np.array(img) new_img[y:y + h, x:x + w, :] = img[int(box[1]):int(box[1]) + h, int(box[0]):int(box[0] + w)] return new_img
def plot_packing_density_by_m(data): n = 100 m = 1_000 x = list() total = list() for m in range(100, 1001, 100): f = list() for rec, pos, _ in data[100, m]: w, h = rpack.enclosing_size(rec, pos) a = sum(x * y for x, y in rec) f.append(a / (w * h)) x.append(f) total.extend(f) x.append(total) fig, ax = plt.subplots(tight_layout=True) ax.axhline(np.array(total).mean(), color=matplotlib.rcParams['boxplot.meanprops.markerfacecolor'], linewidth=1, linestyle=':') bplot = ax.boxplot( x, sym='.', vert=True, patch_artist=True, labels=list(range(100, 1001, 100)) + ['total'], # positions=list(range(1, 11)) + [11.25], # widths=[0.5]*10 + [1], showmeans=True, medianprops=dict(color='black')) # fill with colors colors = ['lightblue'] * 10 + ['lightgreen'] for patch, color in zip(bplot['boxes'], colors): patch.set_facecolor(color) # ax.set_xlim([None, 13]) ax.yaxis.grid(True) ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1, decimals=0)) ax.yaxis.set_major_locator(mtick.MultipleLocator(0.01)) ax.yaxis.set_minor_locator(mtick.MultipleLocator(0.001)) ax.set_title('Packing density') ax.set_xlabel( rf'rectangle side lengths ~ $Unif\{{1, m\}}$, ${n} \leq m \leq {m}$') for ext in IMG_EXT: plt.savefig( os.path.join(args.output_dir, f'packing_density_by_m.{ext}')) fig.clf() plt.close()
def proportional(self, min_size: int = 32, album_count: int = 100) -> None: """ :param min_size: the smallest size for an album in pixels :param album_count: the number of albums to include in the poster :return: None """ from rpack import pack, enclosing_size if self.album_data is None or len(self.album_data.index) < album_count: album_data = get_album_data(album_count, genre_tags=self.genre_tags) else: album_data = self.album_data album_sizes = album_data["msPlayed"].astype(float) album_sizes = album_sizes / min(album_sizes) * min_size album_sizes = [(int(n), int(n)) for n in album_sizes] new_poss = pack(album_sizes) self.album_data = album_data self.positions = new_poss self.album_sizes = album_sizes self.size = enclosing_size(album_sizes, new_poss)
def plot_squares(directory): data = load_simple(directory, 'square') f = list() for (rec, pos) in data: w, h = rpack.enclosing_size(rec, pos) a = sum(x * y for x, y in rec) f.append(a / (w * h)) with PdfPages(os.path.join(args.output_dir, 'squares.pdf')) as pdf: fig, ax = plt.subplots(tight_layout=True) ax.plot(list(range(1, len(f) + 1)), f) ax.grid(True) ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1)) ax.xaxis.set_major_locator(mtick.MultipleLocator(10)) ax.set_title('Packing density, squares') ax.set_xlabel('Rectangle max side length (n)') pdf.savefig(figure=fig) for ext in IMG_EXT: plt.savefig(os.path.join(args.output_dir, f'squares_summary.{ext}')) fig.clf() plt.close() for n, (rec, pos) in enumerate(data, start=1): if n == 1: title = ', square 1x1' elif n == 2: title = ', squares 1x1 + 2x2' else: title = f', squares 1x1 ... {n}x{n}' p = PlotPacking(rec, pos, title=title) while p.feed(): pass pdf.savefig(figure=p.fig) p.fig.clf() plt.close()
def __init__(self, rec, pos, gridlines=False, title='', trim=False): """Initialization of PlotPacking""" self.rec = rec self.pos = pos self.gridlines = gridlines self.index = None self.encl_w, self.encl_h = rpack.enclosing_size(rec, pos) self.density = sum(w * h for w, h in rec) / (self.encl_w * self.encl_h) if trim: self.fig = plt.figure(figsize=(6, 6 * self.encl_h / self.encl_w)) self.ax = self.fig.add_axes([0.01, 0.01, 0.98, 0.98]) else: self.fig, self.ax = plt.subplots(tight_layout=True) self.ax.set_aspect('equal') self.ax.invert_yaxis() self.ax.set_xlim([0, self.encl_w]) self.ax.set_ylim([self.encl_h, 0]) self.ax.xaxis.set_visible(False) self.ax.yaxis.set_visible(False) if title and not trim: self.ax.set_title(f'Packing density {100*self.density:.2f}% ' f'({self.encl_w} x {self.encl_h})' + title)
def plot_packing_density_by_n(data): m = 1_000 x = list() for n in range(10, 101, 10): f = list() for rec, pos, _ in data[n, m]: w, h = rpack.enclosing_size(rec, pos) a = sum(x * y for x, y in rec) f.append(a / (w * h)) x.append(f) fig, ax = plt.subplots(tight_layout=True) bplot = ax.boxplot(x, sym='.', vert=True, patch_artist=True, showfliers=True, labels=list(range(10, 101, 10)), showmeans=True, medianprops=dict(color='black')) # fill with colors for patch in bplot['boxes']: patch.set_facecolor('lightblue') # ax.set_ylim([0.7, None]) ax.yaxis.grid(True) ax.yaxis.set_major_formatter(mtick.PercentFormatter(xmax=1, decimals=0)) ax.yaxis.set_major_locator(mtick.MultipleLocator(0.05)) ax.yaxis.set_minor_locator(mtick.MultipleLocator(0.01)) ax.set_title( rf'Packing density, rectangle side lengths ~ $Unif\{{1, {m}\}}$') ax.set_xlabel('Number of rectangles') for ext in IMG_EXT: plt.savefig( os.path.join(args.output_dir, f'packing_density_by_n.{ext}')) fig.clf() plt.close()
def test_medium_pack(self): sizes = [(i, i) for i in range(20, 1, -1)] pos = rpack.pack(sizes) width, height = rpack.enclosing_size(sizes, pos) self.assertLessEqual(width*height, 3045)
def test_basic_pack(self): """Basic pack: four 2x2 and one 3x3""" sizes = [(2, 2), (2, 2), (2, 2), (3, 3)] pos = rpack.pack(sizes) width, height = rpack.enclosing_size(sizes, pos) self.assertEqual(width*height, 25)
# In[10]: b = '0' * len(sizes) num = int(b) Areas = {} Positions = {} Sizes = {} for i in range(2**len(sizes)): temp = [list(i) for i in sizes] s = bin(num)[2:].zfill(len(sizes)) for j in range(len(sizes)): if s[j] == '1': temp[j][1], temp[j][0] = temp[j][0], temp[j][1] temp = [tuple(j) for j in temp] positions = rpack.pack(temp) t = rpack.enclosing_size(temp, positions) Areas[s] = t[0] * t[1] Positions[s] = positions Sizes[s] = temp num += 1 mArea = min(Areas.values()) for k, v in Areas.items(): if v == mArea: positions = Positions[k] sizes = Sizes[k] break positions # In[11]: positions
def packing_density(rec, pos): w, h = rpack.enclosing_size(rec, pos) return sum(x * y for x, y in rec) / (w * h)
f for f in listdir(folder) if isfile(join(folder, f)) and (f.endswith(".png") or f.endswith(".jpg")) ] images = [] for i in range(len(names)): s = "Loading {}, {}/{}".format(names[i], i + 1, len(names)) s += " " * (84 - len(s)) print(s, end="\r") images.append(Image.open(folder + names[i])) print("\nCalculating each image position...") print(time.time()) rectangles = [i.size for i in images] positions = rpack.pack(rectangles) size = rpack.enclosing_size(rectangles, positions) print(time.time()) print( "\nPositions calculated! Creating a new image with size {} by {} pixels.". format(size[0], size[1])) output_file = Image.new("RGBA", size) for i in range(len(positions)): s = "Putting {} in final image, {}/{}".format( names[i].replace(".png", "").replace(".jpg", ""), i + 1, len(names)) s += " " * (84 - len(s)) print(s, end="\r") output_file.paste(images[i], positions[i]) print("\nSaving the image...")