доступ к значениям пикселей в пределах границы контура с использованием opencv в python

<p>я использую opencv 3.0.0 на python 2.7.9. я пытаюсь отследить объект в видео с неподвижным фоном и оценить некоторые его свойства. поскольку на изображении может быть несколько движущихся объектов, я хочу иметь возможность различать их и отслеживать их по отдельности в оставшихся кадрах видео.</p><p>один способ, которым я думал, что мог сделать это, это преобразовать изображение в двоичное, получить контуры капель (в данном случае отслеживаемый объект) и получить координаты границы объекта. затем я могу перейти к этим координатам границы в изображении в градациях серого, получить интенсивности пикселей, окруженные этой границей, и отследить этот цветовой градиент/интенсивности пикселей в других кадрах. таким образом, я мог бы держать два объекта отдельно друг от друга, чтобы они не рассматривались как новые объекты в следующем кадре.</p><p>у меня есть координаты границы контура, но я не знаю, как получить интенсивность пикселей в пределах этой границы. может ли кто-нибудь помочь мне с этим?</p><p>спасибо!</p>

<p>следуя нашим комментариям, вы можете создать список массивов <code>numpy</code>, где каждый элемент - это интенсивности, которые описывают внутреннюю часть контура каждого объекта. в частности, для каждого контура создайте двоичную маску, которая заполняет внутреннюю часть контура, найдите координаты <code>(x,y)</code> заполненного объекта, затем внесите в указатель свое изображение и захватите интенсивности.</p><p>я не знаю точно, как вы настроили свой код, но давайте предположим, что у вас есть изображение в градациях серого, называемое <code>img</code>. возможно, вам потребуется преобразовать изображение в оттенки серого, поскольку <code>cv2.findcontours</code> работает с изображениями в оттенках серого. при этом, обычно вызывайте <code>cv2.findcontours</code>:</p><pre><code>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) </code></pre><p><code>contours</code> теперь представляет собой список трехмерных массивов <code>numpy</code>, каждый из которых имеет размер <code>n x 1 x 2</code>, где <code>n</code> - общее количество точек контура для каждого объекта.</p><p>таким образом, вы можете создать наш список следующим образом:</p><pre><code># 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]]) </code></pre><p>для каждого контура мы создаем пустое изображение, а затем рисуем контур <strong>заливки</strong> на этом пустом изображении. вы можете заполнить область, которую занимает контур, указав для параметра <code>thickness</code> значение -1. я установил внутреннюю часть контура на 255. после этого мы используем <a href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html"><code>numpy.where</code></a> , чтобы найти все строки и столбцы в массиве, которые соответствуют определенному условию. в нашем случае мы хотим найти значения, равные 255. после этого мы используем эти точки для индексации нашего изображения, чтобы получить интенсивность пикселей, внутреннюю по отношению к контуру.</p><p><code>lst\_intensities</code> содержит этот список массивов 1d <code>numpy</code>, где каждый элемент дает вам интенсивности, которые принадлежат внутренней части контура каждого объекта. чтобы получить доступ к каждому массиву, просто выполните <code>lst\_intensities[i]</code>, где <code>i</code> - контур, к которому вы хотите получить доступ.</p>

<p>ответ от @rayryeng отличный!</p><p>одна небольшая вещь из моей реализации: функция <code>np.where()</code> возвращает tuple, который содержит массив индексов строк и массив индексов столбцов. итак, <code>pts[0]</code> включает в себя список <code>row indices</code>, которые соответствуют высоте изображения, <code>pts[1]</code> включает в себя список <code>column indices</code>, которые соответствуют ширине изображения. <code>img.shape</code> возвращает <code>(rows, cols, channels)</code>. поэтому я думаю, что это должен быть <code>img[pts[0], pts[1]]</code>, чтобы нарезать <code>ndarray</code> позади img.</p>