cvcanny и emgu - PullRequest
       10

cvcanny и emgu

1 голос
/ 17 января 2012

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

1 Ответ

4 голосов
/ 18 января 2012

Ну, здесь есть два пути мысли, но сначала есть несколько вещей, с которыми нужно разобраться. Если вы не используете 3D-изображения, вы не сможете добиться точного размера, и даже в этом случае это зависит от разрешения, вы можете захотеть взглянуть на использование Xbox Kinect для 3D-данных.

Если вы используете одну камеру, вам необходимо знать спецификацию и тип объектива, прежде чем вы сможете рассчитать размер в реальном мире. Это так, что вы можете рассчитать значение пикселя на мм. См. Мой ответ ЗДЕСЬ для подробного объяснения гомографии и расчета FOV.

Если вы знаете это, вы можете нарисовать контур тела и попросить человека встать, чтобы подогнать его, прежде чем рассчитывать размер по ожидаемым значениям.

Это, конечно, применимо, только если вы хотите взять изображение пользователя и сопоставить его с реальным размером, поэтому вы хотите сказать им, что им нужен размер 10,12, 14 SML XL и т. Д.

Но натягивать одежду на тело гораздо легче, добрые. Я ссылаюсь на примеры в папке EMGU Directory \ EMGU.CV.Example \.

Сначала вам нужно определить тело, я бы не советовал использовать для этого обнаружение краев, хотя это можно сделать, вам придется циклически проходить по каждому контуру и находить тот, который соответствует телу, а затем, если вы можете соответствовать ему, нарисовать изображение предмета одежды. Посмотрите на пример «ShapeDetection», так как он использует сопоставление счетчиков для квадратов и треугольников.

Гораздо более быстрым методом был бы метод классификатора Хаара, хотя его нельзя отрегулировать так, чтобы он был настолько надежным, что его было бы гораздо проще реализовать, и он рассматривал вашу область как приемлемое решение. Взгляните на пример «FaceDetection» для кода. Да, этот обнаруживает только лицо, но есть другие классификаторы haar, которые обнаружат тело, они находятся в каталоге EMGU \ opencv \ data \ haarcascades. Вы ищете:

  • haarcascade_mcs_upperbody.xml
  • haarcascade_upperbody.xml
  • haarcascade_lowerbody.xml
  • haarcascade_fullbody.xml

Запустите их с помощью веб-камеры и проверьте, как они работают. В Google есть множество примеров, но я бы предложил соединить воедино пример «CamerCapture» и пример «FaceDetection», чтобы лучше понять. Если вы застряли, спросите здесь или на форуме EMGU, и я помогу вам.

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

Что касается наложения двух изображений, есть два реальных варианта. Первый заключается в том, чтобы вставить изображение в новом окне рисунка с фоном изображения, сделанным прозрачным, как с фоном окна рисунка. Это только потребует от вас регулировки положения элемента управления и содержимого, но может быть более сложным. Это может быть лучше в исполнении, так как отображение изображения не займет много времени. Особенно, если вы используете изображения HD.

Второй более простой вариант проще: он предполагает, что фон одежды черный или белый. Прокрутите каждый пиксель области интереса, в который вы собираетесь поместить предмет одежды, соответствующая ценность одежды не черная или белая, затем замените пиксель на захваченном изображении значением предмета одежды. Если вам нужна дополнительная информация о доступе к данным изображений, см. Мою статью ЗДЕСЬ .

Существует также «PedestrianDetection», в котором используется дескриптор Hog, однако для этого потребуется гораздо больше работы, чем для каскадного метода Хаара, однако его время выполнения обычно хуже. Это может быть альтернативой, если Хаар не отвечает вашим требованиям, но я уверен, что это будет.

Надеюсь, это поможет вам, если вам понадобится дополнительная информация или фрагменты кода, дайте мне знать,

Приветствия,

Крис


КОД:

Этот код написан быстро и не был полностью протестирован, поэтому если есть странная ошибка,Я знаю, и я это исправлю.

Хорошо, так что мы начнем с захвата камеры достаточно прямо, мы создадим новую переменную Capture в зависимости от того, какое устройство мы хотим использовать.Если существует более одного устройства, мы можем определить, когда завершится создание нашего устройства захвата,

_capture = new Capture (0);будет использовать первое устройство
_capture = new Capture (1);будет использовать второе устройство

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

Форма для справки - это просто графическое поле, помещенное в красивую и простую форму.

Камера и ее захват ...

private Capture _capture;

public Form1()
{
    InitializeComponent();

    //We will start our capture here we can always do this from another method
    _capture = new Capture();
    Application.Idle += ProcessFrame;
}

Application.Idle + = ProcessFrame;добавляет вызов метода всякий раз, когда мы получаем кадр, и наша программа ничего не делает, этот метод предпочтительнее, чем использование таймера, поскольку он позволяет более высокую частоту кадров.

Итак, здесь мы до кода обработки такжеобъявляем глобально наш haarcascade, поскольку мы используем это так часто, что мы не хотим производить его каждый кадр.Важным примечанием является то, что мы делаем копию приобретаемого фрейма, но это не существенно, однако гарантирует, что у нас не возникнет никаких проблем, если сборщик мусора выпустит информацию о фрейме, пока мы выполняем большое действие обработки.Мы также выделяем память для нашего фрейма как глобальную переменную, поскольку мы используем его все время, пока не хотим его создавать.

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

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

//Add the cascade file to you project and set to copy always as it needs to 
//be in your output directory
HaarCascade UpperBody = new HaarCascade("haarcascade_mcs_upperbody.xml");
HaarCascade LowerBody = new HaarCascade("haarcascade_lowerbody.xml");

Image<Bgr, Byte> frame = new Image<Bgr, Byte>();
Image<Gray, Byte> Gray_frame = new Image<Gray, Byte>();

private void ProcessFrame(object sender, EventArgs arg)
{
    frame = _capture.QueryFrame().Copy();
    Gray_frame = frame.Convert<Gray, Byte>();

    //Upper Body
    MCvAvgComp[][] UpperBodyDetected = Gray_frame.DetectHaarCascade(
        UpperBody , 
        1.1, 
        10, 
        Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, 
        new Size(20, 20));

    //Lower Body
    MCvAvgComp[][] LowerBodyDetected = Gray_frame.DetectHaarCascade(
        LowerBody , 
        1.1, 
        10, 
        Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, 
        new Size(20, 20));

    //draw the results on the image just for effect for now
    // but alternatively here we could display the clothing item according to the ROI
    foreach (MCvAvgComp Upp_Body in UpperBodyDetected[0])
    {
        //draw the upper bodt detected in the with blue
        frame.Draw(Upp_Body.rect, new Bgr(Color.Blue), 2);
    }
    foreach (MCvAvgComp Low_Body in LowerBodyDetected[0])
    {
        //draw the upper bodt detected in the with red
        frame.Draw(Low_Body.rect, new Bgr(Color.Red), 2);
    }
}

Хорошо, вот код, который вам нужен, чтобы найти тело, теперь нам нужно нарисовать объект поверх нашего изображения, для этого потребуется более детальное приложение, но я дам вам быстрый пример того, как рисоватьполучено изображение с белым фоном поверх рамки.Если вы хотите нарисовать изображение с помощью нового элемента управления, то, боюсь, у меня нет времени, чтобы полностью протестировать необходимый код.Если вы застряли, пожалуйста, спросите, так как здесь больше людей, которые знают c #, чем анализ изображений.

//our image to draw
Image<Bgr, Byte> Jumper_example = new Image<Bgr, Byte>("filename.jpg");

foreach (MCvAvgComp Upp_Body in UpperBodyDetected[0])
{
    for(int i = 0; i < Jumper_example.Height; i++)
    {
        for(int j = 0; j < Jumper_example.Width; j++)
        {
            //This will only execute if the data isn't white
            if(Jumper_example.Data[i,j,0] != 255 && Jumper_example.Data[i,j,1] != 255 && Jumper_example.Data[i,j,2] != 255)
            {
                //work out our co-ordinates to draw to
                x = Upp_Body.rect.X + j;
                y = Upp_Body.rect.Y + i;

                //.Data is usually backwards if I remember but if it doesn't draw
                //correctley swap x an y this is where I may have messed up if so let me

                //copy data
                frame.Data[y,x,0] = Jumper_example.Data[i,j,0];
                frame.Data[y,x,1] = Jumper_example.Data[i,j,1];
                frame.Data[y,x,2] = Jumper_example.Data[i,j,2];
            }
        }
    }
}

Хорошо, надеюсь, это поможет,

Приветствия,
Крис

...