Доступ к значениям пикселей в пределах границы контура с помощью OpenCV в Python
Я использую OpenCV 3.0.0 на Python 2.7.9. Я пытаюсь отслеживать объект в видео, с неподвижным фоном, и оценить некоторые его свойства. Поскольку в изображении может быть несколько движущихся объектов, я хочу иметь возможность различать их и отслеживать их индивидуально на протяжении оставшихся кадров видео.
один из способов, которым я думал, что смогу это сделать, - преобразовать изображение в двоичный файл, получить контуры сгустков (в данном случае отслеживаемый объект) и получить координаты границы объекта. Затем я могу перейти к этим координатам границы в изображении в оттенках серого, получить интенсивности пикселей, окруженные этой границей, и отслеживать этот градиент цвета/интенсивности пикселей в других кадрах. Таким образом, я мог бы держать два объекта отдельно друг от друга, поэтому они не будут рассматриваться как новые объекты в следующем кадре.
У меня есть координаты границы контура, но я не знаю, как получить интенсивности пикселей в пределах этой границы. Мог кто-то пожалуйста, помогите мне с этим?
спасибо!
2 ответов
происходит с нашими комментариями, что вы можете сделать, это создать список numpy
массивы, где каждый элемент-это интенсивности, описывающие внутреннюю часть контура каждого объекта. В частности, для каждого контура создайте двоичную маску, которая заполняет внутреннюю часть контура, найдите (x,y)
координаты заполненного объекта, затем индексируйте в свое изображение и захватите интенсивности.
я не знаю точно, как вы создали свой код, но предположим, у вас есть изображение оттенки серогоimg
. Вам может потребоваться преобразовать изображение в оттенки серого, потому что cv2.findContours
работает на изображениях в оттенках серого. С этим звоните cv2.findContours
обычно:
import cv2
import numpy as np
#... Put your other code here....
#....
# Call if necessary
#img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Call cv2.findContours
contours,_ = cv2.findContours(img, cv2.RETR_LIST, cv2.cv.CV_CHAIN_APPROX_NONE)
contours
теперь список 3D numpy
массивы, где каждый имеет размер N x 1 x 2
здесь N
- общее количество точек контура для каждого объекта.
таким образом, вы можете создать наш список вот так:
# Initialize empty list
lst_intensities = []
# For each list of contour points...
for i in range(len(contours)):
# Create a mask image that contains the contour filled in
cimg = np.zeros_like(img)
cv2.drawContours(cimg, contours, i, color=255, thickness=-1)
# Access the image pixels and create a 1D numpy array then add to list
pts = np.where(cimg == 255)
lst_intensities.append(img[pts[0], pts[1]])
для каждого контура, мы создаем пустое изображение, а затем нарисовать заполненной контур в этом пустом изображении. Вы можете заполнить область, которую занимает контур, указав thickness
параметр равен -1. Я установил внутреннюю часть контура на 255. После, мы используем numpy.where
найти все строки и столбцов в массиве, которые соответствуют определенному условию. В нашем случае, мы хотим найти значения, которые равны 255. После этого мы используем эти точки для индексации в нашем изображении, чтобы захватить интенсивности пикселей, которые являются внутренними для контур.
lst_intensities
содержит этот список 1D numpy
массивы, где каждый элемент дает вам интенсивности, которые принадлежат внутренней части контура каждого объекта. Чтобы получить доступ к каждому массиву, просто сделайте lst_intensities[i]
здесь i
- это контур, к которому вы хотите получить доступ.
ответ от @rayryeng отлично!
одна маленькая вещь из моей реализации:
The np.where()
возвращает кортеж, содержащий массив индексов строк и массив индексов столбцов. Итак,pts[0]
включает в себя список row indices
, которые соответствуют высоте изображения, pts[1]
включает в себя список column indices
, которые соответствуют ширине изображения. The img.shape
возвращает (rows, cols, channels)
. Поэтому я думаю, что это должно быть img[pts[0], pts[1]]
фрагмент ndarray
позади img.