Я изучаю глубокое обучение. Обучил алгоритм классификации изображений. Проблема, однако, в том, что для обучения изображений я использовал:
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 Обновленный вопрос
image.load_img() использует PIL, который читает в RGB, а cv2.imread() читает в BGR. Это единственная разница.





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 Я никогда раньше не слышал этого выражения. Самое близкое, что я слышал, - это использование птиц, но манго тоже работает :)
Помимо 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. Вам следует расширить свой ответ, чтобы обобщить его на любую предварительно обученную сеть.
По-другому как? Другая форма, данные?