Новая функция поиск фото по фото.

Технология находиться в бета версии но свои функции выполняет правильно.

В создание модели сделана на классике CV или на базе нейронной сети. На вход модели - изображение, на выход - D-мерный дескриптор/эмбеддинг. В случае с классикой это может быть комбинация SIFT-дескриптора + Bag of Visual Words.

Так-же в систему была добавлена ИИ для распознание порнографический материалов

Предварительная обработка изображений

В classify_nsfw.py функция resize_image написана для обработки масштабирования изображения без использования встроенной программы масштабирования изображения caffe. Объяснение в комментариях к коду связано с тем, что этот алгоритм масштабирования используется во время обучения, поэтому для достижения наилучших результатов в тесте необходимо использовать алгоритм масштабирования. Затем изображение было снова обрезано, потому что resize_image был вызван для масштабирования до 256x256, а размер, принятый моделью, был 224x224.

img_data_rs = resize_image(pimg, sz=(256, 256))
image = caffe.io.load_image(StringIO(img_data_rs))

H, W, _ = image.shape
_, _, h, w = caffe_net.blobs['data'].data.shape
h_off = max((H - h) / 2, 0)
w_off = max((W - w) / 2, 0)

В коде C ++ я использовал метод opencv, предоставленный в caffe, для обработки этого шага:

cv::Mat img = ReadImageToCVMat(file, 256, 256);
...
// crop image
cv::Size size = sample.size();
int H = size.height;
int W = size.width;
int h = input_geometry_.height;
int w = input_geometry_.width;

int h_off = std::max((H - h) / 2, 0);
int w_off = std::max((W - w) / 2, 0);
sample(cv::Rect(w_off, h_off, w, h)).copyTo(sample_resized);

Предварительная обработка данных

В classify_nsfw.py мы можем увидеть такой кусок кода:

caffe_transformer = caffe.io.Transformer({'data': nsfw_net.blobs['data'].data.shape})
# move image channels to outermost
caffe_transformer.set_transpose('data', (2, 0, 1)) 
# subtract the dataset-mean value in each channel
caffe_transformer.set_mean('data', np.array([104, 117, 123])) 
# rescale from [0, 1] to [0, 255]
caffe_transformer.set_raw_scale('data', 255) 
# swap channels from RGB to BGR
caffe_transformer.set_channel_swap('data', (2, 1, 0))  

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

caffe_transformer.set_transpose('data', (2, 0, 1)) 

Это утверждение беспокоило нас долгое время, и я не знаю, как с ним справиться в программе на C ++. После проверки сетевой информации я узнал, что изображение, считываемое caffe.io, представляет собой матрицу HWC (H: высокий, W: широкий, C: цветной), а для модели caffe требуется формат (CHW), поэтому требуется преобразование матрицы. Переместите размер значения цвета на передний план. (2, 0, 1) означает переупорядочить 2, 0, 1 столбцы исходных данных в новом порядке.

caffe_transformer.set_raw_scale('data', 255) 

Эта обработка связана с тем, что значение цвета, считываемое с помощью caffe.io, нормализуется до числа от 0 до 1, а модель кафе принимает целое число байтов от 0 до 255, поэтому требуется усиление.

В коде C ++, поскольку opencv используется для обработки изображений, два вышеуказанных шага обработки преобразования не требуются.

caffe_transformer.set_mean('data', np.array([104, 117, 123]))

Во многих примерах среднее значение обычно загружается из файла среднего значения, и здесь прямо указывается фиксированное значение. Так называемое среднее значение можно понимать как среднее арифметическое данных. Обычно входные данные вычитаются из среднего, чтобы уменьшить влияние сингулярных значений (аномальные значения, значения, которые намного больше или меньше среднего). Вот триплет, который представляет среднее значение на канале RGB.

Соответствующий код C ++ выглядит следующим образом:

cv::Mat sample_normalized;
cv::subtract(sample_float, mean_, sample_normalized);

Следующий код - это RGB в BGR, который легче понять.

caffe_transformer.set_channel_swap('data', (2, 1, 0)) 

Мы проверили несколько примеров caffe C ++, ни один из которых не содержит этого шага. Возможно, cv :: Mat уже может правильно оценивать RGB и BGR, поэтому этот шаг не добавлен в код.