{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -U albumentations\n!pip install opencv-python\n!pip install opencv-contrib-python==4.5.5.62\n!pip install wandb --upgrade\n!pip install timm==0.9.02","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:07:51.716998Z","iopub.execute_input":"2023-06-04T17:07:51.717519Z","iopub.status.idle":"2023-06-04T17:09:02.787381Z","shell.execute_reply.started":"2023-06-04T17:07:51.71748Z","shell.execute_reply":"2023-06-04T17:09:02.786076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport wandb\nimport shutil \nfrom pathlib import Path\nimport json\n\nimport numpy as np \nimport pandas as pd\nimport random\n\nimport cv2\nfrom tqdm import tqdm\nimport copy\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport torchvision\nfrom torchvision import datasets, models, transforms\nfrom torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, CosineAnnealingLR, ReduceLROnPlateau, StepLR\n\ntry:\n    from torchinfo import summary\nexcept:\n    print(\"[INFO] Couldn't find torchinfo... installing it.\")\n    !pip install -q torchinfo\n    from torchinfo import summary\n\nimport timm\n\nimport albumentations as A\nimport albumentations.pytorch as AP\n\nfrom albumentations import (\n    HorizontalFlip, IAAPerspective, ShiftScaleRotate, CLAHE, RandomRotate90, Resize, RandomCrop,\n    Transpose, ShiftScaleRotate, Blur, OpticalDistortion, GridDistortion, HueSaturationValue,\n    IAAAdditiveGaussianNoise, GaussNoise, MotionBlur, MedianBlur, RandomBrightnessContrast, IAAPiecewiseAffine,\n    IAASharpen, IAAEmboss, Flip, OneOf, Compose, Rotate, RandomScale, RandomGridShuffle,\n    RandomContrast, RandomGamma, RandomBrightness, CenterCrop, VerticalFlip, ColorJitter,\n    ChannelShuffle, InvertImg, RGBShift, ElasticTransform, Equalize, RandomResizedCrop, ChannelDropout\n)\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\nfrom PIL import Image\nimport math\nfrom zipfile import ZipFile\nfrom sklearn.model_selection import train_test_split\nimport uuid","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:11:08.271754Z","iopub.execute_input":"2023-06-04T17:11:08.272164Z","iopub.status.idle":"2023-06-04T17:11:08.296206Z","shell.execute_reply.started":"2023-06-04T17:11:08.272133Z","shell.execute_reply":"2023-06-04T17:11:08.294883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/noaa-right-whale-recognition/train.csv')\ndf.sample(4)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:11:12.004653Z","iopub.execute_input":"2023-06-04T17:11:12.005188Z","iopub.status.idle":"2023-06-04T17:11:12.077269Z","shell.execute_reply.started":"2023-06-04T17:11:12.005139Z","shell.execute_reply":"2023-06-04T17:11:12.076332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.info()\ndf.shape","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:11:22.197448Z","iopub.execute_input":"2023-06-04T17:11:22.197829Z","iopub.status.idle":"2023-06-04T17:11:22.226418Z","shell.execute_reply.started":"2023-06-04T17:11:22.197803Z","shell.execute_reply":"2023-06-04T17:11:22.225235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.nunique()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:11:25.864496Z","iopub.execute_input":"2023-06-04T17:11:25.864886Z","iopub.status.idle":"2023-06-04T17:11:25.87848Z","shell.execute_reply.started":"2023-06-04T17:11:25.864858Z","shell.execute_reply":"2023-06-04T17:11:25.877266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Из 4544 размеченных изображений уникальных особей - 447.","metadata":{}},{"cell_type":"code","source":"grdf = df.groupby(['whaleID'])\ngrdf.size().sort_values(axis=0, ascending=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:12:33.675249Z","iopub.execute_input":"2023-06-04T17:12:33.675673Z","iopub.status.idle":"2023-06-04T17:12:33.688941Z","shell.execute_reply.started":"2023-06-04T17:12:33.675642Z","shell.execute_reply":"2023-06-04T17:12:33.688088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"whale_counts = grdf.size().values\nplt.hist(whale_counts, bins=100)\nplt.xlabel('Количество изображений')\nplt.ylabel('Количество китов')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:12:39.512578Z","iopub.execute_input":"2023-06-04T17:12:39.513031Z","iopub.status.idle":"2023-06-04T17:12:40.189693Z","shell.execute_reply.started":"2023-06-04T17:12:39.512994Z","shell.execute_reply":"2023-06-04T17:12:40.18858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Размеченная выборка несбалансирована, многие киты встречаются на небольшом количестве изображений. Было решено не выбрасывать из набора китов, изображения которых встречаются редко.","metadata":{}},{"cell_type":"markdown","source":"Посмотрим как выглядят снимки","metadata":{}},{"cell_type":"code","source":"path_im = '/kaggle/input/noaa-right-whale-recognition/imgs.zip'\nwith ZipFile(path_im, 'r') as zip:\n    files = zip.namelist()\n    random_file = random.choice(files)\n    with zip.open(random_file) as img_file:\n        img = Image.open(img_file)\n        plt.imshow(img)\n        plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:13:08.561886Z","iopub.execute_input":"2023-06-04T17:13:08.562302Z","iopub.status.idle":"2023-06-04T17:13:10.128349Z","shell.execute_reply.started":"2023-06-04T17:13:08.562269Z","shell.execute_reply":"2023-06-04T17:13:10.12749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path_im = '/kaggle/input/noaa-right-whale-recognition/imgs.zip'\nwith ZipFile(path_im, 'r') as zip:\n    files = zip.namelist()\n    random_files = random.sample(files, 6)  # выбираем 6 случайных файлов\n    images = []\n    for file in random_files:\n        with zip.open(file) as img_file:\n            img = Image.open(img_file)\n            images.append(np.array(img))  # добавляем каждое изображение в массив\n    fig, axs = plt.subplots(nrows=2, ncols=3, figsize=(12, 6))  # создаем 2 строки и 3 столбца графиков\n    for i, ax in enumerate(axs.flat):\n        ax.imshow(images[i])  # отображаем каждое изображение в соответствующей ячейке\n        ax.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:13:20.961776Z","iopub.execute_input":"2023-06-04T17:13:20.962167Z","iopub.status.idle":"2023-06-04T17:13:26.900657Z","shell.execute_reply.started":"2023-06-04T17:13:20.962137Z","shell.execute_reply":"2023-06-04T17:13:26.899593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Узнаем размер картинок","metadata":{}},{"cell_type":"code","source":"path_im = '/kaggle/input/noaa-right-whale-recognition/imgs.zip'\nwith ZipFile(path_im, 'r') as zip:\n    files = zip.namelist()\n    random_files = random.sample(files, 10)  # выбираем 10 случайных файлов\n    images = []\n    for file in random_files:\n        with zip.open(file) as img_file:\n            img = Image.open(img_file)\n            images.append(np.array(img))  # добавляем каждое изображение в массив\n    for im in images:\n        height, width, _ = im.shape # меняем порядок размерности идексов массива\n        print('Размер картинки: {}x{}'.format(width, height))","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:13:41.274761Z","iopub.execute_input":"2023-06-04T17:13:41.275294Z","iopub.status.idle":"2023-06-04T17:13:42.622893Z","shell.execute_reply.started":"2023-06-04T17:13:41.27525Z","shell.execute_reply":"2023-06-04T17:13:42.621971Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Теперь поработаем с файлами разметки носовой части и дыхательного отверстия","metadata":{}},{"cell_type":"code","source":"# нос\nwith open('/kaggle/input/points1/points1.json') as f:\n    points1 = json.load(f)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:15:53.698086Z","iopub.execute_input":"2023-06-04T17:15:53.69876Z","iopub.status.idle":"2023-06-04T17:15:53.735083Z","shell.execute_reply.started":"2023-06-04T17:15:53.698723Z","shell.execute_reply":"2023-06-04T17:15:53.734095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# дыхало\nwith open('/kaggle/input/points2/points2.json') as f:\n    points2 = json.load(f)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:00.50623Z","iopub.execute_input":"2023-06-04T17:16:00.507041Z","iopub.status.idle":"2023-06-04T17:16:00.544123Z","shell.execute_reply.started":"2023-06-04T17:16:00.506992Z","shell.execute_reply":"2023-06-04T17:16:00.54289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_t = [{'filename': d['filename'],\n         'x_t': d['annotations'][0]['x'],\n         'y_t': d['annotations'][0]['y']}\n        for d in points1]\n        \ndf_t = pd.DataFrame.from_records(df_t)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:07.28249Z","iopub.execute_input":"2023-06-04T17:16:07.282861Z","iopub.status.idle":"2023-06-04T17:16:07.300647Z","shell.execute_reply.started":"2023-06-04T17:16:07.282833Z","shell.execute_reply":"2023-06-04T17:16:07.299468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_bh = [{'filename': d['filename'],\n         'x_bh': d['annotations'][0]['x'],\n         'y_bh': d['annotations'][0]['y']}\n        for d in points2]\n\ndf_bh = pd.DataFrame.from_records(df_bh)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:12.857798Z","iopub.execute_input":"2023-06-04T17:16:12.858192Z","iopub.status.idle":"2023-06-04T17:16:12.874504Z","shell.execute_reply.started":"2023-06-04T17:16:12.858164Z","shell.execute_reply":"2023-06-04T17:16:12.873401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annot = pd.merge(df_t, df_bh, on='filename') # объединяем DataFrame по имени файла\n\nprint(df_annot)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:23.552732Z","iopub.execute_input":"2023-06-04T17:16:23.553147Z","iopub.status.idle":"2023-06-04T17:16:23.583143Z","shell.execute_reply.started":"2023-06-04T17:16:23.553114Z","shell.execute_reply":"2023-06-04T17:16:23.582137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_ID = df.rename(columns = {'Image' : 'filename'})\ndf_ID.sort_values(by='filename', ascending=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:31.961858Z","iopub.execute_input":"2023-06-04T17:16:31.962294Z","iopub.status.idle":"2023-06-04T17:16:31.98397Z","shell.execute_reply.started":"2023-06-04T17:16:31.96226Z","shell.execute_reply":"2023-06-04T17:16:31.982733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(df_ID.shape)\nprint(df_annot.shape)","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:16:38.881841Z","iopub.execute_input":"2023-06-04T17:16:38.882333Z","iopub.status.idle":"2023-06-04T17:16:38.888609Z","shell.execute_reply.started":"2023-06-04T17:16:38.882292Z","shell.execute_reply":"2023-06-04T17:16:38.88742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_annot","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:17:11.749657Z","iopub.execute_input":"2023-06-04T17:17:11.750076Z","iopub.status.idle":"2023-06-04T17:17:11.771225Z","shell.execute_reply.started":"2023-06-04T17:17:11.750045Z","shell.execute_reply":"2023-06-04T17:17:11.77001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_ID","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:17:18.664984Z","iopub.execute_input":"2023-06-04T17:17:18.66549Z","iopub.status.idle":"2023-06-04T17:17:18.680084Z","shell.execute_reply.started":"2023-06-04T17:17:18.665447Z","shell.execute_reply":"2023-06-04T17:17:18.679068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_an = pd.merge(df_ID, df_annot, on='filename')\ndf_an","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:17:24.187169Z","iopub.execute_input":"2023-06-04T17:17:24.187593Z","iopub.status.idle":"2023-06-04T17:17:24.216432Z","shell.execute_reply.started":"2023-06-04T17:17:24.187561Z","shell.execute_reply":"2023-06-04T17:17:24.215242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Рассчитываем и добавляем в датафрейм расстояние от носа до выдувного отверстия и угол поворота","metadata":{}},{"cell_type":"code","source":"lenght = []\nfor _, row in df_an.iterrows():\n    x_t = row['x_t']\n    y_t = row['y_t']\n    x_bh = row['x_bh']\n    y_bh = row['y_bh']\n    L = np.linalg.norm(np.array([x_t, y_t]) - np.array([x_bh, y_bh]))\n    lenght.append(L)\n\ndf_an['lenght'] = lenght # добавляем новой колонкой в df\n\nangle = [] # угол между x и lenght\n\nfor _, row in df_an.iterrows():\n    x = row['x_t'] - row['x_bh']\n    L = row['lenght']\n    angle_rad = math.acos(x/L)\n    angle_deg = math.degrees(angle_rad)\n    angle.append(angle_deg)\n\ndf_an['angle'] = angle # добавляем новой колонкой в df","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:17:45.569202Z","iopub.execute_input":"2023-06-04T17:17:45.569611Z","iopub.status.idle":"2023-06-04T17:17:46.335479Z","shell.execute_reply.started":"2023-06-04T17:17:45.569582Z","shell.execute_reply":"2023-06-04T17:17:46.33446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Попробуем кропнуть картинку с центром в точке дыхательного отверстия, длинной и шириной немного большей, чем длина до носа","metadata":{}},{"cell_type":"code","source":"new_size = [] # размер обрезки изображения\n\nfor _, row in df_an.iterrows():\n    L = row['lenght']\n    size = 2.6 * L\n    new_size.append(size)\n\ndf_an['new_size'] = new_size # добавляем новой колонкой в df","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:18:02.586621Z","iopub.execute_input":"2023-06-04T17:18:02.586995Z","iopub.status.idle":"2023-06-04T17:18:02.85788Z","shell.execute_reply.started":"2023-06-04T17:18:02.586967Z","shell.execute_reply":"2023-06-04T17:18:02.856927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_an","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:18:12.169788Z","iopub.execute_input":"2023-06-04T17:18:12.170187Z","iopub.status.idle":"2023-06-04T17:18:12.192551Z","shell.execute_reply.started":"2023-06-04T17:18:12.170156Z","shell.execute_reply":"2023-06-04T17:18:12.191351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Создаем новую папку\nos.makedirs('/kaggle/working/imgs')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nwith zipfile.ZipFile(path_im, 'r') as zip_ref:\n    zip_ref.extractall('/kaggle/working/imgs')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_path = \"/kaggle/working/imgs/imgs\"\nfiles = os.listdir(folder_path)\nnum_files = len(files)\nprint(\"В папке {} файлов: {}\".format(folder_path, num_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"В папке /kaggle/working/imgs/imgs файлов: 11469","metadata":{}},{"cell_type":"code","source":"if not os.path.exists('/kaggle/working/marked_imgs'):\n    os.mkdir('/kaggle/working/marked_imgs')\n    \nfolder = '/kaggle/working/imgs/imgs'\nfiles = os.listdir(folder)\n\n# Фильтруем список файлов по маске и проверяем наличие разметки\nmarked_files = []\nfor file in df_an['filename']:\n    if file.endswith('.jpg') and file in files:\n        marked_files.append(file)\n        \n# Копируем только отмеченные файлы в новую папку\nfor file in marked_files:\n    shutil.copyfile(os.path.join(folder, file), os.path.join('/kaggle/working/marked_imgs', file))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_path = \"/kaggle/working/marked_imgs\"\nfiles = os.listdir(folder_path)\nnum_files = len(files)\nprint(\"В папке {} файлов: {}\".format(folder_path, num_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"В папке /kaggle/working/marked_imgs файлов: 4543","metadata":{}},{"cell_type":"code","source":"# Удаляем исходную папку\n#shutil.rmtree('/kaggle/working/marked_imgs')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Создаем новую папку\n#os.makedirs('/kaggle/working/new_imgs')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Сверка папок с датафреймами\n# Создадим список имен файлов из папки /kaggle/working/new_imgs\nexisting_files = os.listdir('/kaggle/input/notebook395b94d85f/new_imgs')\n\n# Создадим множество номеров файлов в df_an\ndf_filenames = list(df_an['filename'].values)\n\n# Cписок файлов в df_an, которых нет в папке new_imgs\nmissing_files = [file for file in df_filenames if file not in existing_files]\n\n# Cписок файлов в папке new_imgs, которых нет в df_an\nextra_files = [file for file in existing_files if file not in df_filenames]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_an.shape","metadata":{"execution":{"iopub.status.busy":"2023-06-04T17:19:24.618064Z","iopub.execute_input":"2023-06-04T17:19:24.619213Z","iopub.status.idle":"2023-06-04T17:19:24.625748Z","shell.execute_reply.started":"2023-06-04T17:19:24.619172Z","shell.execute_reply":"2023-06-04T17:19:24.624591Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_path = \"/kaggle/input/notebook395b94d85f/new_imgs\"\nfiles = os.listdir(folder_path)\nnum_files = len(files)\nprint(\"В папке {} файлов: {}\".format(folder_path, num_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"duplicates = df_an.duplicated(subset=['filename'])\nif duplicates.any():\n    print(\"Есть повторяющиеся значения в столбце 'filename'\")\nelse:\n    print(\"Нет повторяющихся значений в столбце 'filename'\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"missing_files","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_an = df_an[~df_an['filename'].isin(missing_files)]\ndf_an.shape","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Обходим каждое изображение и обрезаем его\nfor index, row in df_an.iterrows():\n        \n    # Открываем изображение\n    img_path = '/kaggle/working/marked_imgs/' + row['filename']\n    if not os.path.exists(img_path):\n        continue\n        \n    img = Image.open(img_path)\n    \n    new_size = row['new_size']\n    \n    # Вычисляем левый верхний угол (x1, y1) и правый нижний угол (x2, y2) для обрезки\n    x1 = row['x_bh'] - new_size/2\n    y1 = row['y_bh'] - new_size/2\n    x2 = x1 + new_size\n    y2 = y1 + new_size\n    \n    # Обрезаем изображение\n    cropped_img = img.crop((x1, y1, x2, y2))      \n    # Сохраняем обрезанный файл\n    new_img_path = f'/kaggle/working/new_imgs/{row[\"filename\"]}'\n    cropped_img.save(new_img_path)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_path = \"/kaggle/input/notebook395b94d85f/new_imgs\"\nfiles = os.listdir(folder_path)\nnum_files = len(files)\nprint(\"В папке {} файлов: {}\".format(folder_path, num_files))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Приведем в соответствие разметку и файлы в папке","metadata":{}},{"cell_type":"code","source":"path_dir = '/kaggle/working/new_imgs'\nfiles = os.listdir(path_dir)\nrandom_files = random.sample(files, 6)  # выбираем 6 случайных файлов\n\nimages = []\nfor file in random_files:\n    with Image.open(os.path.join(path_dir, file)) as img:\n        images.append(np.array(img))  # добавляем каждое изображение в массив\n            \nfig, axs = plt.subplots(nrows=2, ncols=3, figsize=(12, 6))  # создаем 2 строки и 3 столбца графиков\nfor i, ax in enumerate(axs.flat):\n    ax.imshow(images[i])  # отображаем каждое изображение в соответствующей ячейке\n    ax.axis('off')\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path_dir = '/kaggle/working/new_imgs'\nfiles = os.listdir(path_dir)\nrandom_files = random.sample(files, 10)  # выбираем 10 случайных файлов\n\nimages = []\nfor file in random_files:\n    with Image.open(os.path.join(path_dir, file)) as img:\n        images.append(np.array(img))  # добавляем каждое изображение в массив\n    \nfor im in images:\n    height, width, _ = im.shape # меняем порядок размерности идексов массива\n    print('Размер картинки: {}x{}'.format(width, height))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Сохранение папки в постоянную директорию","metadata":{}}]}