avans06/Audio-To-MIDI-And-Advanced-Renderer
37
1#! /usr/bin/python32 3r'''############################################################################4################################################################################5#6#7# Tegridy Plots Python Module (TPLOTS)8# Version 1.09#10# Project Los Angeles11#12# Tegridy Code 202513#14# https://github.com/asigalov61/tegridy-tools15#16#17################################################################################18#19# Copyright 2024 Project Los Angeles / Tegridy Code20#21# Licensed under the Apache License, Version 2.0 (the "License");22# you may not use this file except in compliance with the License.23# You may obtain a copy of the License at24#25# http://www.apache.org/licenses/LICENSE-2.026#27# Unless required by applicable law or agreed to in writing, software28# distributed under the License is distributed on an "AS IS" BASIS,29# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.30# See the License for the specific language governing permissions and31# limitations under the License.32#33################################################################################34################################################################################35#36# Critical dependencies37#38# !pip install numpy==1.24.439# !pip install scipy40# !pip install matplotlib41# !pip install networkx42# !pip3 install scikit-learn43#44################################################################################45#46# Future critical dependencies47#48# !pip install umap-learn49# !pip install alphashape50#51################################################################################52'''53 54################################################################################55# Modules imports56################################################################################57 58import os59from collections import Counter60from itertools import groupby61 62import numpy as np63 64import networkx as nx65 66from sklearn.manifold import TSNE67from sklearn import metrics68from sklearn.preprocessing import MinMaxScaler69from sklearn.decomposition import PCA70 71from scipy.ndimage import zoom72from scipy.spatial import distance_matrix73from scipy.sparse.csgraph import minimum_spanning_tree74from scipy.stats import zscore75 76import matplotlib.pyplot as plt77from PIL import Image78 79################################################################################80# Constants81################################################################################82 83ALL_CHORDS_FULL = [[0], [0, 3], [0, 3, 5], [0, 3, 5, 8], [0, 3, 5, 9], [0, 3, 5, 10], [0, 3, 6],84 [0, 3, 6, 9], [0, 3, 6, 10], [0, 3, 7], [0, 3, 7, 10], [0, 3, 8], [0, 3, 9],85 [0, 3, 10], [0, 4], [0, 4, 6], [0, 4, 6, 9], [0, 4, 6, 10], [0, 4, 7],86 [0, 4, 7, 10], [0, 4, 8], [0, 4, 9], [0, 4, 10], [0, 5], [0, 5, 8], [0, 5, 9],87 [0, 5, 10], [0, 6], [0, 6, 9], [0, 6, 10], [0, 7], [0, 7, 10], [0, 8], [0, 9],88 [0, 10], [1], [1, 4], [1, 4, 6], [1, 4, 6, 9], [1, 4, 6, 10], [1, 4, 6, 11],89 [1, 4, 7], [1, 4, 7, 10], [1, 4, 7, 11], [1, 4, 8], [1, 4, 8, 11], [1, 4, 9],90 [1, 4, 10], [1, 4, 11], [1, 5], [1, 5, 8], [1, 5, 8, 11], [1, 5, 9],91 [1, 5, 10], [1, 5, 11], [1, 6], [1, 6, 9], [1, 6, 10], [1, 6, 11], [1, 7],92 [1, 7, 10], [1, 7, 11], [1, 8], [1, 8, 11], [1, 9], [1, 10], [1, 11], [2],93 [2, 5], [2, 5, 8], [2, 5, 8, 11], [2, 5, 9], [2, 5, 10], [2, 5, 11], [2, 6],94 [2, 6, 9], [2, 6, 10], [2, 6, 11], [2, 7], [2, 7, 10], [2, 7, 11], [2, 8],95 [2, 8, 11], [2, 9], [2, 10], [2, 11], [3], [3, 5], [3, 5, 8], [3, 5, 8, 11],96 [3, 5, 9], [3, 5, 10], [3, 5, 11], [3, 6], [3, 6, 9], [3, 6, 10], [3, 6, 11],97 [3, 7], [3, 7, 10], [3, 7, 11], [3, 8], [3, 8, 11], [3, 9], [3, 10], [3, 11],98 [4], [4, 6], [4, 6, 9], [4, 6, 10], [4, 6, 11], [4, 7], [4, 7, 10], [4, 7, 11],99 [4, 8], [4, 8, 11], [4, 9], [4, 10], [4, 11], [5], [5, 8], [5, 8, 11], [5, 9],100 [5, 10], [5, 11], [6], [6, 9], [6, 10], [6, 11], [7], [7, 10], [7, 11], [8],101 [8, 11], [9], [10], [11]]102 103################################################################################104 105CHORDS_TYPES = ['WHITE', 'BLACK', 'UNKNOWN', 'MIXED WHITE', 'MIXED BLACK', 'MIXED GRAY']106 107################################################################################108 109WHITE_NOTES = [0, 2, 4, 5, 7, 9, 11]110 111################################################################################112 113BLACK_NOTES = [1, 3, 6, 8, 10]114 115################################################################################116# Helper functions117################################################################################118 119def tones_chord_type(tones_chord, 120 return_chord_type_index=True,121 ):122 123 """124 Returns tones chord type125 """126 127 WN = WHITE_NOTES128 BN = BLACK_NOTES129 MX = WHITE_NOTES + BLACK_NOTES130 131 132 CHORDS = ALL_CHORDS_FULL133 134 tones_chord = sorted(tones_chord)135 136 ctype = 'UNKNOWN'137 138 if tones_chord in CHORDS:139 140 if sorted(set(tones_chord) & set(WN)) == tones_chord:141 ctype = 'WHITE'142 143 elif sorted(set(tones_chord) & set(BN)) == tones_chord:144 ctype = 'BLACK'145 146 if len(tones_chord) > 1 and sorted(set(tones_chord) & set(MX)) == tones_chord:147 148 if len(sorted(set(tones_chord) & set(WN))) == len(sorted(set(tones_chord) & set(BN))):149 ctype = 'MIXED GRAY'150 151 elif len(sorted(set(tones_chord) & set(WN))) > len(sorted(set(tones_chord) & set(BN))):152 ctype = 'MIXED WHITE'153 154 elif len(sorted(set(tones_chord) & set(WN))) < len(sorted(set(tones_chord) & set(BN))):155 ctype = 'MIXED BLACK'156 157 if return_chord_type_index:158 return CHORDS_TYPES.index(ctype)159 160 else:161 return ctype162 163###################################################################################164 165def tone_type(tone, 166 return_tone_type_index=True167 ):168 169 """170 Returns tone type171 """172 173 tone = tone % 12174 175 if tone in BLACK_NOTES:176 if return_tone_type_index:177 return CHORDS_TYPES.index('BLACK')178 else:179 return "BLACK"180 181 else:182 if return_tone_type_index:183 return CHORDS_TYPES.index('WHITE')184 else:185 return "WHITE"186 187###################################################################################188 189def find_closest_points(points, return_points=True):190 191 """192 Find closest 2D points193 """194 195 coords = np.array(points)196 197 num_points = coords.shape[0]198 closest_matches = np.zeros(num_points, dtype=int)199 distances = np.zeros((num_points, num_points))200 201 for i in range(num_points):202 for j in range(num_points):203 if i != j:204 distances[i, j] = np.linalg.norm(coords[i] - coords[j])205 else:206 distances[i, j] = np.inf207 208 closest_matches = np.argmin(distances, axis=1)209 210 if return_points:211 points_matches = coords[closest_matches].tolist()212 return points_matches213 214 else:215 return closest_matches.tolist()216 217################################################################################218 219def reduce_dimensionality_tsne(list_of_valies,220 n_comp=2,221 n_iter=5000,222 verbose=True223 ):224 225 """226 Reduces the dimensionality of the values using t-SNE.227 """228 229 vals = np.array(list_of_valies)230 231 tsne = TSNE(n_components=n_comp,232 n_iter=n_iter,233 verbose=verbose)234 235 reduced_vals = tsne.fit_transform(vals)236 237 return reduced_vals.tolist()238 239################################################################################240 241def compute_mst_edges(similarity_scores_list):242 243 """244 Computes the Minimum Spanning Tree (MST) edges based on the similarity scores.245 """246 247 num_tokens = len(similarity_scores_list[0])248 249 graph = nx.Graph()250 251 for i in range(num_tokens):252 for j in range(i + 1, num_tokens):253 weight = 1 - similarity_scores_list[i][j]254 graph.add_edge(i, j, weight=weight)255 256 mst = nx.minimum_spanning_tree(graph)257 258 mst_edges = list(mst.edges(data=False))259 260 return mst_edges261 262################################################################################263 264def square_binary_matrix(binary_matrix, 265 matrix_size=128,266 interpolation_order=5,267 return_square_matrix_points=False268 ):269 270 """271 Reduces an arbitrary binary matrix to a square binary matrix272 """273 274 zoom_factors = (matrix_size / len(binary_matrix), 1)275 276 resized_matrix = zoom(binary_matrix, zoom_factors, order=interpolation_order)277 278 resized_matrix = (resized_matrix > 0.5).astype(int)279 280 final_matrix = np.zeros((matrix_size, matrix_size), dtype=int)281 final_matrix[:, :resized_matrix.shape[1]] = resized_matrix282 283 points = np.column_stack(np.where(final_matrix == 1)).tolist()284 285 if return_square_matrix_points:286 return points287 288 else:289 return resized_matrix290 291################################################################################292 293def square_matrix_points_colors(square_matrix_points):294 295 """296 Returns colors for square matrix points297 """298 299 cmap = generate_colors(12)300 301 chords = []302 chords_dict = set()303 counts = []304 305 for k, v in groupby(square_matrix_points, key=lambda x: x[0]):306 pgroup = [vv[1] for vv in v]307 chord = sorted(set(pgroup))308 tchord = sorted(set([p % 12 for p in chord]))309 chords_dict.add(tuple(tchord))310 chords.append(tuple(tchord))311 counts.append(len(pgroup))312 313 chords_dict = sorted(chords_dict)314 315 colors = []316 317 for i, c in enumerate(chords):318 colors.extend([cmap[round(sum(c) / len(c))]] * counts[i])319 320 return colors321 322################################################################################323 324def hsv_to_rgb(h, s, v):325 326 if s == 0.0:327 return v, v, v328 329 i = int(h*6.0)330 f = (h*6.0) - i331 p = v*(1.0 - s)332 q = v*(1.0 - s*f)333 t = v*(1.0 - s*(1.0-f))334 i = i%6335 336 return [(v, t, p), (q, v, p), (p, v, t), (p, q, v), (t, p, v), (v, p, q)][i]337 338################################################################################339 340def generate_colors(n):341 return [hsv_to_rgb(i/n, 1, 1) for i in range(n)]342 343################################################################################344 345def add_arrays(a, b):346 return [sum(pair) for pair in zip(a, b)]347 348################################################################################349 350def calculate_similarities(lists_of_values, metric='cosine'):351 return metrics.pairwise_distances(lists_of_values, metric=metric).tolist()352 353################################################################################354 355def get_tokens_embeddings(x_transformer_model):356 return x_transformer_model.net.token_emb.emb.weight.detach().cpu().tolist()357 358################################################################################359 360def minkowski_distance_matrix(X, p=3):361 362 X = np.array(X)363 364 n = X.shape[0]365 dist_matrix = np.zeros((n, n))366 367 for i in range(n):368 for j in range(n):369 dist_matrix[i, j] = np.sum(np.abs(X[i] - X[j])**p)**(1/p)370 371 return dist_matrix.tolist()372 373################################################################################374 375def robust_normalize(values):376 377 values = np.array(values)378 q1 = np.percentile(values, 25)379 q3 = np.percentile(values, 75)380 iqr = q3 - q1381 382 filtered_values = values[(values >= q1 - 1.5 * iqr) & (values <= q3 + 1.5 * iqr)]383 384 min_val = np.min(filtered_values)385 max_val = np.max(filtered_values)386 normalized_values = (values - min_val) / (max_val - min_val)387 388 normalized_values = np.clip(normalized_values, 0, 1)389 390 return normalized_values.tolist()391 392################################################################################393 394def min_max_normalize(values):395 396 scaler = MinMaxScaler()397 398 return scaler.fit_transform(values).tolist()399 400################################################################################401 402def remove_points_outliers(points, z_score_threshold=3):403 404 points = np.array(points)405 406 z_scores = np.abs(zscore(points, axis=0))407 408 return points[(z_scores < z_score_threshold).all(axis=1)].tolist()409 410################################################################################411 412def generate_labels(lists_of_values, 413 return_indices_labels=False414 ):415 416 ordered_indices = list(range(len(lists_of_values)))417 ordered_indices_labels = [str(i) for i in ordered_indices]418 ordered_values_labels = [str(lists_of_values[i]) for i in ordered_indices]419 420 if return_indices_labels:421 return ordered_indices_labels422 423 else:424 return ordered_values_labels425 426################################################################################427 428def reduce_dimensionality_pca(list_of_values, n_components=2):429 430 """431 Reduces the dimensionality of the values using PCA.432 """433 434 pca = PCA(n_components=n_components)435 pca_data = pca.fit_transform(list_of_values)436 437 return pca_data.tolist()438 439def reduce_dimensionality_simple(list_of_values, 440 return_means=True,441 return_std_devs=True,442 return_medians=False,443 return_vars=False444 ):445 446 '''447 Reduces dimensionality of the values in a simple way448 '''449 450 array = np.array(list_of_values)451 results = []452 453 if return_means:454 means = np.mean(array, axis=1)455 results.append(means)456 457 if return_std_devs:458 std_devs = np.std(array, axis=1)459 results.append(std_devs)460 461 if return_medians:462 medians = np.median(array, axis=1)463 results.append(medians)464 465 if return_vars:466 vars = np.var(array, axis=1)467 results.append(vars)468 469 merged_results = np.column_stack(results)470 471 return merged_results.tolist()472 473################################################################################474 475def reduce_dimensionality_2d_distance(list_of_values, p=5):476 477 '''478 Reduces the dimensionality of the values using 2d distance479 '''480 481 values = np.array(list_of_values)482 483 dist_matrix = distance_matrix(values, values, p=p)484 485 mst = minimum_spanning_tree(dist_matrix).toarray()486 487 points = []488 489 for i in range(len(values)):490 for j in range(len(values)):491 if mst[i, j] > 0:492 points.append([i, j])493 494 return points495 496################################################################################497 498def normalize_to_range(values, n):499 500 min_val = min(values)501 max_val = max(values)502 503 range_val = max_val - min_val504 505 normalized_values = [((value - min_val) / range_val * 2 * n) - n for value in values]506 507 return normalized_values508 509################################################################################510 511def reduce_dimensionality_simple_pca(list_of_values, n_components=2):512 513 '''514 Reduces the dimensionality of the values using simple PCA515 '''516 517 reduced_values = []518 519 for l in list_of_values:520 521 norm_values = [round(v * len(l)) for v in normalize_to_range(l, (n_components+1) // 2)]522 523 pca_values = Counter(norm_values).most_common()524 pca_values = [vv[0] / len(l) for vv in pca_values]525 pca_values = pca_values[:n_components]526 pca_values = pca_values + [0] * (n_components - len(pca_values))527 528 reduced_values.append(pca_values)529 530 return reduced_values531 532################################################################################533 534def filter_and_replace_values(list_of_values, 535 threshold, 536 replace_value, 537 replace_above_threshold=False538 ):539 540 array = np.array(list_of_values)541 542 modified_array = np.copy(array)543 544 if replace_above_threshold:545 modified_array[modified_array > threshold] = replace_value546 547 else:548 modified_array[modified_array < threshold] = replace_value549 550 return modified_array.tolist()551 552################################################################################553 554def find_shortest_constellation_path(points, 555 start_point_idx, 556 end_point_idx,557 p=5,558 return_path_length=False,559 return_path_points=False,560 ):561 562 """563 Finds the shortest path between two points of the points constellation564 """565 566 points = np.array(points)567 568 dist_matrix = distance_matrix(points, points, p=p)569 570 mst = minimum_spanning_tree(dist_matrix).toarray()571 572 G = nx.Graph()573 574 for i in range(len(points)):575 for j in range(len(points)):576 if mst[i, j] > 0:577 G.add_edge(i, j, weight=mst[i, j])578 579 path = nx.shortest_path(G, 580 source=start_point_idx, 581 target=end_point_idx, 582 weight='weight'583 )584 585 path_length = nx.shortest_path_length(G, 586 source=start_point_idx, 587 target=end_point_idx, 588 weight='weight')589 590 path_points = points[np.array(path)].tolist()591 592 593 if return_path_points:594 return path_points595 596 if return_path_length:597 return path_length598 599 return path600 601################################################################################602# Core functions603################################################################################604 605def plot_ms_SONG(ms_song,606 preview_length_in_notes=0,607 block_lines_times_list = None,608 plot_title='ms Song',609 max_num_colors=129, 610 drums_color_num=128, 611 plot_size=(11,4), 612 note_height = 0.75,613 show_grid_lines=False,614 return_plt = False,615 timings_multiplier=1,616 save_plt='',617 save_only_plt_image=True,618 save_transparent=False619 ):620 621 '''ms SONG plot'''622 623 notes = [s for s in ms_song if s[0] == 'note']624 625 if (len(max(notes, key=len)) != 7) and (len(min(notes, key=len)) != 7):626 print('The song notes do not have patches information')627 print('Ploease add patches to the notes in the song')628 629 else:630 631 start_times = [(s[1] * timings_multiplier) / 1000 for s in notes]632 durations = [(s[2] * timings_multiplier) / 1000 for s in notes]633 pitches = [s[4] for s in notes]634 patches = [s[6] for s in notes]635 636 colors = generate_colors(max_num_colors)637 colors[drums_color_num] = (1, 1, 1)638 639 pbl = (notes[preview_length_in_notes][1] * timings_multiplier) / 1000640 641 fig, ax = plt.subplots(figsize=plot_size)642 643 for start, duration, pitch, patch in zip(start_times, durations, pitches, patches):644 rect = plt.Rectangle((start, pitch), duration, note_height, facecolor=colors[patch])645 ax.add_patch(rect)646 647 ax.set_xlim([min(start_times), max(add_arrays(start_times, durations))])648 ax.set_ylim([min(pitches)-1, max(pitches)+1])649 650 ax.set_facecolor('black')651 fig.patch.set_facecolor('white')652 653 if preview_length_in_notes > 0:654 ax.axvline(x=pbl, c='white')655 656 if block_lines_times_list:657 for bl in block_lines_times_list:658 ax.axvline(x=bl, c='white')659 660 if show_grid_lines:661 ax.grid(color='white')662 663 plt.xlabel('Time (s)', c='black')664 plt.ylabel('MIDI Pitch', c='black')665 666 plt.title(plot_title)667 668 if save_plt != '':669 if save_only_plt_image:670 plt.axis('off')671 plt.title('')672 plt.savefig(save_plt, 673 transparent=save_transparent, 674 bbox_inches='tight', 675 pad_inches=0, 676 facecolor='black'677 )678 plt.close()679 680 else:681 plt.savefig(save_plt)682 plt.close()683 684 if return_plt:685 return fig686 687 plt.show()688 plt.close()689 690################################################################################691 692def plot_square_matrix_points(list_of_points,693 list_of_points_colors,694 plot_size=(7, 7),695 point_size = 10,696 show_grid_lines=False,697 plot_title = 'Square Matrix Points Plot',698 return_plt=False,699 save_plt='',700 save_only_plt_image=True,701 save_transparent=False702 ):703 704 '''Square matrix points plot'''705 706 fig, ax = plt.subplots(figsize=plot_size)707 708 ax.set_facecolor('black')709 710 if show_grid_lines:711 ax.grid(color='white')712 713 plt.xlabel('Time Step', c='black')714 plt.ylabel('MIDI Pitch', c='black')715 716 plt.title(plot_title)717 718 plt.scatter([p[0] for p in list_of_points], 719 [p[1] for p in list_of_points], 720 c=list_of_points_colors, 721 s=point_size722 )723 724 if save_plt != '':725 if save_only_plt_image:726 plt.axis('off')727 plt.title('')728 plt.savefig(save_plt, 729 transparent=save_transparent, 730 bbox_inches='tight', 731 pad_inches=0, 732 facecolor='black'733 )734 plt.close()735 736 else:737 plt.savefig(save_plt)738 plt.close()739 740 if return_plt:741 return fig742 743 plt.show()744 plt.close()745 746################################################################################747 748def plot_cosine_similarities(lists_of_values,749 plot_size=(7, 7),750 save_plot=''751 ):752 753 """754 Cosine similarities plot755 """756 757 cos_sim = metrics.pairwise_distances(lists_of_values, metric='cosine')758 759 plt.figure(figsize=plot_size)760 761 plt.imshow(cos_sim, cmap="inferno", interpolation="nearest")762 763 im_ratio = cos_sim.shape[0] / cos_sim.shape[1]764 765 plt.colorbar(fraction=0.046 * im_ratio, pad=0.04)766 767 plt.xlabel("Index")768 plt.ylabel("Index")769 770 plt.tight_layout()771 772 if save_plot != '':773 plt.savefig(save_plot, bbox_inches="tight")774 plt.close()775 776 plt.show()777 plt.close()778 779################################################################################780 781def plot_points_with_mst_lines(points, 782 points_labels, 783 points_mst_edges,784 plot_size=(20, 20),785 labels_size=24,786 save_plot=''787 ):788 789 """790 Plots 2D points with labels and MST lines.791 """792 793 plt.figure(figsize=plot_size)794 795 for i, label in enumerate(points_labels):796 plt.scatter(points[i][0], points[i][1])797 plt.annotate(label, (points[i][0], points[i][1]), fontsize=labels_size)798 799 for edge in points_mst_edges:800 i, j = edge801 plt.plot([points[i][0], points[j][0]], [points[i][1], points[j][1]], 'k-', alpha=0.5)802 803 plt.title('Points Map with MST Lines', fontsize=labels_size)804 plt.xlabel('X-axis', fontsize=labels_size)805 plt.ylabel('Y-axis', fontsize=labels_size)806 807 if save_plot != '':808 plt.savefig(save_plot, bbox_inches="tight")809 plt.close()810 811 plt.show()812 813 plt.close()814 815################################################################################816 817def plot_points_constellation(points, 818 points_labels,819 p=5, 820 plot_size=(15, 15),821 labels_size=12,822 show_grid=False,823 save_plot=''824 ):825 826 """827 Plots 2D points constellation828 """829 830 points = np.array(points)831 832 dist_matrix = distance_matrix(points, points, p=p)833 834 mst = minimum_spanning_tree(dist_matrix).toarray()835 836 plt.figure(figsize=plot_size)837 838 plt.scatter(points[:, 0], points[:, 1], color='blue')839 840 for i, label in enumerate(points_labels):841 plt.annotate(label, (points[i, 0], points[i, 1]), 842 textcoords="offset points", 843 xytext=(0, 10), 844 ha='center',845 fontsize=labels_size846 )847 848 for i in range(len(points)):849 for j in range(len(points)):850 if mst[i, j] > 0:851 plt.plot([points[i, 0], points[j, 0]], [points[i, 1], points[j, 1]], 'k--')852 853 plt.xlabel('X-axis', fontsize=labels_size)854 plt.ylabel('Y-axis', fontsize=labels_size)855 plt.title('2D Coordinates with Minimum Spanning Tree', fontsize=labels_size)856 857 plt.grid(show_grid)858 859 if save_plot != '':860 plt.savefig(save_plot, bbox_inches="tight")861 plt.close()862 863 plt.show()864 865 plt.close()866 867################################################################################868 869def binary_matrix_to_images(matrix, 870 step,871 overlap,872 output_folder='./Dataset/', 873 output_img_prefix='image', 874 output_img_ext='.png',875 save_to_array=False,876 verbose=True877 ):878 879 if not save_to_array:880 881 if verbose:882 print('=' * 70)883 print('Checking output folder dir...')884 885 os.makedirs(os.path.dirname(output_folder), exist_ok=True)886 887 if verbose:888 print('Done!')889 890 if verbose:891 print('=' * 70)892 print('Writing images...')893 894 matrix = np.array(matrix, dtype=np.uint8)895 896 image_array = []897 898 for i in range(0, max(1, matrix.shape[0]), overlap):899 900 submatrix = matrix[i:i+step, :]901 902 if submatrix.shape[0] < 128:903 zeros_array = np.zeros((128-submatrix.shape[0], 128))904 submatrix = np.vstack((submatrix, zeros_array))905 906 img = Image.fromarray(submatrix * 255).convert('1')907 908 if save_to_array:909 image_array.append(np.array(img))910 911 else:912 img.save(output_folder + output_img_prefix + '_' + str(matrix.shape[1]) + '_' + str(i).zfill(7) + output_img_ext)913 914 if verbose:915 print('Done!')916 print('=' * 70)917 print('Saved', (matrix.shape[0] // min(step, overlap))+1, 'imges!')918 print('=' * 70)919 920 if save_to_array:921 return np.array(image_array).tolist()922 923################################################################################924 925def images_to_binary_matrix(list_of_images):926 927 image_array = np.array(list_of_images)928 929 original_matrix = []930 931 for img in image_array:932 933 submatrix = np.array(img)934 original_matrix.extend(submatrix.tolist())935 936 return original_matrix937 938################################################################################939 940def square_image_matrix(image_matrix,941 matrix_size=128,942 num_pca_components=5,943 filter_out_zero_rows=False,944 return_square_matrix_points=False945 ):946 947 """948 Reduces an arbitrary image matrix to a square image matrix949 """950 951 matrix = np.array(image_matrix)952 953 if filter_out_zero_rows:954 matrix = matrix[~np.all(matrix == 0, axis=1)]955 956 target_rows = matrix_size957 958 rows_per_group = matrix.shape[0] // target_rows959 960 compressed_matrix = np.zeros((target_rows, matrix.shape[1]), dtype=np.int32)961 962 for i in range(target_rows):963 start_row = i * rows_per_group964 end_row = (i + 1) * rows_per_group965 group = matrix[start_row:end_row, :]966 967 pca = PCA(n_components=num_pca_components)968 pca.fit(group)969 970 principal_component = np.mean(pca.components_, axis=0)971 contributions = np.dot(group, principal_component)972 selected_row_index = np.argmax(contributions)973 974 compressed_matrix[i, :] = group[selected_row_index, :]975 976 if return_square_matrix_points:977 filtered_matrix = compressed_matrix[~np.all(compressed_matrix == 0, axis=1)]978 979 row_indexes, col_indexes = np.where(filtered_matrix != 0)980 points = np.column_stack((row_indexes, filtered_matrix[row_indexes, col_indexes])).tolist()981 982 return points983 984 else:985 return compressed_matrix.tolist()986 987################################################################################988 989def image_matrix_to_images(image_matrix,990 step,991 overlap,992 num_img_channels=3,993 output_folder='./Dataset/',994 output_img_prefix='image',995 output_img_ext='.png',996 save_to_array=False,997 verbose=True998 ):999 1000 if num_img_channels > 1:1001 n_mat_channels = 31002 1003 else:1004 n_mat_channels = 11005 1006 if not save_to_array:1007 1008 if verbose:1009 print('=' * 70)1010 print('Checking output folder dir...')1011 1012 os.makedirs(os.path.dirname(output_folder), exist_ok=True)1013 1014 if verbose:1015 print('Done!')1016 1017 if verbose:1018 print('=' * 70)1019 print('Writing images...')1020 1021 matrix = np.array(image_matrix)1022 1023 image_array = []1024 1025 for i in range(0, max(1, matrix.shape[0]), overlap):1026 1027 submatrix = matrix[i:i+step, :]1028 1029 if submatrix.shape[0] < 128:1030 zeros_array = np.zeros((128-submatrix.shape[0], 128))1031 submatrix = np.vstack((submatrix, zeros_array))1032 1033 if n_mat_channels == 3:1034 1035 r = (submatrix // (256*256)) % 2561036 g = (submatrix // 256) % 2561037 b = submatrix % 2561038 1039 rgb_image = np.stack((r, g, b), axis=-1).astype(np.uint8)1040 img = Image.fromarray(rgb_image, 'RGB')1041 1042 else:1043 grayscale_image = submatrix.astype(np.uint8)1044 img = Image.fromarray(grayscale_image, 'L')1045 1046 if save_to_array:1047 image_array.append(np.array(img))1048 1049 else:1050 img.save(output_folder + output_img_prefix + '_' + str(matrix.shape[1]) + '_' + str(i).zfill(7) + output_img_ext)1051 1052 if verbose:1053 print('Done!')1054 print('=' * 70)1055 print('Saved', (matrix.shape[0] // min(step, overlap))+1, 'imges!')1056 print('=' * 70)1057 1058 if save_to_array:1059 return np.array(image_array).tolist()1060 1061################################################################################1062 1063def images_to_image_matrix(list_of_images,1064 num_img_channels=31065 ):1066 1067 if num_img_channels > 1:1068 n_mat_channels = 31069 1070 else:1071 n_mat_channels = 11072 1073 image_array = np.array(list_of_images)1074 1075 original_matrix = []1076 1077 for img in image_array:1078 1079 if num_img_channels == 3:1080 1081 rgb_array = np.array(img)1082 1083 matrix = (rgb_array[..., 0].astype(np.int64) * 256*256 +1084 rgb_array[..., 1].astype(np.int64) * 256 +1085 rgb_array[..., 2].astype(np.int64))1086 1087 else:1088 matrix = np.array(img)1089 1090 original_matrix.extend(matrix)1091 1092 return original_matrix1093 1094################################################################################1095 1096def square_matrix_to_RGB_matrix(square_matrix):1097 1098 smatrix = np.array(square_matrix)1099 sq_matrix = smatrix[:smatrix.shape[1]]1100 1101 r = (sq_matrix // (256 ** 2)) % 2561102 g = (sq_matrix // 256) % 2561103 b = sq_matrix % 2561104 1105 rgb_array = np.stack((r, g, b), axis=-1)1106 1107 return rgb_array.tolist()1108 1109################################################################################1110 1111def upsample_square_matrix(square_matrix, upsampling_factor=4):1112 1113 smatrix = np.array(square_matrix)1114 sq_matrix = smatrix[:smatrix.shape[1]]1115 1116 scaling_array = np.ones((upsampling_factor, upsampling_factor))1117 scaled_array = np.kron(sq_matrix, scaling_array)1118 scaled_array = scaled_array.astype('int')1119 1120 return scaled_array.tolist()1121 1122################################################################################1123 1124def downsample_square_matrix(square_matrix, downsampling_factor=4):1125 1126 smatrix = np.array(square_matrix)1127 sq_matrix = smatrix[:smatrix.shape[1]]1128 1129 dmatrix = sq_matrix[::downsampling_factor, ::downsampling_factor]1130 dmatrix = dmatrix.astype('int')1131 1132 return dmatrix.tolist()1133 1134################################################################################1135 1136def plot_parsons_code(parsons_code, 1137 start_pitch=60, 1138 return_plot_dict=False, 1139 return_plot_string=False,1140 plot_size=(10, 10),1141 labels_size=16,1142 save_plot=''1143 ):1144 1145 '''1146 Plot parsons code string1147 '''1148 1149 if parsons_code[0] != "*":1150 return None1151 1152 contour_dict = {}1153 pitch = 01154 index = 01155 1156 maxp = 01157 minp = 01158 1159 contour_dict[(pitch, index)] = "*"1160 1161 for point in parsons_code:1162 if point == "R":1163 index += 11164 contour_dict[(pitch, index)] = "-"1165 1166 index += 11167 contour_dict[(pitch, index)] = "*"1168 1169 elif point == "U":1170 index += 11171 pitch -= 11172 contour_dict[(pitch, index)] = "/"1173 1174 index += 11175 pitch -= 11176 contour_dict[(pitch, index)] = "*"1177 1178 if pitch < maxp:1179 maxp = pitch1180 1181 elif point == "D":1182 index += 11183 pitch += 11184 contour_dict[(pitch, index)] = "\\"1185 1186 index += 11187 pitch += 11188 contour_dict[(pitch, index)] = "*"1189 1190 if pitch > minp:1191 minp = pitch1192 1193 if return_plot_dict:1194 return contour_dict1195 1196 if return_plot_string:1197 1198 plot_string = ''1199 1200 for pitch in range(maxp, minp+1):