Пролог

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

Предположим вот. Теперь вы можете меня найти и побить за кривой код)
Предположим вот. Теперь вы можете меня найти и побить за кривой код)

Нам нужно:

  • Сделать так, чтобы лазер отличал одни пиксели от других

  • Почистить всё лишнее

Иными словами - переводим цвет в чб и векторизуем растр. Получить надо что-то похожее на карандашный рисунок.

Завязка

Для начала установим библиотеку openCV для python. Для этого открываем терминал и прописываем:

pip install opencv-python

Таким легким движением мы установили openCV для всех наших python-проектов. Меня такой расклад устраивает, но если что вы всегда можете отступить от гайда и рабоать с виртуальной машиной) Теперь открываем любимый редактор, в моём случае VS code, и создаем проект.

Развитие

Следующее, что мы сделаем - импортируем cv2 и откроем изображение.

import cv2 as cv
orig = cv.imread('me.jpg')

Вместо me,jpg пропишите название изображения, находящегося в папке проекта. По религиозным причинам патента на RGB-модель openCV для хранения и обработки использует BGR-модель. Давайте наше цветное изображение конвертируем в ЧБ-формат, как будто делали фото на фотоаппарат бабули. Делается это следующим образом:

gray = cv.cvtColor(orig, cv.COLOR_BGR2GRAY)

Разберём подробно cv.cvtColor(orig, cv.COLOR_BGR2GRAY). Данная функция конвертирует изображение и возвращает результат. Первым аргументом является уже считанное изображение, а вторым - профиль конвертации. В cv2 их много, для всех нужд хватит, нам нужен один из самых простых.

Далее нам надо как-то почистить изображение от лишних пикселей, чтобы не было каши. Лучше всего с эти справится блюр короля математики (Гаусса), однако он размоет не пустоты (светлое), а наоборот, темное. То есть то, что нам необходимо выразить, поэтому предварительно мы инвертируем изображение, а после применения GaussianBlur вернём обратно.

inv_gray = 255 - gray
blur_img = cv.GaussianBlur(inv_gray, (11, 11), 0)
inv_blur = 255 - blur_img

cv.GaussianBlur(inv_gray, (11, 11), 0) принимает на вход три параметра: исходное изображения, размеры прямоугольника, откуда берется среднее показание для определения яркости текущего пикселя и так называемая sigma. Пока она нам не нужна, оставим 0.

Осталось только наложить на наше серое изображение замыленное в с яркостью белого 255 и готово. делаем это так:

sketch_img = cv.divide(gray, inv_blur, scale=255.0)

Кульминация

Давайте добавим еще просмотр каждого этапа до нажатия по кнопке. Тут я думаю объяснения излишни:

cv.imshow("orig", orig)
cv.waitKey()
cv.imshow("gray", gray)
cv.waitKey()
cv.imshow("inv_gray", inv_gray)
cv.waitKey()
cv.imshow("blur_img", blur_img)
cv.waitKey()
cv.imshow("inv_blur", inv_blur)
cv.waitKey()
cv.imshow("sketch_img", sketch_img)
cv.waitKey()
cv.imwrite("sketch.jpg", sketch_img)
cv.destroyAllWindows()

В конце я ещё сохраняю результат. Собираем проект и смотрим, что у нас получилось.

Поэтапно 1
Поэтапно 1
Поэтапно 2
Поэтапно 2
Результат)
Результат)

Четкость можно регулировать прямоугольником блюра и разрешением камеры.

Завязка

Давайте на последок для новичков ещё покажу как брать изображение с камеры в openCV.

Для этого сначала инициализируем нашу камеру, затем будем получать с нее фрейм до нажатия на кнопку. последний полученный кадр будет нашим изображением.

cam = cv.VideoCapture(0)
while True:
    _, frame = cam.read()
    cv.imshow("monit", frame)
    k = cv.waitKey(5)
    if k == ord("q"):
        cv.imwrite("me.jpg", frame)
        break

Ну а всё вместе выглядит так:

import cv2 as cv

cam = cv.VideoCapture(0)
while True:
    _, frame = cam.read()
    cv.imshow("monit", frame)
    k = cv.waitKey(5)
    if k == ord("q"):
        cv.imwrite("me.jpg", frame)
        break

orig = cv.imread('me.jpg')

gray = cv.cvtColor(orig, cv.COLOR_BGR2GRAY)

inv_gray = 255 - gray

blur_img = cv.GaussianBlur(inv_gray, (11, 11), 0)

inv_blur = 255 - blur_img

sketch_img = cv.divide(gray, inv_blur, scale=255.0)

cv.imshow("orig", orig)
cv.waitKey()
cv.imshow("gray", gray)
cv.waitKey()
cv.imshow("inv_gray", inv_gray)
cv.waitKey()
cv.imshow("blur_img", blur_img)
cv.waitKey()
cv.imshow("inv_blur", inv_blur)
cv.waitKey()
cv.imshow("sketch_img", sketch_img)
cv.waitKey()
cv.imwrite("sketch.jpg", sketch_img)
cv.destroyAllWindows()

Эпилог

Ну вроде всё рассказал, что хотел) Буду очень рад комментариям. Читайте предыдущие части)

Комментарии (0)