У меня есть Kinect и драйверы для Windows и MacOSX. Есть ли какие-либо примеры распознавания жестов, передаваемые из Kinect с использованием OpenCV API? Я пытаюсь добиться аналогичного прототипа DaVinci для Xbox Kinect, но в Windows и MacOSX.
Где я могу узнать/найти примеры распознавания жестов, передаваемые из Kinect, с использованием OpenCV?
Ответы (3)
Я думаю, что это не будет так просто, главным образом потому, что данные изображения глубины от kinect не так чувствительны. Таким образом, после расстояния от 1 м до 1,5 м все пальцы будут объединены, и, следовательно, вы не сможете получить четкие контуры для обнаружения пальцев.
Демо по вашей ссылке, похоже, не использует настоящее распознавание жестов. Он просто различает два разных положения рук (открыто/закрыто), что намного проще, и отслеживает положение рук. Учитывая то, как он держит руки в демоверсии (перед телом, лицом к кинекту, когда они открыты), вот, вероятно, что он делает. Поскольку вы не указали, какой язык вы используете, я буду использовать имена функций C в openCV, но они должны быть похожи на других языках. Я также предполагаю, что вы можете получить карту глубины от kinect (возможно, через функцию обратного вызова, если вы используете libfreenect).
Порог по глубине выбирать только точки достаточно близкие (руки). Вы можете добиться этого либо самостоятельно, либо напрямую с помощью openCV для получения двоичного изображения (cvThreshold() с CV_THRESH_BINARY). Отобразите изображение, полученное после пороговой обработки, и отрегулируйте пороговое значение в соответствии с вашей конфигурацией (старайтесь не находиться слишком близко к kinect, так как в этой области больше помех).
Получите контур рук с помощью cvFindContour()
Это основа. Теперь, когда у вас есть контуры рук, в зависимости от того, что вы хотите сделать, вы можете двигаться в разных направлениях. Если вы просто хотите определить между открытой и закрытой рукой, вы, вероятно, можете сделать:
Получите выпуклую оболочку рук, используя cvConvexHull2()
Получите дефекты выпуклости, используя cvConvexityDefect() на контурах и выпуклой оболочке, которую вы получили ранее.
Проанализируйте дефекты выпуклости: если есть большие дефекты, рука открыта (потому что форма вогнута между пальцами), если нет, рука закрыта.
Но вы также можете сделать обнаружение пальцев! Это то, что я сделал на прошлой неделе, это не требует больших усилий и, вероятно, улучшит вашу демонстрацию! Дешевый, но довольно надежный способ сделать это:
Аппроксимируйте контуры рук многоугольником. Используйте cvApproxPoly() на контуре. Вам нужно будет настроить параметр точности, чтобы полигон был как можно более простым, но не смешивал пальцы вместе (около 15 должно быть неплохо, но нарисуйте его на своем изображении с помощью cvDrawContours(), чтобы проверить, что вы получаете) .
Проанализируйте контур, чтобы найти острые выпуклые углы. Вам придется сделать это вручную. Это самая сложная часть, потому что:
- The data structures used in openCV might be a bit confusing at first. If you struggle too much with the CvSeq structure, cvCvtSeqToArray() might help.
- Наконец-то вы можете выполнить некоторые (основные) математические действия, чтобы найти выпуклые углы. Помните, что вы можете использовать скалярное произведение, чтобы определить, насколько острым является угол, и векторное произведение, чтобы различить выпуклые и вогнутые углы.
Вот вам и острые выпуклые углы — кончики ваших пальцев!
Это простой алгоритм обнаружения пальцев, но есть много способов улучшить его. Например, вы можете попробовать применить срединный фильтр к карте глубины, чтобы немного «сгладить» все, или попробовать использовать более точную аппроксимацию полигона, но затем отфильтровать контур, чтобы объединить точки, которые должны смыкаться на кончиках пальцев, и т. д. .
Удачи и приятного времяпровождения!
mage dest = новое изображение (this.bitmap.Width, this.bitmap.Height); CvInvoke.cvThreshold(src, dest, 220, 300, Emgu.CV.CvEnum.THRESH.CV_THRESH_BINARY); Bitmap nem1 = новый Bitmap (dest.Bitmap); this.bitmap = nem1; Графика g = Graphics.FromImage(this.bitmap);
using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
for (Contour<Point> contours = dest.FindContours(); contours != null; contours = contours.HNext)
{
g.DrawRectangle(new Pen(new SolidBrush(Color.Green)),contours.BoundingRectangle);
// CvInvoke.cvConvexHull2(contours,, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE, 0);
IntPtr seq = CvInvoke.cvConvexHull2(contours,storage.Ptr, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE, 0);
IntPtr defects = CvInvoke.cvConvexityDefects(contours, seq, storage);
Seq<Point> tr= contours.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
Seq<Emgu.CV.Structure.MCvConvexityDefect> te = contours.GetConvexityDefacts(storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
g.DrawRectangle(new Pen(new SolidBrush(Color.Green)), tr.BoundingRectangle);
//g.DrawRectangle(new Pen(new SolidBrush(Color.Green)), te.BoundingRectangle);
}
Сделал по твоему алгоритму, но не работает Что такое wwr?