Как отследить спицу колеса в двух последующих видеокадрах? - PullRequest
1 голос
/ 27 мая 2019

Рассмотрим два последующих кадра видео, которые выглядят следующим образом: fig1

fig2

Как можно отслеживать движение одной из спиц?

Я спрашиваю об этом, потому что у меня нет опыта работы с видео. Так что любой совет будет полезен! Что я отслеживаю? Из того, что я прочитал, обычно мне нужно сначала обнаружить объект, который я хочу отследить. И для этого я использую алгоритм определения угла, например goodfeaturestotrack. Но как мне убедиться, что я обнаружил правильную спицу и т. Д.?

Некоторая дополнительная информация: частота кадров видео составляет 30 кадров в секунду. Колесо вращается только по часовой стрелке. И когда я кликаю по видео кадр за кадром, становится совершенно очевидно, что спица не перемещается более чем на половину угла между двумя спицами (от кадра к кадру). Также: радиус колеса 5см.

Я уже опробовал ответ Марка. Я записал Tmax и отметку времени кадра в txt-файле, а затем написал следующий код для вычисления соответствующей скорости:

ListOfVelocities = []
for idx in range(1,len(ListOfAngles)):
    if ListOfAngles[idx] < ListOfAngles[idx-1]:
        rotation = (360-ListOfAngles[idx]) + ListOfAngles[idx-1]
    else: 
        rotation = ListOfAngles[idx] - ListOfAngles[idx-1]
    timePassed = VideoTimestamp[idx]-VideoTimestamp[idx-1]
    velocity = 2*np.pi/360 * rotation * RADIUS * timePassed
    ListOfVelocities.append(velocity)

Ответы [ 3 ]

2 голосов
/ 27 мая 2019

Я на самом деле не воспринимаю это как проблему с отслеживанием, потому что колесо ограничено, поэтому оно не может перемещаться по всей раме, оно может только изменять свое угловое положение, поэтому вам действительно нужно знать, где какая-то часть он находится в одном кадре и на сколько он повернулся в следующем кадре. Затем, как вы знаете частоту кадров, то есть время между кадрами, вы можете рассчитать скорость.

Итак, вопрос в том, как определить, какая же спица была измерена в предыдущем кадре. Поскольку область за спицами темная, вам нужно, чтобы светлая спица хорошо контрастировала, чтобы ее было легко найти. Итак, я бы покрасил четыре спицы в черный, а вы просто ищете одну светлую на темном фоне. Я также хотел бы покрасить центр колеса в красный цвет (или другой насыщенный цвет), чтобы вы могли легко найти середину.

Теперь, в начале обработки, найдите центр колеса, ища красный и получите его координаты x, y на изображении. Теперь выберите радиус в пикселях, который вы можете изменить позже, и составьте список координат x, y, скажем, 360 точек (1 на градус) по окружности круга, центрированного вокруг красной точки. Эти точки и все синусы / косинусы не будут меняться на протяжении всей обработки, поэтому делайте это вне основного цикла обработки видео.

Теперь в каждом кадре используйте индексирование, чтобы подобрать яркость в каждой из 360 точек и, по крайней мере, сначала выберите самый яркий в качестве спицы.

Итак, я грубо нарисовал на вашем изображении, чтобы центр был красным, и только одна спица была белой:

enter image description here

Теперь код выглядит примерно так:

#!/usr/bin/env python3

import math
import numpy as np
from PIL import Image

# Open image and make Numpy version of it too
im = Image.open('wheel.png')
imnp = np.array(im)

# Find centre by looking for red pixels
# See https://stackoverflow.com/a/52183666/2836621
x, y = 193, 168

# Set up list of 360 points on a circle centred on red dot outside main processing loop
radius = 60
# List of X values and Y values on circumference
Xs = []
Ys = []
for theta in range(360):
    thetaRad = math.radians(theta)
    dx = int(radius * math.sin(thetaRad))
    dy = int(radius * math.cos(thetaRad))
    Xs.append(x+dx)
    Ys.append(y+dy)

# Your main loop processing frames starts here

# Make greyscale Numpy version of image
grey = np.array(im.convert('L'))

sum  = 0
Bmax = 0
Tmax = 0
for theta in range(360):
    brightness=grey[Ys[theta],Xs[theta]]
    sum += brightness
    if brightness > Bmax:
        Bmax = brightness
        Tmax = theta
    print(f"theta: {theta}: brightness={brightness}")

# Calculate mean
Mgrey = sum/len(Xs)
print(f"Mean brightness on circumf: {Mgrey}")

# Print peak brightness and matching theta
print(f"Peak brightness: {Bmax} at theta: {Tmax}")

И вывод такой:

theta: 0: brightness=38
theta: 5: brightness=38
theta: 10: brightness=38
theta: 15: brightness=38
theta: 20: brightness=38
theta: 25: brightness=38
theta: 30: brightness=38
theta: 35: brightness=45
theta: 40: brightness=38
theta: 45: brightness=33
theta: 50: brightness=30
theta: 55: brightness=28
theta: 60: brightness=28
theta: 65: brightness=31
theta: 70: brightness=70
theta: 75: brightness=111
theta: 80: brightness=130
theta: 85: brightness=136
theta: 90: brightness=139    <--- peak brightness at 90 degrees to vertical as per picture - thankfully!
theta: 95: brightness=122
theta: 100: brightness=82
theta: 105: brightness=56
theta: 110: brightness=54
theta: 115: brightness=49
theta: 120: brightness=43
theta: 125: brightness=38
theta: 130: brightness=38
theta: 135: brightness=38
theta: 140: brightness=38
theta: 145: brightness=38
theta: 150: brightness=38
theta: 155: brightness=38
theta: 160: brightness=38
theta: 165: brightness=38
theta: 170: brightness=38
theta: 175: brightness=38
theta: 180: brightness=31
theta: 185: brightness=33
theta: 190: brightness=38
theta: 195: brightness=48
theta: 200: brightness=57
theta: 205: brightness=38
theta: 210: brightness=38
theta: 215: brightness=38
theta: 220: brightness=38
theta: 225: brightness=38
theta: 230: brightness=38
theta: 235: brightness=38
theta: 240: brightness=38
theta: 245: brightness=38
theta: 250: brightness=52
theta: 255: brightness=47
theta: 260: brightness=36
theta: 265: brightness=35
theta: 270: brightness=32
theta: 275: brightness=32
theta: 280: brightness=29
theta: 285: brightness=38
theta: 290: brightness=38
theta: 295: brightness=38
theta: 300: brightness=38
theta: 305: brightness=38
theta: 310: brightness=38
theta: 315: brightness=38
theta: 320: brightness=39
theta: 325: brightness=40
theta: 330: brightness=42
theta: 335: brightness=42
theta: 340: brightness=40
theta: 345: brightness=36
theta: 350: brightness=35
theta: 355: brightness=38
Mean brightness on circumf: 45.87222222222222
Peak brightness: 142 at theta: 89

Если в следующем кадре пиковая яркость теперь равна 100 градусам по вертикали, вы знаете, что колесо повернулось на 10 градусов за 1 / (frames_per_second).

Вам может понадобиться изменить радиус для достижения наилучших результатов - экспериментируйте! Белый радиус, показанный на изображении, соответствует радиусу 60 пикселей в коде.

Вместо того, чтобы брать пиковую яркость, вы можете найти среднее и стандартное отклонение яркости 360 пикселей по окружности, а затем принять угол в качестве среднего значения углов, где яркость больше некоторого числа стандартные отклонения выше среднего. Это зависит от необходимого разрешения / точности.

Вы также можете собрать все яркости вокруг круга, проиндексированного тэтой, в один массив из 360 элементов, например:

brightnessByTheta = grey[Ys[:],Xs[:]]

и вы получите:

array([ 38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  43,  49,  47,  46,  45,  44,  43,  43,
        40,  38,  36,  34,  33,  33,  33,  32,  31,  31,  29,  30,  28,
        29,  29,  29,  28,  28,  27,  29,  28,  28,  27,  28,  28,  29,
        31,  36,  42,  51,  60,  70,  81,  89,  98, 105, 111, 117, 122,
       126, 128, 130, 131, 132, 133, 135, 136, 138, 139, 141, 142, 139,
       136, 133, 129, 124, 122, 119, 113, 104,  93,  82,  72,  65,  60,
        59,  56,  56,  55,  55,  54,  54,  53,  52,  52,  50,  49,  47,
        46,  45,  44,  43,  42,  40,  39,  38,  38,  37,  38,  38,  37,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  34,  31,  31,  31,  31,
        31,  31,  32,  33,  34,  35,  36,  37,  38,  42,  43,  44,  45,
        48,  49,  50,  51,  55,  57,  60,  64,  65,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  52,  56,  46,  46,  47,  47,  38,  39,  40,  40,
        36,  36,  36,  36,  36,  35,  35,  34,  34,  34,  32,  33,  33,
        33,  33,  32,  32,  31,  30,  29,  29,  28,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,  38,
        38,  38,  38,  38,  38,  38,  40,  40,  39,  38,  39,  39,  39,
        40,  40,  41,  41,  42,  42,  42,  41,  41,  42,  42,  41,  40,
        39,  40,  40,  38,  39,  38,  37,  36,  36,  35,  34,  33,  35,
        38,  38,  38,  38,  38,  38,  38,  38,  38], dtype=uint8)
1 голос
/ 27 мая 2019

Для предоставленных кадров невозможно отследить одну спицу, потому что все спицы имеют одинаковую форму и цвет. Практический способ отследить его - физически разметить спицу. Затем, пока ваша камера имеет движение, вам нужно регистрация изображения , чтобы выровнять кадры. Нетрудно отследить спицу потом.

Редактировать: Физическая метка может быть цветным пятном на спице (для простоты используйте цвет, который уникален на изображении). Затем используйте метод thresholding , чтобы выделить цвет. Вам может потребоваться некоторое улучшение, чтобы убрать шумы.

0 голосов
/ 03 июня 2019

Лук, Масуд объясняет, что ты физически помечаешь колесо.Это может быть небольшая белая наклейка или капля краски.Если вы конвертируете в оттенки серого, то лучшим вариантом будет белый, IMO.Если бы это был я, я бы нашел колесо, используя Hough Circle и порог.Как только у вас будет колесо, создайте маску для удаления фона.Это оставляет только колесо.После того, как у вас есть колесо, найдите самое светлое место (должна быть белая наклейка, капля краски или что-то еще использованное), запишите его местоположение, предпочтительно центр, и для каждого кадра выполните один и тот же процесс и измерьте изменение местоположения и используйте его.чтобы выяснить момент импульса.

Дуг

...