From e9f52f780652a9d9e9d73a2c3f39f225ce0a0938 Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:28:58 +0000 Subject: [PATCH 1/6] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/.keep diff --git a/docs/.keep b/docs/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From e55f8ef8d019eed4c8f705319b35a53b250f0a2f Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:29:57 +0000 Subject: [PATCH 2/6] add mindscience architecture --- docs/MindScience_Architecture.jpg | Bin 0 -> 126998 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/MindScience_Architecture.jpg diff --git a/docs/MindScience_Architecture.jpg b/docs/MindScience_Architecture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3182f79731f44653d089bda17964519f735722fb GIT binary patch literal 126998 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 NJpQi1N%w2`{{nwXNFo3L literal 0 HcmV?d00001 -- Gitee From 046d03ed8a63cbc6ad86a471ce884fd5703d9a3c Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:30:18 +0000 Subject: [PATCH 3/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20docs?= =?UTF-8?q?/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/.keep diff --git a/docs/.keep b/docs/.keep deleted file mode 100644 index e69de29bb..000000000 -- Gitee From c34f8ed49aef8dcb0a9230b8dbc00b2c2ce6d7a0 Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:30:24 +0000 Subject: [PATCH 4/6] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20READ?= =?UTF-8?q?ME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 973296add..000000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -MindSpore for science. -- Gitee From eee9448c10228e88f8d5037a35c498520b6c80dd Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:31:03 +0000 Subject: [PATCH 5/6] add mindscience readme --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..fdda4c56b --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# MindScience + +## 概述 + +MindScience是基于MindSpore融合架构打造的科学计算行业套件,包含了业界领先的数据集、基础模型、预制高精度模型和前后处理工具,加速了科学行业应用开发。目前已推出面向电子信息行业的MindElec套件和面向生命科学行业的MindSPONGE套件,分别实现了电磁仿真性能提升10倍和生物制药化合物模拟效率提升50%。 + +## 架构图 +
+MindScience Architecture +
\ No newline at end of file -- Gitee From ba7cccdae4774f5c00ab2330787c294d32cc8f75 Mon Sep 17 00:00:00 2001 From: liyang777 Date: Tue, 14 Sep 2021 12:32:20 +0000 Subject: [PATCH 6/6] add mindelec vision --- MindElec/mindelec/vision/body.py | 101 ++++++++ .../mindelec/vision/mindinsight_vision.py | 221 ++++++++++++++++++ MindElec/mindelec/vision/plane.py | 138 +++++++++++ MindElec/mindelec/vision/print_scatter.py | 118 ++++++++++ MindElec/mindelec/vision/video.py | 87 +++++++ 5 files changed, 665 insertions(+) create mode 100644 MindElec/mindelec/vision/body.py create mode 100644 MindElec/mindelec/vision/mindinsight_vision.py create mode 100644 MindElec/mindelec/vision/plane.py create mode 100644 MindElec/mindelec/vision/print_scatter.py create mode 100644 MindElec/mindelec/vision/video.py diff --git a/MindElec/mindelec/vision/body.py b/MindElec/mindelec/vision/body.py new file mode 100644 index 000000000..380f76e53 --- /dev/null +++ b/MindElec/mindelec/vision/body.py @@ -0,0 +1,101 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Visualization of the results 3D VTK form""" + +import os +from pyevtk.hl import gridToVTK +import numpy as np + + +def vtk_structure(grid_tensor, eh_tensor, path_res): + r""" + Generates 3D vtk file for visualizaiton. + + Args: + grid_tensor (np.array): grid data (shape: (dim_t, dim_x, dim_y, dim_z, 4)). + eh_tensor (np.array): electric and magnetic data (np.array, shape: (dim_t, dim_x, dim_y, dim_z, 6)). + path_res (str): save path for the output vtk file. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import vtk_structure + >>> grid_tensor = np.random.rand(20, 10, 10, 10, 4).astype(np.float32) + >>> eh_tensor = np.random.rand(20, 10, 10, 10, 6).astype(np.float32) + >>> path_res = './result_vtk' + >>> vtk_structure(grid_tensor, eh_tensor, path_res) + """ + if not isinstance(grid_tensor, np.ndarray): + raise TypeError("The type of grid_tensor should be numpy array, but get {}".format(type(grid_tensor))) + + if not isinstance(eh_tensor, np.ndarray): + raise TypeError("The type of eh_tensor should be numpy array, but get {}".format(type(eh_tensor))) + + if not isinstance(path_res, str): + raise TypeError("The type of path_res should be str, but get {}".format(type(path_res))) + if not os.path.exists(path_res): + os.makedirs(path_res) + + input_grid = grid_tensor + output_grid = eh_tensor + + shape_grid = input_grid.shape + shape_eh = output_grid.shape + + if len(shape_grid) != 5 or shape_grid[-1] != 4: + raise ValueError("grid_tensor shape should be (dim_t, dim_x, dim_y, dim_z, 4), but get {}" + .format(shape_grid)) + + if len(shape_eh) != 5 or shape_eh[-1] != 6: + raise ValueError("eh_tensor shape should be (dim_t, dim_x, dim_y, dim_z, 6), but get {}" + .format(shape_eh)) + + if shape_grid[:4] != shape_eh[:4]: + raise ValueError("grid_tensor and eh_tensor should have the same dimension except the last axis, " + "but get grid_tensor shape {} and eh_tensor shape{}".format(shape_grid, shape_eh)) + + (dim_t, dim_x, dim_y, dim_z, d) = input_grid.shape + input_grid = np.reshape(input_grid, (dim_t * dim_x * dim_y * dim_z, d)) + x_min, x_max = np.min(input_grid[:, 0]), np.max(input_grid[:, 0]) + y_min, y_max = np.min(input_grid[:, 1]), np.max(input_grid[:, 1]) + z_min, z_max = np.min(input_grid[:, 2]), np.max(input_grid[:, 2]) + + x_all = np.linspace(x_min, x_max, dim_x, endpoint=True, dtype='float64') + y_all = np.linspace(y_min, y_max, dim_y, endpoint=True, dtype='float64') + z_all = np.linspace(z_min, z_max, dim_z, endpoint=True, dtype='float64') + + x = np.zeros((dim_x, dim_y, dim_z)) + y = np.zeros((dim_x, dim_y, dim_z)) + z = np.zeros((dim_x, dim_y, dim_z)) + + for i in range(dim_x): + for j in range(dim_y): + for k in range(dim_z): + x[i, j, k] = x_all[i] + y[i, j, k] = y_all[j] + z[i, j, k] = z_all[k] + + for t in range(dim_t): + print(t) + output_grid_show = output_grid[t] + ex, ey, ez = output_grid_show[:, :, :, 0], output_grid_show[:, :, :, 1], output_grid_show[:, :, :, 2] + hx, hy, hz = output_grid_show[:, :, :, 3], output_grid_show[:, :, :, 4], output_grid_show[:, :, :, 5] + ex, ey, ez = ex.astype(np.float64), ey.astype(np.float64), ez.astype(np.float64) + hx, hy, hz = hx.astype(np.float64), hy.astype(np.float64), hz.astype(np.float64) + gridToVTK(os.path.join(path_res, 'eh_t' + str(t)), + x, y, z, + pointData={"Ex": ex, "Ey": ey, "Ez": ez, "Hx": hx, "Hy": hy, "Hz": hz}) diff --git a/MindElec/mindelec/vision/mindinsight_vision.py b/MindElec/mindelec/vision/mindinsight_vision.py new file mode 100644 index 000000000..ee7a447ef --- /dev/null +++ b/MindElec/mindelec/vision/mindinsight_vision.py @@ -0,0 +1,221 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Callback functions for model.train and model.eval""" + +import os +import numpy as np +from mindspore.dataset.engine.datasets import BatchDataset as ds +from mindspore.common.tensor import Tensor +from mindspore.train.callback import Callback +from mindspore.train.summary import SummaryRecord +from ..solver import Solver + + +class MonitorTrain(Callback): + r""" + Loss monitor for train. + + Args: + per_print_times (int): print loss interval. + summary_dir (str): summary save path. + + Returns: + Callback monitor. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> from mindelec.vision import MonitorTrain + >>> per_print_times = 1 + >>> summary_dir = './summary_train' + >>> MonitorTrain(per_print_times, summary_dir) + """ + + def __init__(self, per_print_times=1, summary_dir='./summary_train'): + super(MonitorTrain, self).__init__() + if not isinstance(per_print_times, int): + raise TypeError("per_print_times must be int, but get {}".format(type(per_print_times))) + if per_print_times <= 0: + raise ValueError("per_print_times must be > 0.") + + if not isinstance(summary_dir, str): + raise TypeError("summary_dir must be str, but get {}".format(type(summary_dir))) + if not os.path.exists(summary_dir): + os.makedirs(summary_dir) + + self._per_print_times = per_print_times + self._summary_dir = summary_dir + self._step_counter = 0 + self.final_loss = 0 + + def __enter__(self): + self.summary_record = SummaryRecord(self._summary_dir) + return self + + def __exit__(self, *exc_args): + self.summary_record.close() + + def step_end(self, run_context): + """ + Evaluate the model at the end of epoch. + + Args: + run_context (RunContext): Context of the train running. + """ + self._step_counter += 1 + params = run_context.original_args() + + loss = params.net_outputs + + if isinstance(loss, (tuple, list)): + if isinstance(loss[0].asnumpy(), np.ndarray) and isinstance(loss[0], Tensor): + loss = loss[0] + + if isinstance(loss.asnumpy(), np.ndarray) and isinstance(loss, Tensor): + loss = np.mean(loss.asnumpy()) + + cur_step = (params.cur_step_num - 1) % params.batch_num + 1 + + if isinstance(loss, float) and (np.isnan(loss) or np.isinf(loss)): + raise ValueError("epoch: {} step: {}. Invalid loss, training end.".format( + params.cur_epoch_num, cur_step)) + + if self._per_print_times != 0 and params.cur_step_num % self._per_print_times == 0: + print("epoch: %s step: %s, loss is %s" % (params.cur_epoch_num, cur_step, loss), flush=True) + self.summary_record.add_value('scalar', 'train_loss', Tensor(loss)) + self.summary_record.record(self._step_counter) + self.final_loss = loss + + +class MonitorEval(Callback): + r""" + LossMonitor for eval. + + Args: + summary_dir (str): summary save path. + model (Solver): Model object for eval. + eval_ds (Dataset): eval dataset. + eval_interval (int): eval interval. + draw_flag (bool): specifies if save summary_record. + + Returns: + Callback monitor. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import mindspore.nn as nn + >>> from mindelec.solver import Solver + >>> from mindelec.vision import MonitorEval + >>> class S11Predictor(nn.Cell): + ... def __init__(self, input_dimension): + ... super(S11Predictor, self).__init__() + ... self.fc1 = nn.Dense(input_dimension, 128) + ... self.fc2 = nn.Dense(128, 128) + ... self.fc3 = nn.Dense(128, 1001) + ... self.relu = nn.ReLU() + ... + ... def construct(self, x): + ... x0 = x + ... x1 = self.relu(self.fc1(x0)) + ... x2 = self.relu(self.fc2(x1)) + ... x = self.fc3(x1 + x2) + ... return x + >>> model_net = S11Predictor(3) + >>> model = Solver(network=model_net, mode="Data", optimizer=nn.Adam(0.001), loss_fn=nn.MSELoss()) + >>> # For details about how to build the dataset, please refer to the tutorial + >>> # document on the official website. + >>> eval_ds = Dataset() + >>> summary_dir = './summary_eval_path' + >>> eval_interval = 10 + >>> draw_flag = True + >>> MonitorEval(summary_dir, model, eval_ds, eval_interval, draw_flag) + """ + + def __init__(self, + summary_dir='./summary_eval', + model=None, + eval_ds=None, + eval_interval=10, + draw_flag=True): + super(MonitorEval, self).__init__() + if not isinstance(summary_dir, str): + raise ValueError("summary_dir must be str, but get {}".format(type(summary_dir))) + + if not isinstance(model, Solver): + raise ValueError("model must be mindelec solver, but get {}".format(type(model))) + + if not isinstance(eval_ds, ds): + raise ValueError("eval dataset must be mindelec dataset, but get {}".format(type(eval_ds))) + + if not isinstance(eval_interval, int): + raise TypeError("eval_interval must be int, but get {}".format(type(eval_interval))) + if eval_interval <= 0: + raise ValueError("eval_interval must be > 0.") + + if not isinstance(draw_flag, bool): + raise ValueError("draw_flag must be bool, but get {}".format(type(draw_flag))) + + self._summary_dir = summary_dir + self._model = model + self._eval_ds = eval_ds + self._eval_interval = eval_interval + self._draw_flag = draw_flag + + self._eval_count = 0 + self.temp = None + self.loss_final = 0.0 + self.l2_s11_final = 0.0 + + def __enter__(self): + self.summary_record = SummaryRecord(self._summary_dir) + return self + + def __exit__(self, *exc_args): + self.summary_record.close() + + def epoch(self, run_context): + """ + Evaluate the model at the end of epoch. + + Args: + run_context (RunContext): Context of the train running. + """ + self.temp = run_context + self._eval_count += 1 + cb_param = run_context.original_args() + cur_epoch = cb_param.cur_epoch_num + if cur_epoch % self._eval_interval == 0: + res_eval = self._model.model.eval(valid_dataset=self._eval_ds, dataset_sink_mode=True) + loss_eval_print, l2_s11_print = res_eval['eval_mrc']['loss_error'], res_eval['eval_mrc']['l2_error'] + + self.loss_final = loss_eval_print + self.l2_s11_final = l2_s11_print + print('Eval current epoch:', cur_epoch, ' loss:', loss_eval_print, ' l2_s11:', l2_s11_print) + + self.summary_record.add_value('scalar', 'eval_loss', Tensor(loss_eval_print)) + self.summary_record.record(self._eval_count * self._eval_interval) + + self.summary_record.add_value('scalar', 'l2_s11', Tensor(l2_s11_print)) + self.summary_record.record(self._eval_count * self._eval_interval) + + if self._draw_flag: + pic_res = res_eval['eval_mrc']['pic_res'] + for i in range(len(pic_res)): + self.summary_record.add_value('image', 'l2_s11_image_' + str(i), + Tensor(np.expand_dims(pic_res[i], 0).transpose((0, 3, 1, 2)))) + self.summary_record.record(self._eval_count * self._eval_interval) diff --git a/MindElec/mindelec/vision/plane.py b/MindElec/mindelec/vision/plane.py new file mode 100644 index 000000000..ddd83164d --- /dev/null +++ b/MindElec/mindelec/vision/plane.py @@ -0,0 +1,138 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Visualization of the results in 2D image form""" + +import os +import numpy as np +import matplotlib.pyplot as plt +import matplotlib + +matplotlib.use('Agg') + + +def plot_s11(s11_tensor, path_image_save, legend, dpi=300): + r""" + Draw s11-frequency curve and save it in path_image_save. + + Args: + s11_tensor (np.array): s11 data (shape: (dim_frequency, 2)). + path_image_save (str): s11-frequency curve saved path. + legend (str): the legend of s11, plotting parameters. + dpi (int): plotting parameters. Default: 300. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import plot_s11 + >>> s11 = np.random.rand(1001, 2).astype(np.float32) + >>> s11[:, 0] = np.linspace(0, 4 * 10 ** 9, 1001) + >>> s11 = s11.astype(np.float32) + >>> s11_tensor = s11 + >>> path_image_save = './result_s11' + >>> legend = 's11' + >>> dpi = 300 + >>> plot_s11(s11_tensor, path_image_save, legend, dpi) + """ + if not isinstance(s11_tensor, np.ndarray): + raise TypeError("The type of s11_tensor should be numpy array, but get {}".format(type(s11_tensor))) + + if not isinstance(path_image_save, str): + raise TypeError("The type of path_image_save should be str, but get {}".format(type(path_image_save))) + if not os.path.exists(path_image_save): + os.makedirs(path_image_save) + + if not isinstance(legend, str): + raise TypeError("The type of legend should be str, but get {}".format(type(legend))) + + if not isinstance(dpi, int): + raise TypeError("The type of dpi must be int, but get {}".format(type(dpi))) + if dpi <= 0: + raise ValueError("dpi must be > 0.") + + shape_s11_all = s11_tensor.shape + if len(shape_s11_all) != 2 or shape_s11_all[-1] != 2: + raise ValueError("s11_tensor shape should be (dim_frequency, 2), but get {}".format(shape_s11_all)) + + s11_temp, frequency = s11_tensor[:, 0], s11_tensor[:, 1] + plt.figure(dpi=dpi, figsize=(8, 4)) + plt.plot(frequency, s11_temp, '-', label=legend, linewidth=2) + plt.title('s11(dB)') + plt.xlabel('frequency(Hz)') + plt.ylabel('dB') + plt.legend() + plt.savefig(os.path.join(path_image_save, 's11.jpg')) + plt.close() + + +def plot_eh(simu_res_tensor, path_image_save, z_index, dpi=300): + r""" + Draw electric and magnetic field values of every timestep for 2D slices, and save them in path_image_save + + Args: + simu_res_tensor (np.array): simulation result (shape (dim_t, dim_x, dim_y, dim_z, 6)). + path_image_save (str): images saved path. + z_index (int): show 2D image for z=z_index. + dpi (int): plotting parameters. Default: 300. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import plot_eh + >>> simu_res_tensor = np.random.rand(20, 10, 10, 10, 6).astype(np.float32) + >>> path_image_save = './result_eh' + >>> z_index = 5 + >>> dpi = 300 + >>> plot_eh(simu_res_tensor, path_image_save, z_index, dpi) + """ + if not isinstance(simu_res_tensor, np.ndarray): + raise TypeError("The type of simu_res_tensor should be numpy array, but get {}".format(type(simu_res_tensor))) + + if not isinstance(path_image_save, str): + raise TypeError("The type of path_image_save should be str, but get {}".format(type(path_image_save))) + if not os.path.exists(path_image_save): + os.makedirs(path_image_save) + + if not isinstance(z_index, int): + raise TypeError("The type of z_index must be int, but get {}".format(type(z_index))) + if z_index <= 0: + raise ValueError("z_index must be > 0.") + + if not isinstance(dpi, int): + raise TypeError("The type of dpi must be int, but get {}".format(type(dpi))) + if dpi <= 0: + raise ValueError("dpi must be > 0.") + + shape_simulation_res = simu_res_tensor.shape + if len(shape_simulation_res) != 5 or shape_simulation_res[-1] != 6: + raise ValueError("path_simu_res shape should be (dim_t, dim_x, dim_y, dim_z, 6), but get {}" + .format(shape_simulation_res)) + + plot_order = ['Ex', 'Ey', 'Ez', 'Hx', 'Hy', 'Hz'] + + for i in range(6): + current = simu_res_tensor[:, :, :, z_index, i] + min_val, max_val = np.min(current), np.max(current) + timesteps = len(current) + for t in range(timesteps): + current_2d = current[t] + plt.figure(dpi=dpi) + plt.imshow(current_2d, vmin=min_val, vmax=max_val) + plt.colorbar() + plt.savefig(os.path.join(path_image_save, plot_order[i] + '_' + str(t) + '.jpg')) + plt.close() diff --git a/MindElec/mindelec/vision/print_scatter.py b/MindElec/mindelec/vision/print_scatter.py new file mode 100644 index 000000000..dfce1a46d --- /dev/null +++ b/MindElec/mindelec/vision/print_scatter.py @@ -0,0 +1,118 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""util functions for tests""" + +import os +import numpy as np +import matplotlib.pyplot as plt + + +def print_graph_1d(name, x, path, clear=True): + r""" + Draw 1d scatter image + + Args: + name (str): name of the graph. + x (np.array): data to draw (shape (dim_print,)). + path (str): save path of the graph. + clear (bool): specifies whether clear the current axes. Default: True. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import print_graph_1d + >>> name = "output.jpg" + >>> x = np.ones(10) + >>> path = "./graph_1d" + >>> clear = True + >>> print_graph_1d(name, x, path, clear) + """ + if not isinstance(name, str): + raise TypeError("The type of name should be str, but get {}".format(type(name))) + + if not isinstance(x, np.ndarray): + raise TypeError("The type of x should be numpy array, but get {}".format(type(x))) + shape_x = x.shape + if len(shape_x) != 1: + raise ValueError("x shape should be (dim_print,), but get {}".format(shape_x)) + + if not isinstance(path, str): + raise TypeError("The type of path should be str, but get {}".format(type(path))) + if not os.path.exists(path): + os.makedirs(path) + + if not isinstance(clear, bool): + raise TypeError("The type of clear should be bool, but get {}".format(type(clear))) + + if clear: + plt.cla() + y = np.zeros(x.shape) + plt.scatter(x, y, alpha=0.8, s=0.8) + plt.savefig(os.path.join(path, name), dpi=600) + + +def print_graph_2d(name, x, y, path, clear=True): + r""" + Draw 2d scatter image + + Args: + name (str): name of the graph. + x (np.array): data x to draw (shape (dim_print,)). + y (np.array): data y to draw (shape (dim_print,)). + path (str): save path of the graph. + clear (bool): specifies whether clear the current axes. Default: True. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import print_graph_2d + >>> name = "output.jpg" + >>> x = np.ones(10) + >>> y = np.ones(10) + >>> path = "./graph_2d" + >>> clear = True + >>> print_graph_2d(name, x, y, path, clear) + """ + if not isinstance(name, str): + raise TypeError("The type of name should be str, but get {}".format(type(name))) + + if not isinstance(x, np.ndarray): + raise TypeError("The type of x should be numpy array, but get {}".format(type(x))) + shape_x = x.shape + if len(shape_x) != 1: + raise ValueError("x shape should be (dim_print,), but get {}".format(shape_x)) + + if not isinstance(y, np.ndarray): + raise TypeError("The type of y should be numpy array, but get {}".format(type(y))) + shape_y = y.shape + if len(shape_y) != 1: + raise ValueError("y shape should be (dim_print,), but get {}".format(shape_y)) + + if not isinstance(path, str): + raise TypeError("The type of path should be str, but get {}".format(type(path))) + if not os.path.exists(path): + os.makedirs(path) + + if not isinstance(clear, bool): + raise TypeError("The type of clear should be bool, but get {}".format(type(clear))) + + if clear: + plt.cla() + plt.scatter(x, y, alpha=1.0, s=0.8) + plt.savefig(os.path.join(path, name), dpi=600) diff --git a/MindElec/mindelec/vision/video.py b/MindElec/mindelec/vision/video.py new file mode 100644 index 000000000..d739d6f27 --- /dev/null +++ b/MindElec/mindelec/vision/video.py @@ -0,0 +1,87 @@ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Visualization of the results in video form""" + +import os +from importlib import import_module +from PIL import Image + + +def image_to_video(path_image, path_video, video_name, fps): + r""" + Create video from existing images. + + Args: + path_image (str): image path, all images are jpg. + image names in path_image should be like: + 00.jpg, 01.jpg, 02.jpg, ... 09.jpg, 10.jpg, 11.jpg, 12.jpg ... + path_video (str): video path, video saved path. + video_name (str): video name(.avi file) + fps (int): Specifies how many pictures per second in video. + + Supported Platforms: + ``Ascend`` + + Examples: + >>> import numpy as np + >>> from mindelec.vision import plot_eh, image_to_video + >>> path_image = './images' + >>> eh = np.random.rand(5, 10, 10, 10, 6).astype(np.float32) + >>> plot_eh(eh, path_image, 5, 300) + >>> path_video = './result_video' + >>> video_name = 'video.avi' + >>> fps = 10 + >>> image_to_video(path_image, path_video, video_name, fps) + """ + if not isinstance(path_image, str): + raise TypeError("The type of path_image should be str, but get {}".format(type(path_image))) + if not os.path.exists(path_image): + raise Exception("No folder of images found in path_image, please check the path") + + if not isinstance(path_video, str): + raise TypeError("The type of path_video should be str, but get {}".format(type(path_video))) + if not os.path.exists(path_video): + os.makedirs(path_video) + + if not isinstance(video_name, str): + raise TypeError("The type of video_name should be str, but get {}".format(type(video_name))) + if '.avi' not in video_name or len(video_name) <= 4: + raise Exception("video_name should be .avi file, like result.avi, please check the video_name") + if video_name[-4:] != '.avi': + raise Exception("video_name should be .avi file, like result.avi, please check the video_name") + + if not isinstance(fps, int): + raise TypeError("The type of fps must be int, but get {}".format(type(fps))) + if fps <= 0: + raise ValueError("fps must be > 0.") + + cv2 = import_module("cv2") + fourcc = cv2.VideoWriter_fourcc(*"MJPG") + + images = os.listdir(path_image) + images.sort() + image = Image.open(os.path.join(path_image, images[0])) + vw = cv2.VideoWriter(os.path.join(path_video, video_name), fourcc, fps, image.size) + + for i in range(len(images)): + print(float(i) / len(images)) + jpgfile = os.path.join(path_image, images[i]) + try: + new_frame = cv2.imread(jpgfile) + vw.write(new_frame) + except IOError as exc: + print(jpgfile, exc) + vw.release() + print('Video save success!') -- Gitee