Изображение не обновляется при записи... происходит что-то странное

У меня есть приложение Kinect WPF, которое берет изображения из Kinect, выполняет обнаружение некоторых функций с помощью EmguCV (оболочка C# opencv) и отображает вывод при использовании изображения WPF.

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

Изображение (называемое видео) записывается как таковое:

video.Source = bitmapsource;

в обработчике события colorframeready.

Это работает нормально, пока я не добавлю некоторый код opencv до того, как будет записан источник изображения. Неважно, какой источник используется, поэтому я не думаю, что это конфликт. Я сузил оскорбительный код EmguCV до этой строки:

RecentKeyPoints = surfCPU.DetectKeyPointsRaw(ImageRecent, null);

который переходит прямо в код opencv. Стоит отметить, что:

  • ImageRecent имеет совершенно другое происхождение, чем источник растрового изображения, обновляющий экран.
  • Чтение video.Source возвращает bitmapsource, так что вроде пишет правильно, просто не обновляя экран.

Дайте мне знать, если вам нужна дополнительная информация...

void nui_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
    // Checks for a recent Depth Image
    if (!TrackingReady) return;

    // Stores image
    using (ColorImageFrame colorImageFrame = e.OpenColorImageFrame())
    {
        if (colorImageFrame != null)
        {
            if (FeatureTracker.ColourImageRecent == null)
                //allocate the first time
                FeatureTracker.ColourImageRecent = new byte[colorImageFrame.PixelDataLength];

            colorImageFrame.CopyPixelDataTo(FeatureTracker.ColourImageRecent);
        }
        else return;
    }

    FeatureTracker.FeatureDetect(nui);

    //video.Source = FeatureTracker.ColourImageRecent.ToBitmapSource();
    video.Source = ((Bitmap)Bitmap.FromFile("test1.png")).ToBitmapSource();

    TrackingReady = false;
}

public Bitmap FeatureDetect(KinectSensor nui)
{
    byte[] ColourClone = new byte[ColourImageRecent.Length];
    Array.Copy(ColourImageRecent, ColourClone, ColourImageRecent.Length);
    Bitmap test = (Bitmap)Bitmap.FromFile("test1.png");

    test.RotateFlip(RotateFlipType.RotateNoneFlipY);

    Image<Gray, Byte> ImageRecent = new Image<Gray, byte>(test);
    SURFDetector surfCPU = new SURFDetector(2000, false);
    VectorOfKeyPoint RecentKeyPoints;
    Matrix<int> indices;
    Matrix<float> dist;
    Matrix<byte> mask;
    bool MatchFailed = false;

    // extract SURF features from the object image
    RecentKeyPoints = surfCPU.DetectKeyPointsRaw(ImageRecent, null);
    //Matrix<float> RecentDescriptors = surfCPU.ComputeDescriptorsRaw(ImageRecent, null, RecentKeyPoints);
    //MKeyPoint[] RecentPoints = RecentKeyPoints.ToArray();

    // don't feature detect on first attempt, just store image details for next attempt
    #region
    /*
    if (KeyPointsOld == null)
    {
        KeyPointsOld = RecentKeyPoints;
        PointsOld = RecentPoints;
        DescriptorsOld = RecentDescriptors;
        return ImageRecent.ToBitmap();
    }
    */
    #endregion

    // Attempt to match points to their nearest neighbour
    #region
    /*
    BruteForceMatcher SURFmatcher = new BruteForceMatcher(BruteForceMatcher.DistanceType.L2F32);
    SURFmatcher.Add(RecentDescriptors);
    int k = 5;
    indices = new Matrix<int>(DescriptorsOld.Rows, k);
    dist = new Matrix<float>(DescriptorsOld.Rows, k);
    */

    // Match features, provide the top k matches
    //SURFmatcher.KnnMatch(DescriptorsOld, indices, dist, k, null);

    // Create mask and set to allow all features
    //mask = new Matrix<byte>(dist.Rows, 1);
    //mask.SetValue(255);
    #endregion

    //Features2DTracker.VoteForUniqueness(dist, 0.8, mask);

    // Check number of good maches and for error and end matching if true
    #region
    //int nonZeroCount = CvInvoke.cvCountNonZero(mask);
    //if (nonZeroCount < 5) MatchFailed = true;
    /*
    try
    {
        nonZeroCount = Features2DTracker.VoteForSizeAndOrientation(RecentKeyPoints, KeyPointsOld, indices, mask, 1.5, 20);
    }
    catch (SystemException)
    {
        MatchFailed = true;
    }
    if (nonZeroCount < 5) MatchFailed = true;

    if (MatchFailed)
    {
        return ImageRecent.ToBitmap();
    }
    */
    #endregion

    //DepthMapColourCoordsRecent = CreateDepthMap(nui, DepthImageRecent);
    //PointDist[] FeatureDistances = DistanceToFeature(indices, mask, RecentPoints);
    //Image<Rgb,Byte> rgbimage = ImageRecent.Convert<Rgb, Byte>();
    //rgbimage = DrawPoints(FeatureDistances, rgbimage);

    // Store recent image data for next feature detect.
    //KeyPointsOld = RecentKeyPoints;
    //PointsOld = RecentPoints;
    //DescriptorsOld = RecentDescriptors;

    //CreateDepthMap(nui, iva);
    //rgbimage = CreateDepthImage(DepthMapColourCoordsRecent, rgbimage);

    // Convert image back to a bitmap
    count++;
    //Bitmap bitmap3 = rgbimage.ToBitmap();
    //bitmapstore = bitmap3;

    //bitmap3.Save("test" + count.ToString() + ".png");

    return null;
}

person aforward    schedule 14.03.2012    source источник
comment
можете ли вы сделать diff в ваших коммитах системы управления версиями?   -  person Jake Berger    schedule 14.03.2012
comment
Я мог бы, но я не думаю, что это поможет, было много изменений в результате того, что Microsoft изменила API kinect. Однако эта часть кода не изменилась. Если вы закомментируете вышеприведенный вызов метода surfCPU, он будет работать, но если его не закомментировать, то нет. Даже общий ответ о том, как одна часть кода может повлиять на несвязанную часть в .net, был бы отличным указанием в правильном направлении.   -  person aforward    schedule 14.03.2012
comment
показать ваш код лучше поможет. в любом случае просто начните удалять фрагменты кода и заменять их фиктивными объектами, пока не сузите его.   -  person Jake Berger    schedule 15.03.2012
comment
Добавлен код. Да, я это делал, поэтому большая часть FeatureDetect() закомментирована! Спасибо за совет, буду пробовать дальше.   -  person aforward    schedule 15.03.2012


Ответы (1)


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

В моем случае я обрабатывал поток глубины. Разрешение по умолчанию было 640x480, и Emgu просто не смог обработать изображение достаточно быстро, чтобы не отставать от обработчика frameready. Как только я уменьшил разрешение потока глубины до 320x240, проблема исчезла.

Я также пошел немного дальше и перенес обработку изображений в другой поток, что еще больше ускорило ее (выполните поиск ComponentDispatcher.ThreadIdle). Я все еще не могу сделать 640x480 с разумной частотой кадров, но, по крайней мере, изображение отображается, поэтому я могу видеть, что происходит.

person cpaganucci    schedule 23.08.2012