Изключение при използване на cvKMeans2 в EmguCV

Опитвам се да преобразувам този кодов фрагмент в Emgu CV с помощта на C#. Мисля, че конвертирах повечето от нещата в това, което трябваше да бъдат в EmguCV, но cvKMeans2 продължава да ме изстрелва Изключение, което няма смисъл.

Ето моят код:

Image<Bgr, float> src = new Image<Bgr, float>("c:\\blanc.jpg");
         Matrix<Single> samples = new Matrix<Single>(src.Rows * src.Cols, 3);
         for (int y = 0; y < src.Rows; y++)
         {
            for (int x = 0; x < src.Cols; x++)
            {
               for( int z = 0; z < 3; z++)
               {
                  if(z == 0)
                     samples[y + x * src.Rows, z] = Convert.ToSingle(src[y, x].Blue);
                  else if(z == 1)
                     samples[y + x * src.Rows, z] = Convert.ToSingle(src[y, x].Green);
                  else if (z == 2)
                     samples[y + x * src.Rows, z] = Convert.ToSingle(src[y, x].Red);
               }
            }
         }

         MCvTermCriteria term = new MCvTermCriteria(10000, 0.0001); 
         term.type = TERMCRIT.CV_TERMCRIT_ITER | TERMCRIT.CV_TERMCRIT_EPS;

         int clusterCount = 3;
         Matrix<Int32> labels = new Matrix<Int32>(src.Width, 1);
         int attempts = 5;
         Matrix<Single> centers = new Matrix<Single>(clusterCount, samples.Cols);
         CvInvoke.cvKMeans2(samples, clusterCount, labels, term, attempts, IntPtr.Zero, KMeansInitType.PPCenters, centers, IntPtr.Zero );

         Image<Bgr, float> new_image = new Image<Bgr, float>(src.Size);

         for (int y = 0; y < src.Rows; y++)
         {
            for (int x = 0; x < src.Cols; x++)
            { 
               //nTotal++;
               int cluster_idx = labels[y + x * src.Rows, 0];

               float n1 = centers[cluster_idx, 0];
               float n2 = centers[cluster_idx, 1];
               float n3 = centers[cluster_idx, 2];

               MCvScalar sca = new MCvScalar(n1, n2, n3);
               CvInvoke.cvSet2D(new_image, y, x, sca);
            }
         }

         CvInvoke.cvShowImage( "clustered image", new_image );
         CvInvoke.cvWaitKey( 0 );

Продължавам да получавам това изключение:

Допълнителна информация: OpenCV: labels.isContinuous() && labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == данни. редове

Няма смисъл етикетът да е от тип Single, защото трябва да го използвам като индекс в цикъла точно след cvKMeans2. Може ли някой да ми помогне да накарам този код да работи? Ако този код работи, има голям шанс да купим търговски лиценз на Emgu, който да използваме в нашия софтуер.

Благодаря!

РЕДАКТИРАНЕ

Въз основа на отговора по-долу адаптирах кода си и го накарах да работи така:

Image<Bgr, float> src = new Image<Bgr, float>(@"C:\\test.png");
            Matrix<float> samples = new Matrix<float>(src.Rows * src.Cols, 1, 3);
            Matrix<int> finalClusters = new Matrix<int>(src.Rows * src.Cols, 1);

            for (int y = 0; y < src.Rows; y++)
            {
                for (int x = 0; x < src.Cols; x++)
                {
                    samples.Data[y + x * src.Rows, 0] = (float)src[y, x].Blue;
                    samples.Data[y + x * src.Rows, 1] = (float)src[y, x].Green;
                    samples.Data[y + x * src.Rows, 2] = (float)src[y, x].Red;
                }
            }

            MCvTermCriteria term = new MCvTermCriteria(10000, 0.0001);
            term.type = TERMCRIT.CV_TERMCRIT_ITER | TERMCRIT.CV_TERMCRIT_EPS;

            int clusterCount = 3;
            int attempts = 5;
            Matrix<Single> centers = new Matrix<Single>(clusterCount, samples.Cols, 3);
            CvInvoke.cvKMeans2(samples, clusterCount, finalClusters, term, attempts, IntPtr.Zero, KMeansInitType.PPCenters, centers, IntPtr.Zero);

            Image<Bgr, Byte> new_image = new Image<Bgr, Byte>(src.Size);

            for (int y = 0; y < src.Rows; y++)
            {
                for (int x = 0; x < src.Cols; x++)
                {
                    int cluster_idx = finalClusters[y + x * src.Rows, 0];
                    MCvScalar sca1 = CvInvoke.cvGet2D(centers, cluster_idx, 0);
                    Bgr color = new Bgr(sca1.v0, sca1.v1, sca1.v2);

                    PointF p = new PointF(x, y);
                    new_image.Draw(new CircleF(p, 1.0f), color, 1);
                }
            }

            CvInvoke.cvShowImage("clustered image", new_image);
            CvInvoke.cvWaitKey(0);

person Jean-François Côté    schedule 18.02.2013    source източник


Отговори (1)


Разглеждам примера, за който се позовавате и аз напишете някакъв ванилен код, който работи върху входно rgb изображение, изпълняващо kmeans в rgb пространство. Можете да промените някои параметри, за да го адаптирате към вашите нужди.

Вземете например това входно изображение: ВЪВЕДЕТЕ ИЗОБРАЖЕНИЕ

EMGUCV КОД

Bgr[] clusterColors = new Bgr[] {
        new Bgr(0,0,255),
        new Bgr(0, 255, 0),
        new Bgr(255, 100, 100),
        new Bgr(255,0,255),
        new Bgr(133,0,99),
        new Bgr(130,12,49),
        new Bgr(0, 255, 255)};

        Image<Bgr, float> src = new Image<Bgr, float>("fotobp.jpg");            
        Matrix<float> samples = new Matrix<float>(src.Rows * src.Cols, 1, 3);
        Matrix<int> finalClusters = new Matrix<int>(src.Rows * src.Cols, 1);

        for (int y = 0; y < src.Rows; y++)
        {
            for (int x = 0; x < src.Cols; x++)
            {                    
                samples.Data[y + x * src.Rows, 0] = (float)src[y, x].Blue;
                samples.Data[y + x * src.Rows, 1] = (float)src[y, x].Green;
                samples.Data[y + x * src.Rows, 2] = (float)src[y, x].Red;
            }
        }

        MCvTermCriteria term = new MCvTermCriteria(100, 0.5);
        term.type = TERMCRIT.CV_TERMCRIT_ITER | TERMCRIT.CV_TERMCRIT_EPS;

        int clusterCount = 4;            
        int attempts = 5;
        Matrix<Single> centers = new Matrix<Single>(clusterCount, src.Rows * src.Cols);            
        CvInvoke.cvKMeans2(samples, clusterCount, finalClusters, term, attempts, IntPtr.Zero, KMeansInitType.PPCenters, IntPtr.Zero, IntPtr.Zero);

        Image<Bgr, float> new_image = new Image<Bgr, float>(src.Size);

        for (int y = 0; y < src.Rows; y++)
        {
            for (int x = 0; x < src.Cols; x++)
            {
                PointF p = new PointF(x, y);
                new_image.Draw(new CircleF(p, 1.0f), clusterColors[finalClusters[y + x * src.Rows, 0]], 1);
            }
        }

        CvInvoke.cvShowImage("clustered image", new_image);
        CvInvoke.cvWaitKey(0);

РЕЗУЛТАТ (CLUSTER_NUM = 4) въведете описание на изображението тук

person Luca Del Tongo    schedule 19.02.2013
comment
Ще погледна и ще видя дали мога да го адаптирам за моите нужди. Знаете ли защо се нуждае от първоначален цветен масив, за да работи? Предполага се, че Kmeans е алгоритъм без надзор, нали? - person Jean-François Côté; 19.02.2013
comment
Адаптирах кода си, използвайки вашия пример и го накарах да работи! Благодаря ти много! Вижте актуализирания въпрос за пълния отговор. - person Jean-François Côté; 19.02.2013