- 1. Побитовые операции и маскирование
- 2. Свертка и размытие
- 3. Повышение резкости - изменение размытия изображения.
- 4. Threshoding (бинаризация)
- 5. Расширение, эрозия, открытие / закрытие
- 6. Обнаружение краев и градиенты изображения
- 14. Перспектива и аффинное преобразование
- 8. Приложение Live Sketch
В предыдущих уроках мы узнали об OpenCV и выполнили некоторую базовую обработку изображений, а затем в следующем уроке мы сделали некоторые манипуляции с изображениями в OpenCV, такие как обрезка, поворот, преобразование изображения и т.д. еще несколько техник манипулирования изображениями, например, в конце учебника мы создадим программу python-opencv для создания живого скетча из прямой трансляции веб-камеры. Это приложение будет использовать многие функции обработки изображений, которые мы уже изучили или изучим в этом руководстве, так что это будет хороший практический пример, охватывающий все функции.
Как было сказано в предыдущем руководстве, OpenCV - это библиотека Commuter Vision с открытым исходным кодом, которая имеет интерфейсы C ++, Python и Java и поддерживает Windows, Linux, Mac OS, iOS и Android. Таким образом, его можно легко установить в Raspberry Pi в среде Python и Linux. А Raspberry Pi с OpenCV и подключенной камерой можно использовать для создания множества приложений для обработки изображений в реальном времени, таких как обнаружение лиц, блокировка лица, отслеживание объектов, обнаружение автомобильных номеров, система домашней безопасности и т. Д.
В этом руководстве мы увидим еще несколько манипуляций с изображениями с использованием Python OpenCV. Здесь мы научимся применять следующую функцию к изображению с помощью Python OpenCV:
- Побитовые операции и маскирование
- Свертка и размытие
- Повышение резкости - изменение размытия изображения
- Пороговая обработка (бинаризация)
- Расширение, эрозия, открытие / закрытие
- Обнаружение краев и градиенты изображения
- Перспектива и аффинное преобразование
- Приложение Live Sketch
1. Побитовые операции и маскирование
Побитовые операции помогают вам в маскировке изображений и помогают создавать простые изображения.
Делаем квадрат
import cv2 import numpy as np # мы используем только два измерения, потому что это изображение в оттенках серого, если бы мы использовали # цветное изображение, тогда мы использовали бы rectangle = np.zeros ((300,300,3), np.uint8) # Создание квадрата square = np.zeros ((300,300), np.uint8) cv2.rectangle (square, (50,50), (250,250), 255, -1) cv2.imshow ("квадрат", квадрат) cv2. waitKey (0)
Делаем эллипс
ellipse = np.zeros ((300,300), np.uint8) cv2.ellipse (ellipse, (150,150), (150,150), 30,0,180,255, -1) cv2.imshow ("эллипс", эллипс) cv2.waitKey (0)
Экспериментируйте с поразрядными операциями
#AND_показывает только места пересечения
Побитовое И = cv2.bitwise_and (квадрат, эллипс) cv2.imshow («И», Побитовое И) cv2.waitKey (0)
#OR_показывает только квадрат или эллипс
BitwiseOR = cv2.bitwise_or (квадрат, эллипс) cv2.imshow («OR», BitwiseOR) cv2.waitKey (0)
#XOR_shows только там, где любой существует сам по себе
BitwiseXOR = cv2.bitwise_xor (квадрат, эллипс) cv2.imshow ("XOR", BitwiseXOR) cv2.waitKey (0)
#NOT_shows все, что не является частью эллипса, и операцию NOT можно применить только к одной фигуре
BitwiseNOT_elp = cv2.bitwise_not (эллипс) cv2.imshow ("NOT_ellipse", BitwiseNOT_elp) cv2.waitKey (0) cv2.destroyAllWindows ()
2. Свертка и размытие
Свертки является математической операцией, выполняемой на двух функций, производящих третью функцию, которая обычно представляет собой модифицированный вариант исходной функции.
Выходное изображение = изображение Функция Размер ядра
В компьютерном зрении мы используем ядро, чтобы указать размер, над которым мы запускаем нашу функцию управления нашим изображением.
Размытие - это операция, при которой мы усредняем пиксели в пределах области (ядра).
OpenCV размывает изображение, применяя ядра, ядро сообщает вам, как изменить значение любого заданного пикселя, комбинируя его с разным количеством соседних пикселей, ядро применяется к каждому пикселю изображения один за другим для создания окончательного изображения.
Проще говоря, свертка изображений - это просто поэлементное умножение двух матриц с последующей суммой.
Мы можем просто понять это на следующем примере.
Это ядро 3x3.
Мы умножаем на 1/25, чтобы нормализовать, т.е. суммировать до 1, мы увеличивали или уменьшали интенсивность, как в случае осветления или затемнения изображений.
Давайте протестируем метод размытия opencv filter2D, заданный функцией cv2.filter2D (image, -1, kernel)
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# создание матрицы ядра 3x3
ядро_3x3 = np.ones ((3,3), np.float32) / 9
# мы используем cv2.filter2D для свертки ядра с изображением
blurred = cv2.filter2D (изображение, -1, kernel_3x3) cv2.imshow ('3x3_blurring', размыто) cv2.waitKey (0)
# создание матрицы ядра 7x7
ядро_7x7 = np.ones ((7,7), np.float32) / 49
# мы используем cv2.filter2D для свертки ядра с изображением
blurred = cv2.filter2D (изображение, -1, kernel_7x7) cv2.imshow ('7x7_blurring', размыто) cv2.waitKey (0) cv2.destroyAllWindows ()
Есть и другие методы размытия:
cv2.blur - усредняет значение в указанном окне.
cv2.GaussianBlur - аналогично, но использует окно Гаусса (больше внимания уделяется точкам вокруг центра).
cv2.medianBlur– использует медианное значение всех элементов в окне.
cv2.bilateralFilter– Размывает с сохранением резкости краев, сохраняет края и детали линий.
Мы увидим одно за другим ниже, сначала отобразим исходное изображение, используя приведенный ниже код:
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
cv2.blur:
В этом методе усреднение выполняется путем свертки изображения с помощью нормализованного прямоугольного фильтра, который занимает место под прямоугольником и заменяет центральный элемент. Здесь размер коробки должен быть нечетным и положительным .
# cv2.blur blur = cv2.blur (image, (3,3)) cv2.imshow ('Усреднение', размытие) cv2.waitKey (0)
cv2.GaussianBlur:
# cv2.GaussianBlur # вместо блочного фильтра давайте попробуем гауссовское ядро Gaussian = cv2.GaussianBlur (image, (7,7), 0) cv2.imshow ('Gaussian blurring', Gaussian) cv2.waitKey (0)
cv2.medianBlur:
Требуется медиана всех пикселей под областью ядра, а центральный элемент заменяется этим медианным значением.
# cv2.medianBlur # берет медианное значение всех пикселей под областью ядра, а центральный элемент # заменяется этим медианным значением. Медиана = cv2.medianBlur (изображение, 5) cv2.imshow ('медианный размывания', медиана) cv2.waitKey (0)
cv2.bilateralFilter:
Двусторонний очень эффективен для удаления шума, сохраняя при этом края острыми.
# cv2.bilateralFilter #Bateral очень эффективен при удалении шума при сохранении резкости краев. двусторонний = cv2.bilateralFilter (image, 9,75,75) cv2.imshow («двустороннее размытие», двустороннее) cv2.waitKey (0) cv2. destroyAllWindows ()
Image De-Noising-Non Local означает Denoising
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# параметр после None - это сила фильтра 'h' (5-10 - хороший диапазон) # следующий - h для цветовых компонентов, снова установите то же значение, что и h
dst = cv2.fastNlMeansDenoisingColored (image, None, 6,6,7,21) cv2.imshow ('Быстрое означает шумоподавление', dst) cv2.waitKey (0) cv2.destroyAllWindows ()
Существует 4 варианта нелокальных средств шумоподавления.
cv2.fastNlMeansDenoising () - для одного серого изображения
cv2.fastNlMeansDenoisingColored () - Одноцветное изображение
cv2.fastNlmeansDenoisingMulti () - для последовательности изображений в оттенках серого
cv2.fastNlmeansDenoisingcoloredMulti () - для последовательности цветных изображений
3. Повышение резкости - изменение размытия изображения.
Повышение резкости противоположно размытию, оно усиливает или подчеркивает края изображения.
Ядро =,,
Наша матрица ядра суммирует до единицы, поэтому нет необходимости нормализовать (то есть умножать на коэффициент для такой же яркости, как у оригинала), если ядро не нормализовано до 1, изображение будет ярче или темнее.
import cv2 import numpy as np image = cv2.imread ('elephant.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
kernel_sharpening = np.array (,
])
# применение ядра повышения резкости к входному изображению
sharpened = cv2.filter2D (image, -1, kernel_sharpening) cv2.imshow ('резкость изображения', резкость) cv2.waitKey (0) cv2.destroyAllWindows ()
4. Threshoding (бинаризация)
Пороговая обработка - это акт преобразования изображения в двоичную форму. В opencv есть отдельная функция для определения порога, определяемая как
Cv2.threshold (изображение, пороговое значение, максимальное значение, тип порога)
Различают следующие типы порогов:
- cv2.THRESH_BINARY - наиболее распространенный
- cv2. THRESH_BINARY_INV - наиболее распространенный
- cv2.THRESH_TRUNC
- cv2.THRESH_TOZERO
- cv2. THRESH_TOZERO_INV
ПРИМЕЧАНИЕ: изображение необходимо преобразовать в оттенки серого перед установкой порога.
import cv2 import numpy as np #load image as grayscale image = cv2.imread ('gradient.jpg', 0) cv2.imshow ('original', image) cv2.waitKey (0)
# значение ниже 127 переходит в 0 (черный), а выше 127 переходит в 255 (белый)
_, thresh1 = cv2.threshold (изображение, 127,255, cv2.THRESH_BINARY) cv2.imshow ('1 threshold', thresh1) cv2.waitKey (0)
# значение ниже 127 переходит в 255, а значения выше 127 - в 0 (обратное выше)
_, thresh2 = cv2.threshold (изображение, 127,255, cv2.THRESH_BINARY_INV) cv2.imshow ('2 threshold', thresh2) cv2.waitKey (0)
# значения выше 127 усекаются (удерживаются) до 127, аргумент 255 не используется.
_, thresh3 = cv2.threshold (изображение, 127,255, cv2.THRESH_TRUNC) cv2.imshow ('3 thresh trunc', thresh3) cv2.waitKey (0)
# значения ниже 127 переходят в 0, выше 127 не меняются
_, thresh4 = cv2.threshold (изображение, 127,255, cv2.THRESH_TOZERO) cv2.imshow ('4 threshold', thresh4) cv2.waitKey (0)
# Revesrse выше, ниже 127 не меняется, выше 127 обнуляется
_, thresh5 = cv2.threshold (изображение, 127,255, cv2.THRESH_TOZERO_INV) cv2.imshow ('5 threshold', thresh5) cv2.waitKey (0) cv2.destroyAllWindows ()
5. Расширение, эрозия, открытие / закрытие
Это операции в области математической морфологии.
Расширение - добавляет пиксели к границам объекта на изображении.
Эрозия - удаляет пиксели на границах объекта на изображении.
Открытие - Эрозия с последующим расширением.
Закрытие - Расширение с последующей эрозией.
Открытие очень помогает в шумоподавлении изображений, поскольку оно сначала уменьшает изображение за счет эрозии (удаляет шум), а затем расширяет его.
Путаница с расширением и эрозией
Иногда возникает путаница между расширением и эрозией, обычно на изображениях с белым фоном, поскольку opencv рассматривает белый фон как изображение, которое будет расширено или эродировано вместо исходного изображения, поэтому в этом случае эрозия работает как расширение и наоборот, как показано в образце изображения показано ниже.
Помните, что Dilation добавляет пиксели к границам объектов на изображении, а Erosion удаляет пиксели на границах объектов на изображении.
import cv2 import numpy as np image = cv2.imread ('imagecv.png', 0) cv2.imshow ('original', image) cv2.waitKey (0)
# Эрозия
# давайте определим размер нашего ядра
ядро = np.ones ((5,5), np.uint8)
# теперь мы размываем изображение, здесь итерация не раз, когда вы хотите размыть изображение
erosion = cv2.erode (изображение, ядро, итерации = 1) cv2.imshow ('Размытие', размывание) cv2.waitKey (0)
#dilation
dilation = cv2.dilate (изображение, ядро, итерации = 1) cv2.imshow ('dilation', dilation) cv2.waitKey (0)
#opening, Хорошо для удаления шума
open = cv2.morphologyEx (изображение, cv2.MORPH_OPEN, ядро) cv2.imshow ('открытие', открытие) cv2.waitKey (0)
#closing, Хорошо для удаления шума
закрытие = cv2.morphologyEx (изображение, cv2.MORPH_CLOSE, ядро) cv2.imshow ('закрытие', закрытие) cv2.waitKey (0) cv2.destroyAllWindows ()
6. Обнаружение краев и градиенты изображения
Обнаружение краев - очень важная область компьютерного зрения, особенно при работе с контурами.
Края могут быть определены как границы изображения, на самом деле это края, которые определяют объект в изображениях, они сохраняют много информации об изображении.
Формально края можно определить как внезапные изменения (неоднородности) изображения, и они могут кодировать столько же информации, сколько и пиксели.
На изображении выше показано, как компьютерное зрение идентифицирует и распознает изображение.
Алгоритмы обнаружения кромок : - Существует три основных типа алгоритмов обнаружения кромок.
- Собел - для выделения вертикальных или горизонтальных изображений.
- Лапласиан - оптимальный благодаря низкой частоте ошибок, четко определенным краям и точному обнаружению.
- Алгоритм обнаружения Canny Edge (переделан Джоном Ф. Кэнни в 1986 г.)
1. Применяет размытие по Гауссу
2. Находит градиент интенсивности изображения.
3. применяет не максимальное подавление (т. Е. Удаляет пиксели, не являющиеся краями).
4. Гистерезис применяет порог (т. Е. Если пиксель находится в пределах верхнего и нижнего порога, он считается краем)
import cv2 import numpy as np image = cv2.imread ('input.jpg', 0) height, width = image.shape
#sobel
# извлечение кромок собел
sobel_x = cv2.Sobel (изображение, cv2.CV_64F, 0,1, ksize = 5) sobel_y = cv2.Sobel (изображение, cv2.CV_64F, 1,0, ksize = 5) cv2.imshow ('исходное', изображение) cv2.waitKey (0) cv2.imshow ('sobelx', sobel_x) cv2.waitKey (0)
#Sobely
cv2.imshow ('собелий', собел_й) cv2.waitKey (0)
sobel_OR = cv2.bitwise_or (sobel_x, sobel_y) cv2.imshow ('sobelOR', sobel_OR) cv2.waitKey (0)
#laplaian
Laplacian = cv2.Laplacian (image, cv2.CV_64F) cv2.imshow ('Laplacian', Laplacian) cv2.waitKey (0)
Алгоритм #canny edge detection использует значения градиента в качестве пороговых значений. #in canny
нам нужно предоставить два значения: threshold1 и threshold2.
# любой градиент, превышающий порог 2, считается краем.
# любой градиент, превышающий порог 1, не считается краем.
#values промежуточный порог 1 и 2 порога либо, как край или некраевой
#on, как их интенсивности связаны, в этом случае любое значение ниже 60 будут рассмотрены
#non краев wheareas любое значение выше 120 рассматриваются как краями.
canny = cv2.Canny (изображение, 60,120 ) cv2.imshow ('ловкий', ловкий ) cv2.waitKey (0) cv2.destroyAllWindows ()
14. Перспектива и аффинное преобразование
Давайте сделаем шаг назад и посмотрим на аффинные и неаффинные преобразования, исходное изображение, показанное ниже, явно неаффинное изображение, поскольку края в какой-то момент встретятся, однако мы можем выпрямить его, деформируя и принимая перспективу. преобразовать.
Для этого перспективного преобразования нам нужны четыре координаты исходного изображения, а затем четыре точки выходного изображения, они обозначены точками points_A и points_B. Сначала с помощью этих точек мы вычисляем матрицу преобразования M с помощью функции getPerspectiveTransform.
Затем эта матрица передается в функцию warpPerspective для генерации окончательного результата.
Теперь давайте сначала попробуем преобразование перспективы.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('paper.jpg') cv2.imshow ('original', image) cv2.waitKey (0)
# координата 4-х углов исходного изображения
points_A = np.float32 (,,,])
# координаты 4 углов желаемого результата
# мы используем соотношение бумаги формата A4 1: 1,41
points_B = np.float32 (,,,])
# использовать два набора из двух точек для вычисления предполагаемой матрицы преобразования M
M = cv2.getPerspectiveTransform (points_A, points_B) warped = cv2.warpPerspective (image, M, (420,594)) cv2.imshow ('warpprespective', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
Аффинное преобразование проще, чем неаффинное преобразование, поскольку нам нужно всего три точки, чтобы получить преобразование. Весь процесс происходит так же, но вместо перспективного преобразования у нас теперь есть аффинное преобразование, а также мы определяем столбцы и строки в warpAffine из функции shape вместо того, чтобы вводить ее вручную.
import cv2 import numpy as np import matplotlib.pyplot as plt image = cv2.imread ('box.jpg') rows, cols = image.shape cv2.imshow ('original', image) cv2.waitKey (0)
# координата 3-х углов исходного изображения
points_A = np.float32 (,,])
# координаты трех углов желаемого результата
# мы используем соотношение бумаги формата A4 1: 1,41
points_B = np.float32 (,,])
# использовать два набора из двух точек для вычисления
аффинной # матрицы преобразования, M
M = cv2.getAffineTransform (points_A, points_B) warped = cv2.warpAffine (image, M, (cols, rows)) cv2.imshow ('warpaffine', warped ) cv2.waitKey (0) cv2.destroyAllWindows ()
8. Приложение Live Sketch
Прежде всего, поздравьте себя с тем, что вы сделали этот мини-проект после прочтения всех вышеперечисленных функций манипулирования изображениями. Итак, в этом мини-проекте Python OpenCV мы собираемся изучить некоторые новые концепции циклов и функций. Если вы знакомы с программированием, вы должны иметь более широкое представление о функциях и циклах. Однако в Python основная концепция циклов и функций остается прежней, но метод их определения немного меняется.
Итак, в начале этой программы мы видим определенную группу операторов под заголовком « def sketch (image)»: это формальное определение функции, группы операторов, работающих вместе для определенного вывода.
Итак, этот скетч является функцией, в Python функция определяется как def и заканчивается знаком «:». Кроме того, операторы, которые должны находиться внутри функции или вы можете сказать, какие требуются для правильной работы функции, автоматически выравниваются по сторонам функцией. Итак, чтобы выйти из функций, операторы должны быть полностью выровнены по левому краю. Для получения дополнительных ссылок вы можете обратиться к Google о том, как функции определены в python.
Итак, в этой функции скетча мы ввели несколько уровней обработки изображения, которые объединяются для получения результата. Во-первых, изображение преобразуется в оттенки серого, чтобы opencv мог легко его обработать, а затем к изображению с оттенками серого применяется размытие по Гауссу, чтобы уменьшить шум. Затем края извлекаются с помощью алгоритма обнаружения краев канни, затем двоичный инверсный применяется к определенному краю изображению, здесь двоичное инверсное также может быть выполнено с помощью bitwise_NOT, но мы сознательно выбрали этот пороговый двоичный инверс, поскольку он дает свободу установить его параметры, пока мы не получим четкое изображение.
Также следует отметить, что функция принимает изображение аргументов и возвращает два аргумента ret и mask. В то время как ret - это логическое значение, указывающее, что функция выполнена успешно или нет, а маска - это окончательный результат функции, то есть обработанное изображение.
Тогда вторая концепция операционной веб - камеры в OpenCV, что делается с помощью cv2.VideoCapture (0) функции, которая сохраняет изображение в качестве объекта колпачка , что крышка может быть прочитана с cap.read () функцией, также здесь отметить, что колпачок. read () находится внутри бесконечного цикла while, поскольку ему постоянно приходилось захватывать изображения, чтобы придать ему ощущение живого видео, где частота кадров видео будет частотой кадров вашей веб-камеры, которая в основном составляет от 24 до 60 кадров в секунду.
cap.read () возвращает ret и frame, где ret - это логическое значение, указывающее, что функция была успешно запущена или нет, а кадр содержит изображение, снятое веб-камерой.
Ниже приведен полный код Python OpenCV для запуска Live Sketch.
import cv2 import numpy as np # функция создания эскиза def sketch (image): # преобразовать изображение в оттенки серого img_gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) # очистить изображение с помощью размытия по Гауссу img_gray_blur = cv2.GaussianBlur, (img_gray 5,5), 0) #extract Edge canny_edges = cv2.Canny (img_gray_blur, 10,70) # сделать инвертировать бинаризованное изображение ret, mask = cv2.threshold (canny_edges, 70,255, cv2.THRESH_BINARY_INV) return mask #initialize webcam, cap - объект, предоставленный захватом видео. # он содержит логическое значение, указывающее, было ли оно успешным (ret) # он также содержит изображения, собранные с веб-камеры (кадр) cap = cv2.VideoCapture (0), а True: ret, frame = cap.read () cv2.imshow ('livesketcher', sketch (кадр)), если cv2.waitKey (1) == 13: # 13 является enterkey перерыв #release камеры и закрыть окно, не забудьте освободить веб - камеру с помощью cap.release () cap.release () cv2.destroyAllWindows ()
Итак, это конец второй части манипуляций с изображениями в Python-OpenCV. Чтобы получить хорошее представление о компьютерном зрении и OpenCV, прочтите предыдущие статьи («Начало работы с Python OpenCV и манипуляции с изображениями в Python OpenCV (часть 1)», и вы сможете сделать что-нибудь крутое с помощью Computer Vision.