Привет. Хотел подарить племянникам раскраски, но обычные уже не идут, хочется, чтобы раскраска была одновременно и с персонажами игры и мультиков и всего-всего. Нужно делать свои, нашел пару сервисов, которые делают эскизы из фото, но они либо клеят вотермарки на результат, либо делают не то, что нужно мне, поэтому засел за созданием своего решения.
Готовое решение
Решение нашел достаточно быстро, им оказался метод Кэнни (или Оператор Кэнни), который выделяет границы у фото. Организовал его на OpenCV и с помощью фильтров PIL инвертировал фото, чтобы границы были белыми на черном фоне, а не наоборот. Покрутил еще пару фильтров PIL и пришел к результату:

Результат мне нравится, но четкие границы получаются у рисованных картинок с низкой детализацией, как на фото выше.

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

Еще протестировал программу на тестах для цветных принтеров. Результат неплохой для картинки такого типа, но буквы на темном фоне не видны. Поэтому если захотите превратить изображение в раскраску, то изображение:
-
Должно быть четким
-
Иметь меньше света и теней
-
Желательно иметь низкую детализацию
Попробовать программу вы можете тут — https://github.com/maestroTW/PicToColor
Там же лежит гайд на запуск и todo лист для контрибуторов
Код
Импортируем библиотеки и получаем фото
import PIL from PIL import Image, ImageEnhance, ImageOps import numpy as np import cv2 def make_coloring_page(image_path): # open img = Image.open(image_path)
Увеличиваем качество изображения с помощью PIL
contrast_enhancer = ImageEnhance.Contrast(img) high_contrast_img = contrast_enhancer.enhance(1.5) brightness_enhancer = ImageEnhance.Brightness(high_contrast_img) brighter_img = brightness_enhancer.enhance(1.2)
Используем Метод Кэнни для обнаружения границ изображения и инвертируем, чтобы получить результат на белом фоне
array = np.array(brighter_img) canny_edges = cv2.Canny(array, 100, 200) canny_edges = Image.fromarray(canny_edges) inverted_edges = PIL.ImageOps.invert(canny_edges)
Так-же для удобного использования сделал сайт и сервер на Flask, но тут все базово
Прикручиваем html файл
import base64 from flask import Flask, render_template, request from io import BytesIO import main app = Flask(__name__) @app.route('/') def index(): return render_template('index.html')
Форма для вставки изображения в html:
<form method="POST" action="/upload" enctype="multipart/form-data"> <input id="form-input" type="file" name="image_file" accept="image/*"> <button type="submit">Отправить</button> </form>
Получаем изображение на сервер, превращаем в байт код, чтобы хранить в памяти и отдаем пользователю на отдельной странице
@app.route('/upload', methods=['POST']) def upload(): image_file = request.files['image_file'] if image_file.filename == '': return 'Ошибка: выберите файл.', 400 result = main.make_coloring_page(image_file.stream) buffer = BytesIO() result.save(buffer, format='JPEG') img = b'<img src="data:image/jpeg;base64,' + base64.b64encode(buffer.getvalue()) + b'"/>' return f''' <html> <head><title>Result</title></head> <body> {img.decode()} </body> </html> '''
Полный код можете изучить в репозитории
Итог и планы
По итогу результат мне понравился, по крайней мере на данном этапе он удовлетворил мои потребности и я смог сделать раскраски для родных, но думаю тут еще есть, что допиливать.
Мои личные планы:
-
Добавить кнопку для быстрой установки изображения
-
Ползунок для настройки качества результата
Если у вас есть предложения по развитию проекта, то предлагайте их в комментариях или вносите свой вклад в репозиторий!
Дополнительные материалы
Метод Кэнни — https://ru.wikipedia.org/wiki/Оператор_Кэнни
Компьютерное зрение с OpenCV — https://habr.com/ru/articles/678260/
Обработка изображений с Pillow — https://habr.com/ru/articles/681248/
Гайд на Flask — https://habr.com/ru/articles/783574/
ссылка на оригинал статьи https://habr.com/ru/articles/893132/
Добавить комментарий