Обнаружение определенного водяного знака на фотографии с помощью Python (без SciPy)

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

До сих пор я пытался использовать PIL и функцию обрезки, чтобы изолировать область изображения, где должен быть водяной знак, а затем сравнивал гистограммы с функцией RMS (см. Http://snipplr.com/view/757/compare- two-pil-images-in-python / ). Это не работает очень хорошо, так как в обоих направлениях есть много ошибок.

Любые идеи будут высоко оценены. благодаря

Другая возможность – использовать машинное обучение. Мой фон – естественная обработка языка (не компьютерное зрение), но я попытался создать набор для обучения и тестирования, используя описание вашей проблемы, и, похоже, он работает (точность 100% по невидимым данным).

Обучающий набор

Учебный набор состоял из тех же изображений с водяным знаком (положительный пример) и без водяного знака (отрицательный пример).

Набор для тестирования

Набор тестов состоит из изображений, которые не были в наборе тренировок.

Примеры данных

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

Код:

Полная версия доступна как сущность . Выдержка ниже:

import glob from classify import MultinomialNB from PIL import Image TRAINING_POSITIVE = 'training-positive/*.jpg' TRAINING_NEGATIVE = 'training-negative/*.jpg' TEST_POSITIVE = 'test-positive/*.jpg' TEST_NEGATIVE = 'test-negative/*.jpg' # How many pixels to grab from the top-right of image. CROP_WIDTH, CROP_HEIGHT = 100, 100 RESIZED = (16, 16) def get_image_data(infile): image = Image.open(infile) width, height = image.size # left upper right lower box = width - CROP_WIDTH, 0, width, CROP_HEIGHT region = image.crop(box) resized = region.resize(RESIZED) data = resized.getdata() # Convert RGB to simple averaged value. data = [sum(pixel) / 3 for pixel in data] # Combine location and value. values = [] for location, value in enumerate(data): values.extend([location] * value) return values def main(): watermark = MultinomialNB() # Training count = 0 for infile in glob.glob(TRAINING_POSITIVE): data = get_image_data(infile) watermark.train((data, 'positive')) count += 1 print 'Training', count for infile in glob.glob(TRAINING_NEGATIVE): data = get_image_data(infile) watermark.train((data, 'negative')) count += 1 print 'Training', count # Testing correct, total = 0, 0 for infile in glob.glob(TEST_POSITIVE): data = get_image_data(infile) prediction = watermark.classify(data) if prediction.label == 'positive': correct += 1 total += 1 print 'Testing ({0} / {1})'.format(correct, total) for infile in glob.glob(TEST_NEGATIVE): data = get_image_data(infile) prediction = watermark.classify(data) if prediction.label == 'negative': correct += 1 total += 1 print 'Testing ({0} / {1})'.format(correct, total) print 'Got', correct, 'out of', total, 'correct' if __name__ == '__main__': main() 

Пример вывода

 Training 1 Training 2 Training 3 Training 4 Training 5 Training 6 Training 7 Training 8 Training 9 Training 10 Training 11 Training 12 Training 13 Training 14 Testing (1 / 1) Testing (2 / 2) Testing (3 / 3) Testing (4 / 4) Testing (5 / 5) Testing (6 / 6) Testing (7 / 7) Testing (8 / 8) Testing (9 / 9) Testing (10 / 10) Got 10 out of 10 correct [Finished in 3.5s] 

Точная позиция водяного знака? Как применяется водяной знак к фоновому изображению?

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

 resultPixel = imagePixel + (watermarkPixel*mixinValue) 

mixinValue будет 0.0-1.0, поэтому вы можете заполнить микс, повторно применив водяной знак с помощью множителя (1-mixinValue). Это должно привести к тому, что пиксели будут соответствовать водяному знаку. Просто проверьте цвет изображения результата с исходным водяным знаком.

 testPixel = resultPixel + (watermarkPixel*(1-mixinValue)) assert testPixel == watermarkPixel 

Конечно, сжатие водяного знака, вероятно, вызовет некоторое отклонение в вашем testPixel.

Вы всегда можете использовать API-интерфейс специализированного распознавания изображений для restb.ai для автоматизации процесса обнаружения водяных знаков.

  импортные запросы

 url = "https://api.restb.ai/segmentation"

 querystring = {"client_key": "your-free-key-here", "model_id": "re_logo", "image_url": "http://demo.restb.ai/img/gallery/realestate/logos-watermarks/ re_logo-1.jpg "}

 response = request.request ("GET", url, params = querystring)

 печать (response.text) 

Скриншот демонстрации логотипа и водяного знака