Доступ к значениям пикселей в пределах границы контура с помощью 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.