Как сопоставить cv2.imread с выводом keras image.img_load

Я изучаю глубокое обучение. Обучил алгоритм классификации изображений. Проблема, однако, в том, что для обучения изображений я использовал:

test_image = image.load_img('some.png', target_size = (64, 64))
test_image = image.img_to_array(test_image)

В то время как для реального приложения я использую:

test_image = cv2.imread('trick.png')
test_image = cv2.resize(test_image, (64, 64))

Но я обнаружил, что они дают другой ndarray (разные данные):

Последние записи из load_image:

  [ 64.  71.  66.]
  [ 64.  71.  66.]
  [ 62.  69.  67.]]]

Последние записи cv2.imread:

  [ 15  23  27]
  [ 16  24  28]
  [ 14  24  28]]]

, значит, система не работает. Есть ли способ сопоставить результаты одного с другим?

По-другому как? Другая форма, данные?

nuric 07.06.2018 18:51

@nuric Обновленный вопрос

wasd 07.06.2018 19:00
image.load_img() использует PIL, который читает в RGB, а cv2.imread() читает в BGR. Это единственная разница.
enterML 07.06.2018 19:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
19
3
9 513
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

OpenCV считывает изображения в формате BGR, тогда как в keras они представлены в RGB. Чтобы версия OpenCV соответствовала ожидаемому порядку (RGB), просто поменяйте местами каналы:

test_image = cv2.imread('trick.png')
test_image = cv2.resize(test_image, (64, 64))
test_image = test_image[...,::-1] # Added

В последней строке каналы меняются местами в порядке RGB. Затем вы можете ввести это в свою модель keras.

Еще один момент, который я хотел бы добавить, это то, что cv2.imread обычно считывает изображения с точностью uint8. Изучая вывод загруженного изображения keras, вы можете увидеть, что данные имеют точность с плавающей запятой, поэтому вы также можете преобразовать их в представление с плавающей запятой, например float32:

import numpy as np
# ...
# ...
test_image = test_image[...,::-1].astype(np.float32)

Наконец, в зависимости от того, как вы обучили свою модель, обычно принято нормализовать значения пикселей изображения до диапазона [0,1]. Если вы сделали это со своей моделью keras, убедитесь, что вы разделили свои значения на 255 в своем изображении, прочитанном через OpenCV:

import numpy as np
# ...
# ...
test_image = (test_image[...,::-1].astype(np.float32)) / 255.0

@JeruLuke: D Я никогда раньше не слышал этого выражения. Самое близкое, что я слышал, - это использование птиц, но манго тоже работает :)

rayryeng 07.06.2018 22:59

Помимо CV2, использующего формат BGR и Keras (использующего PIL в качестве бэкэнда), использующего формат RGB, существуют также значительные различия в методах изменения размера CV2 и PIL с использованием одних и тех же параметров.

В Интернете можно найти множество ссылок, но общая идея заключается в том, что существуют тонкие различия в системах координат пикселей, используемых в двух алгоритмах изменения размера, а также потенциальные проблемы с различными методами приведения в плавающее положение в качестве промежуточного шага в алгоритме интерполяции. Конечный результат - визуально похожее изображение, но оно немного смещено / искажено между версиями.

Прекрасный пример состязательной атаки, которая может привести к огромным различиям в точности, несмотря на небольшие различия входных данных.

Недавно я столкнулся с такой же проблемой. Я попытался преобразовать цветовой канал и изменить размер изображения с помощью OpenCV. Однако у PIL и OpenCV есть очень разные способы изменения размера изображения. Вот точное решение этой проблемы.

Это функция, которая принимает путь к файлу изображения, конвертирует в целевой размер и подготавливает к модели Keras -

import cv2
import keras
import numpy as np
from keras.preprocessing import image
from PIL import Image

def prepare_image (file):
    im_resized = image.load_img(file, target_size = (224,224))
    img_array = image.img_to_array(im_resized)
    image_array_expanded = np.expand_dims(img_array, axis = 0)
    return keras.applications.mobilenet.preprocess_input(image_array_expanded)

# execute the function
PIL_image = prepare_image ("lena.png")

Если у вас есть изображение OpenCV, функция будет такой:

def prepare_image2 (img):
    # convert the color from BGR to RGB then convert to PIL array
    cvt_image =  cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    im_pil = Image.fromarray(cvt_image)

    # resize the array (image) then PIL image
    im_resized = im_pil.resize((224, 224))
    img_array = image.img_to_array(im_resized)
    image_array_expanded = np.expand_dims(img_array, axis = 0)
    return keras.applications.mobilenet.preprocess_input(image_array_expanded)

# execute the function
img = cv2.imread("lena.png")
cv2_image = prepare_image2 (img)

# finally check if it is working  
np.array_equal(PIL_image, cv2_image)
>> True

Да, конечно, поскольку вы используете предварительно обученную сеть, поэтому вам нужно использовать их методы предварительной обработки. Также обратите внимание, что вы используете MobileNetV2. Вам следует расширить свой ответ, чтобы обобщить его на любую предварительно обученную сеть.

rayryeng 06.10.2019 22:05

Другие вопросы по теме