Что такое контур изображения
В предыдущем обнаружении края, хотя мы можем обнаружить информацию о крае, край является прерывистым, и обнаруженный край не является целым. Контур изображения отвечает за соединение ребер в единое целое для последующих вычислений.
Следует отметить, что контур изображения является очень важной информацией об особенностях.Благодаря операции с контуром изображения мы можем получить такую информацию, как размер, положение и направление целевого изображения.
Найдите контуры изображения
Контур на изображении соответствует ряду точек, которые в той или иной форме представляют собой кривую на изображении. В OpenCV он предоставляет нам функцию cv2.findContours() для поиска контуров изображения и может возвращать контуры определенного представления в соответствии с параметрами.
Полное определение функции выглядит следующим образом:
def findContours(image, mode, method, contours=None, hierarchy=None):
изображение: исходное изображение, все ненулевые значения обрабатываются как 1, а все 0 значений остаются неизменными
режим: режим поиска контура
параметр | значение |
---|---|
cv2.RETR_EXTERNAL | Обнаружение только внешних контуров |
cv2.RETR_LIST | Для обнаруженных контуров не устанавливается иерархическая связь |
cv2.RETR_CCOMP | Обнаружьте все контуры и организуйте их в двухуровневую иерархию. Верхний слой — это внешняя граница, а нижний слой — внутренняя граница отверстия. Если во внутреннем отверстии есть связанный объект, то граница этого объекта все еще находится на верхнем слое. |
cv2.RETR_TREE | Построить схему иерархической древовидной структуры |
метод: метод аппроксимации контуров
параметр | значение |
---|---|
cv2.CHAIN_APPROX_NONE | Сохраните все точки контура, а разница в позициях пикселей между двумя соседними точками не превышает 1 |
cv2.CHAIN_APPROX_SIMPLE | Сжимайте элементы в горизонтальном направлении, вертикальном направлении и направлении линии объекта и сохраняйте только координаты конечной точки в этом направлении. Например, в крайних случаях прямоугольнику нужно всего 4 точки для хранения информации о контуре. |
cv2.CHAIN_APPROX_TC89_L1 | Стиль алгоритма аппроксимации с использованием цепочки teh_Chinl |
cv2.CHAIN_APPROX_TC89_KCOS | Стиль алгоритма аппроксимации с использованием цепочки teh_Chinl |
контуры: возвращенные контуры. Например, на изображении есть 3 непересекающихся фигуры: круг, прямоугольник и вперед и назад. Тогда это список длины 3, то есть контуров 3, контуры[i][j] — это j-я точка i-го контура.
Конечно, контуры изображения не обязательно непересекающиеся.Если контуры нескольких фигур пересекаются друг с другом, образуется связь родитель-потомок.Contours[i] использует четыре элемента для описания иерархической связи контуров.
- Next: Индекс следующего контура
- Предыдущий: Индекс предыдущего контура
- First_Child: порядковый номер первого дочернего контура
- Parent: порядковый номер родительского контура
Если все вышеуказанные параметры пусты, то есть случай, когда контуры фигур, упомянутых выше, не пересекаются. и значение "-1".
Особо отметим, что иерархическая структура контура определяется режимом параметров, то есть при использовании разных режимов получаются разные номера контуров, и иерархия тоже разная.
иерархия: информация о топологии изображения
Его возвращаемое значение — 3 параметра: изображение, контуры и иерархия. В версии OpenCV4.X функция возвращает только два значения: контуры, иерархия.
Далее мы сосредоточимся на режиме параметров.
режим параметра
(1) cv2.RETR_EXTERNAL (обнаружение только внешнего контура)
Если теперь у нас есть наше изображение, как показано выше, когда мы используем параметр cv2.RETR_EXTERNAL, информация о топологии иерархии будет следующей:
[[ [1 -1 -1 -1] [-1 0 -1 -1] ]]
[1 -1 -1 -1] Эти четыре параметра соответствуют четырем элементам контуров соответственно.
Next1: То есть это означает следующий контур, где следующий контур 0 равен 1
Предыдущий-1: 0-й контур не имеет предыдущего контура
First_Child-1: 0 не имеет дочерних контуров
Parent-1: 0 также не существует родительского контура
[-1 0 -1 -1] соответствует изображению 1 и имеет следующие значения:
-1 : 1 контур не существует следующий контур
0: 1-й контур имеет предыдущий 0-й контур, поэтому он равен 0
-1 : 1 не существует подконтуров
-1:1 родительский контур также не существует
Его топология выглядит следующим образом:
(2) cv2.RETR_LIST (не устанавливать иерархическую связь для обнаруженного контура)
Предположим, мы используем исходное изображение, как показано выше, тогда значение иерархии равно:
[[ [1 -1 -1 -1] [2 0 -1 -1] [-1 1 -1 -1] ]]
[1 -1 -1 -1] Значение:
1: Следующий контур нулевого контура равен 1, поэтому возвращаем 1
-1: 0-й контур не имеет предыдущего контура, поэтому -1
-1 : 0 не существует подконтуров
-1:0 также не существует родительского контура
[2 0 -1 -1] Значение:
Следующий контур контура 2:1 равен 2, поэтому возвращаем 2
0: Контур перед первым контуром равен 0, поэтому значение равно 0
-1 : 1 не существует подконтуров
-1:1 родительский контур также не существует
[-1 1 -1 -1] Значение:
Контур -1:2 не имеет следующего контура, поэтому возвращаем -1
1: передний контур второго контура равен 1, поэтому значение равно 1
-1 : 2 не существует подконтуров
-1:2 также не существует родительского контура
Топология этой связи такова:
(3) cv2.RETR_CCOMP (построить два уровня контуров)
Когда параметр режима равен cv2.RETR_CCOMP, исходное изображение выглядит так, как показано выше, и его иерархическое значение:
[[ [1 -1 -1 -1] [-1 0 2 -1] [-1 -1 -1 1] ]]
[1 -1 -1 -1] означает следующее:
Следующий контур контура 1:0 равен 1, поэтому возвращаем 1
-1: 0-й контур не имеет предыдущего контура, поэтому значение равно -1.
-1 : 0 не существует подконтуров
-1:0 также не существует родительского контура
[-1 0 2 -1] означает следующее:
-1: 1 контур не имеет следующего контура, поэтому возвращаем -1
0: Контур перед первым контуром равен 0, поэтому значение равно 0
2 : Подконтур 1-го контура равен 2, поэтому значение равно 2.
-1: 1-й контур также не имеет родительского контура
[-1 -1 -1 1] означает следующее:
Контур -1:2 не имеет следующего контура, поэтому возвращаем -1
-1: Контур не существует до 2-го контура, поэтому значение равно -1.
-1: 2-й контур также не имеет подконтуров
1: Родительский контур второго контура равен 1, поэтому значение равно 1.
Его топология выглядит следующим образом:
(4) cv2.RETR_TREE (построение схемы иерархической древовидной структуры)
Когда граф все еще (3) граф, его значение режима равно cv2.RETR_TREE, а возвращаемое значение иерархии:
[[ [1 -1 -1 -1] [-1 0 2 -1] [-1 -1 -1 1] ]]
[1 -1 -1 -1] означает следующее:
Контур 1:0 Следующий контур равен 1, поэтому возвращаем 1
-1: Контур не существует до 0-го контура, поэтому значение равно -1.
-1: 0-й контур также не имеет подконтуров
-1: 0-й контур также не имеет родительского контура
[-1 0 2 -1] означает следующее:
-1: 1 контур не имеет следующего контура, поэтому возвращаем -1
0: Контур перед первым контуром равен 0, поэтому значение равно 0
2: Первый контур имеет подконтур 2, поэтому значение равно 2.
-1: у первого контура нет родительского контура
[-1 -1 -1 1] означает следующее:
Контур -1:2 не имеет следующего контура, поэтому возвращаем -1
-1: 2-й контур не имеет переднего контура, поэтому значение равно -1.
-1: для 2-го контура не существует подконтуров
1: Второй контур имеет родительский контур 1, значение равно 1
Топология также является (3)-графом.
нарисовать контур изображения
В OpenCV он предоставляет нам cv2.drawContours() для рисования контуров изображения, и его полное определение выглядит следующим образом:
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None):
image: изображение контура, который будет нарисован
контуры: контуры, которые нужно нарисовать
контурIdx: индекс края, который необходимо нарисовать, -1 означает рисовать все, 0 и положительное число означает рисовать соответствующий контур.
цвет: цвет для рисования
толщина: кисть для рисования контура, значение "-1" для рисования сплошного контура
lineType: тип линии для рисования контура
иерархия: соответствует иерархической информации, выводимой функцией cv2.findContours()
maxLevel: управляет глубиной нарисованного уровня контура, если значение равно 0, рисуется только 0-й слой.
offset: параметр смещения, который представляет собой смещение нарисованного контура в определенной позиции.
Далее, давайте нарисуем контур изображения на практике Конкретный код выглядит следующим образом:
import cv2
img = cv2.imread("24.jpg")
cv2.imshow("img", img)
# 转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 转换为二值图
ret, binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
# 获取图像的轮廓参数
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
result = cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("result", result)
cv2.waitKey()
cv2.destroyAllWindows()
После запуска эффект следующий:
Однако это не конечная цель, цель получения контура состоит в том, чтобы разделить изображение, то есть что мне теперь делать, чтобы получить единый подграф из этих трех контуров? Перейти непосредственно к коду.
import cv2
import numpy as np
img = cv2.imread("24.jpg")
cv2.imshow("img", img)
# 转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 转换为二值图
ret, binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
# 获取图像的轮廓参数
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
result = []
for i in range(len(contours)):
temp = np.zeros(img.shape, dtype=np.uint8)
result.append(temp)
result[i] = cv2.drawContours(result[i], contours, i, (0, 0, 255), 5)
cv2.imshow(str(i), result[i])
cv2.waitKey()
cv2.destroyAllWindows()
После запуска мы можем разделить отдельные графики.
Контур изображения в сочетании с побитовым И для получения объекта переднего плана изображения
Помимо выделения чистых контуров изображения для машинного обучения, мы также можем получить объекты переднего плана на изображении. Здесь нам просто нужно заменить изображение и изменить последние несколько строк кода.
Конкретный код выглядит следующим образом:
import cv2
import numpy as np
img = cv2.imread("4.jpg")
cv2.imshow("img", img)
# 转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 转换为二值图
ret, binary = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
# 获取图像的轮廓参数
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(img.shape, dtype=np.uint8)
mask = cv2.drawContours(mask, contours, -1, (255, 255, 255), -1)
cv2.imshow("MASK",mask)
result=cv2.bitwise_and(img,mask)
cv2.imshow("result",result)
cv2.waitKey()
cv2.destroyAllWindows()
После запуска эффект следующий:
Крайний левый - исходное изображение
Посередине сплошной контур персонажа, полученный из исходного изображения.
Крайний справа — это извлеченный человек на переднем плане.