Example #1
0
//===========================================================================
///	PerformSupervoxelSLIC
///
///	Performs k mean segmentation. It is fast because it searches locally, not
/// over the entire image.
//===========================================================================
void SLIC::PerformSupervoxelSLIC(
    vector<double>&				kseedsl,
    vector<double>&				kseedsa,
    vector<double>&				kseedsb,
    vector<double>&				kseedsx,
    vector<double>&				kseedsy,
    vector<double>&				kseedsz,
    int**&					klabels,
    const int&				STEP,
    const double&				compactness)
{
    int sz = m_width*m_height;
    const int numk = kseedsl.size();
    //int numitr(0);

    //----------------
    int offset = STEP;
    //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
    //----------------

    vector<double> clustersize(numk, 0);
    vector<double> inv(numk, 0);//to store 1/clustersize[k] values

    vector<double> sigmal(numk, 0);
    vector<double> sigmaa(numk, 0);
    vector<double> sigmab(numk, 0);
    vector<double> sigmax(numk, 0);
    vector<double> sigmay(numk, 0);
    vector<double> sigmaz(numk, 0);

    vector< double > initdouble(sz, DBL_MAX);
    vector< vector<double> > distvec(m_depth, initdouble);
    //vector<double> distvec(sz, DBL_MAX);

    double invwt = 1.0/((STEP/compactness)*(STEP/compactness));//compactness = 20.0 is usually good.

    int x1, y1, x2, y2, z1, z2;
    double l, a, b;
    double dist;
    double distxyz;
    for( int itr = 0; itr < 5; itr++ )
    {
        distvec.assign(m_depth, initdouble);
        for( int n = 0; n < numk; n++ )
        {
            y1 = max(0.0,			kseedsy[n]-offset);
            y2 = min((double)m_height,	kseedsy[n]+offset);
            x1 = max(0.0,			kseedsx[n]-offset);
            x2 = min((double)m_width,	kseedsx[n]+offset);
            z1 = max(0.0,			kseedsz[n]-offset);
            z2 = min((double)m_depth,	kseedsz[n]+offset);


            for( int z = z1; z < z2; z++ )
            {
                for( int y = y1; y < y2; y++ )
                {
                    for( int x = x1; x < x2; x++ )
                    {
                        int i = y*m_width + x;

                        l = m_lvecvec[z][i];
                        a = m_avecvec[z][i];
                        b = m_bvecvec[z][i];

                        dist =			(l - kseedsl[n])*(l - kseedsl[n]) +
                                        (a - kseedsa[n])*(a - kseedsa[n]) +
                                        (b - kseedsb[n])*(b - kseedsb[n]);

                        distxyz =		(x - kseedsx[n])*(x - kseedsx[n]) +
                                        (y - kseedsy[n])*(y - kseedsy[n]) +
                                        (z - kseedsz[n])*(z - kseedsz[n]);
                        //------------------------------------------------------------------------
                        dist += distxyz*invwt;
                        //------------------------------------------------------------------------
                        if( dist < distvec[z][i] )
                        {
                            distvec[z][i] = dist;
                            klabels[z][i]  = n;
                        }
                    }
                }
            }
        }
        //-----------------------------------------------------------------
        // Recalculate the centroid and store in the seed values
        //-----------------------------------------------------------------
        //instead of reassigning memory on each iteration, just reset.

        sigmal.assign(numk, 0);
        sigmaa.assign(numk, 0);
        sigmab.assign(numk, 0);
        sigmax.assign(numk, 0);
        sigmay.assign(numk, 0);
        sigmaz.assign(numk, 0);
        clustersize.assign(numk, 0);

        for( int d = 0; d < m_depth; d++  )
        {
            int ind(0);
            for( int r = 0; r < m_height; r++ )
            {
                for( int c = 0; c < m_width; c++ )
                {
                    sigmal[klabels[d][ind]] += m_lvecvec[d][ind];
                    sigmaa[klabels[d][ind]] += m_avecvec[d][ind];
                    sigmab[klabels[d][ind]] += m_bvecvec[d][ind];
                    sigmax[klabels[d][ind]] += c;
                    sigmay[klabels[d][ind]] += r;
                    sigmaz[klabels[d][ind]] += d;

                    clustersize[klabels[d][ind]] += 1.0;
                    ind++;
                }
            }
        }

        {   for( int k = 0; k < numk; k++ )
            {
                if( clustersize[k] <= 0 ) clustersize[k] = 1;
                inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
            }
        }

        {   for( int k = 0; k < numk; k++ )
            {
                kseedsl[k] = sigmal[k]*inv[k];
                kseedsa[k] = sigmaa[k]*inv[k];
                kseedsb[k] = sigmab[k]*inv[k];
                kseedsx[k] = sigmax[k]*inv[k];
                kseedsy[k] = sigmay[k]*inv[k];
                kseedsz[k] = sigmaz[k]*inv[k];
            }
        }
    }
}
//===========================================================================
///	PerformSuperpixelSegmentation_VariableSandM
///
///	Magic SLIC - no parameters
///
///	Performs k mean segmentation. It is fast because it looks locally, not
/// over the entire image.
/// This function picks the maximum value of color distance as compact factor
/// M and maximum pixel distance as grid step size S from each cluster (13 April 2011).
/// So no need to input a constant value of M and S. There are two clear
/// advantages:
///
/// [1] The algorithm now better handles both textured and non-textured regions
/// [2] There is not need to set any parameters!!!
///
/// SLICO (or SLIC Zero) dynamically varies only the compactness factor S,
/// not the step size S.
//===========================================================================
void SLIC::PerformSuperpixelSegmentation_VariableSandM(
	vector<double>&				kseedsl,
	vector<double>&				kseedsa,
	vector<double>&				kseedsb,
	vector<double>&				kseedsx,
	vector<double>&				kseedsy,
	int*						klabels,
	const int&					STEP,
	const int&					NUMITR)
{
	int sz = m_width*m_height;
	const int numk = kseedsl.size();
	//double cumerr(99999.9);
	int numitr(0);

	//----------------
	int offset = STEP;
	if(STEP < 10) offset = STEP*1.5;
	//----------------

	vector<double> sigmal(numk, 0);
	vector<double> sigmaa(numk, 0);
	vector<double> sigmab(numk, 0);
	vector<double> sigmax(numk, 0);
	vector<double> sigmay(numk, 0);
	vector<int> clustersize(numk, 0);
	vector<double> inv(numk, 0);//to store 1/clustersize[k] values
	vector<double> distxy(sz, DBL_MAX);
	vector<double> distlab(sz, DBL_MAX);
	vector<double> distvec(sz, DBL_MAX);
	vector<double> maxlab(numk, 10*10);//THIS IS THE VARIABLE VALUE OF M, just start with 10
	vector<double> maxxy(numk, STEP*STEP);//THIS IS THE VARIABLE VALUE OF M, just start with 10

	double invxywt = 1.0/(STEP*STEP);//NOTE: this is different from how usual SLIC/LKM works

	while( numitr < NUMITR )
	{
		//------
		//cumerr = 0;
		numitr++;
		//------

		distvec.assign(sz, DBL_MAX);
		for( int n = 0; n < numk; n++ )
		{
			int y1 = max(0,			static_cast<int>(kseedsy[n])-offset);
			int y2 = min(m_height,	static_cast<int>(kseedsy[n])+offset);
			int x1 = max(0,			static_cast<int>(kseedsx[n])-offset);
			int x2 = min(m_width,	static_cast<int>(kseedsx[n])+offset);

			for( int y = y1; y < y2; y++ )
			{
				for( int x = x1; x < x2; x++ )
				{
					int i = y*m_width + x;
					_ASSERT( y < m_height && x < m_width && y >= 0 && x >= 0 );

					double l = m_lvec[i];
					double a = m_avec[i];
					double b = m_bvec[i];

					distlab[i] =	(l - kseedsl[n])*(l - kseedsl[n]) +
									(a - kseedsa[n])*(a - kseedsa[n]) +
									(b - kseedsb[n])*(b - kseedsb[n]);

					distxy[i] =		(x - kseedsx[n])*(x - kseedsx[n]) +
									(y - kseedsy[n])*(y - kseedsy[n]);

					//------------------------------------------------------------------------
					double dist = distlab[i]/maxlab[n] + distxy[i]*invxywt;//only varying m, prettier superpixels
					//double dist = distlab[i]/maxlab[n] + distxy[i]/maxxy[n];//varying both m and S
					//------------------------------------------------------------------------
					
					if( dist < distvec[i] )
					{
						distvec[i] = dist;
						klabels[i]  = n;
					}
				}
			}
		}
		//-----------------------------------------------------------------
		// Assign the max color distance for a cluster
		//-----------------------------------------------------------------
		if(0 == numitr)
		{
			maxlab.assign(numk,1);
			maxxy.assign(numk,1);
		}
		{for( int i = 0; i < sz; i++ )
		{
			if(maxlab[klabels[i]] < distlab[i]) maxlab[klabels[i]] = distlab[i];
			if(maxxy[klabels[i]] < distxy[i]) maxxy[klabels[i]] = distxy[i];
		}}
		//-----------------------------------------------------------------
		// Recalculate the centroid and store in the seed values
		//-----------------------------------------------------------------
		sigmal.assign(numk, 0);
		sigmaa.assign(numk, 0);
		sigmab.assign(numk, 0);
		sigmax.assign(numk, 0);
		sigmay.assign(numk, 0);
		clustersize.assign(numk, 0);

		for( int j = 0; j < sz; j++ )
		{
			int temp = klabels[j];
			_ASSERT(klabels[j] >= 0);
			sigmal[klabels[j]] += m_lvec[j];
			sigmaa[klabels[j]] += m_avec[j];
			sigmab[klabels[j]] += m_bvec[j];
			sigmax[klabels[j]] += (j%m_width);
			sigmay[klabels[j]] += (j/m_width);

			clustersize[klabels[j]]++;
		}

		{for( int k = 0; k < numk; k++ )
		{
			//_ASSERT(clustersize[k] > 0);
			if( clustersize[k] <= 0 ) clustersize[k] = 1;
			inv[k] = 1.0/double(clustersize[k]);//computing inverse now to multiply, than divide later
		}}
		
		{for( int k = 0; k < numk; k++ )
		{
			kseedsl[k] = sigmal[k]*inv[k];
			kseedsa[k] = sigmaa[k]*inv[k];
			kseedsb[k] = sigmab[k]*inv[k];
			kseedsx[k] = sigmax[k]*inv[k];
			kseedsy[k] = sigmay[k]*inv[k];
		}}
	}
}
Example #3
0
//===========================================================================
///	PerformSuperpixelSLIC
///
///	Performs k mean segmentation. It is fast because it looks locally, not
/// over the entire image.
//===========================================================================
void SLIC::PerformSuperpixelSLIC(
    vector<double>&				kseedsl,
    vector<double>&				kseedsa,
    vector<double>&				kseedsb,
    vector<double>&				kseedsx,
    vector<double>&				kseedsy,
    int*&					klabels,
    const int&				STEP,
    const vector<double>&                   edgemag,
    const double&				M)
{
    int sz = m_width*m_height;
    const int numk = kseedsl.size();
    //----------------
    int offset = STEP;
    //if(STEP < 8) offset = STEP*1.5;//to prevent a crash due to a very small step size
    //----------------

    vector<double> clustersize(numk, 0);
    vector<double> inv(numk, 0);//to store 1/clustersize[k] values

    vector<double> sigmal(numk, 0);
    vector<double> sigmaa(numk, 0);
    vector<double> sigmab(numk, 0);
    vector<double> sigmax(numk, 0);
    vector<double> sigmay(numk, 0);
    vector<double> distvec(sz, DBL_MAX);

    double invwt = 1.0/((STEP/M)*(STEP/M));

    int x1, y1, x2, y2;
    double l, a, b;
    double dist;
    double distxy;
    for( int itr = 0; itr < 10; itr++ )
    {
        distvec.assign(sz, DBL_MAX);
        for( int n = 0; n < numk; n++ )
        {
            y1 = max(0.0,			kseedsy[n]-offset);
            y2 = min((double)m_height,	kseedsy[n]+offset);
            x1 = max(0.0,			kseedsx[n]-offset);
            x2 = min((double)m_width,	kseedsx[n]+offset);


            for( int y = y1; y < y2; y++ )
            {
                for( int x = x1; x < x2; x++ )
                {
                    int i = y*m_width + x;

                    l = m_lvec[i];
                    a = m_avec[i];
                    b = m_bvec[i];

                    dist =			(l - kseedsl[n])*(l - kseedsl[n]) +
                                    (a - kseedsa[n])*(a - kseedsa[n]) +
                                    (b - kseedsb[n])*(b - kseedsb[n]);

                    distxy =		(x - kseedsx[n])*(x - kseedsx[n]) +
                                    (y - kseedsy[n])*(y - kseedsy[n]);

                    //------------------------------------------------------------------------
                    dist += distxy*invwt;//dist = sqrt(dist) + sqrt(distxy*invwt);//this is more exact
                    //------------------------------------------------------------------------
                    if( dist < distvec[i] )
                    {
                        distvec[i] = dist;
                        klabels[i]  = n;
                    }
                }
            }
        }
        //-----------------------------------------------------------------
        // Recalculate the centroid and store in the seed values
        //-----------------------------------------------------------------
        //instead of reassigning memory on each iteration, just reset.

        sigmal.assign(numk, 0);
        sigmaa.assign(numk, 0);
        sigmab.assign(numk, 0);
        sigmax.assign(numk, 0);
        sigmay.assign(numk, 0);
        clustersize.assign(numk, 0);
        //------------------------------------
        //edgesum.assign(numk, 0);
        //------------------------------------

        {   int ind(0);
            for( int r = 0; r < m_height; r++ )
            {
                for( int c = 0; c < m_width; c++ )
                {
                    sigmal[klabels[ind]] += m_lvec[ind];
                    sigmaa[klabels[ind]] += m_avec[ind];
                    sigmab[klabels[ind]] += m_bvec[ind];
                    sigmax[klabels[ind]] += c;
                    sigmay[klabels[ind]] += r;
                    //------------------------------------
                    //edgesum[klabels[ind]] += edgemag[ind];
                    //------------------------------------
                    clustersize[klabels[ind]] += 1.0;
                    ind++;
                }
            }
        }

        {   for( int k = 0; k < numk; k++ )
            {
                if( clustersize[k] <= 0 ) clustersize[k] = 1;
                inv[k] = 1.0/clustersize[k];//computing inverse now to multiply, than divide later
            }
        }

        {   for( int k = 0; k < numk; k++ )
            {
                kseedsl[k] = sigmal[k]*inv[k];
                kseedsa[k] = sigmaa[k]*inv[k];
                kseedsb[k] = sigmab[k]*inv[k];
                kseedsx[k] = sigmax[k]*inv[k];
                kseedsy[k] = sigmay[k]*inv[k];
                //------------------------------------
                //edgesum[k] *= inv[k];
                //------------------------------------
            }
        }
    }
}
Example #4
0
cv::Mat performSuperpixelSegmentation_VariableSandM(std::vector<std::vector<double> > &kseeds, std::vector<double> &kseedsx, std::vector<double> &kseedsy, const std::vector<cv::Mat> &vec, const cv::Size &size, const int &STEP, const int &NUMITR = 10) {
    
    int sz = size.width*size.height;
	const int numk = (int) kseedsx.size();
	int numitr = 0;
    
	int offset = (STEP < 10) ? STEP*1.5 : STEP;
    
    cv::Mat klabels = cv::Mat(size, cv::DataType<int>::type);
    klabels = -1;
    
    std::vector<std::vector<double> > sigmac(0);
    for (int c = 0; c < vec.size(); c++) {
        sigmac.push_back(std::vector<double>(numk, 0));
    }
    std::vector<double> sigmax(numk, 0);
    std::vector<double> sigmay(numk, 0);
    std::vector<int> clustersize(numk, 0);
    std::vector<double> inv(numk, 0);//to store 1/clustersize[k] values
    std::vector<double> distxy(sz, DBL_MAX);
    std::vector<double> distc(sz, DBL_MAX);
    std::vector<double> distvec(sz, DBL_MAX);
    std::vector<double> maxc(numk, 10*10);//THIS IS THE VARIABLE VALUE OF M, just start with 10
    std::vector<double> maxxy(numk, STEP*STEP);//THIS IS THE VARIABLE VALUE OF M, just start with 10
    
	double invxywt = 1.0/(STEP*STEP);//NOTE: this is different from how usual SLIC/LKM works
    
	while( numitr < NUMITR )
	{
		//------
		//cumerr = 0;
		numitr++;
		//------
        
		distvec.assign(sz, DBL_MAX);
		for( int n = 0; n < numk; n++ )
		{
			int y1 = std::max(double(0), kseedsy[n]-offset);
			int y2 = std::min(double(size.height),	kseedsy[n]+offset);
			int x1 = std::max(double(0), kseedsx[n]-offset);
			int x2 = std::min(double(size.width),	kseedsx[n]+offset);
            
			for( int y = y1; y < y2; y++ )
			{
				for( int x = x1; x < x2; x++ )
				{
					int i = y*size.width + x;
					if( !(y < size.height && x < size.width && y >= 0 && x >= 0) ) {
                        throw cv::Exception();
                    }
                    
					distc[i] =	0;
                    for (int c = 0; c < vec.size(); c++) {
                        distc[i] += (vec[c].ptr<double>()[i] - kseeds[c][n]) * (vec[c].ptr<double>()[i] - kseeds[c][n]);
                    }
                    
					distxy[i] =		(x - kseedsx[n])*(x - kseedsx[n]) + (y - kseedsy[n])*(y - kseedsy[n]);
                    
					double dist = distc[i]/maxc[n] + distxy[i]*invxywt;//only varying m, prettier superpixels
					
					if( dist < distvec[i] )
					{
						distvec[i] = dist;
						klabels.ptr<int>()[i]  = n;
					}
				}
			}
		}
		//-----------------------------------------------------------------
		// Assign the max color distance for a cluster
		//-----------------------------------------------------------------
		if(0 == numitr)
		{
			maxc.assign(numk,1);
			maxxy.assign(numk,1);
		}
		{for( int i = 0; i < sz; i++ )
		{
			if(maxc[klabels.ptr<int>()[i]] < distc[i]) maxc[klabels.ptr<int>()[i]] = distc[i];
			if(maxxy[klabels.ptr<int>()[i]] < distxy[i]) maxxy[klabels.ptr<int>()[i]] = distxy[i];
		}}
		//-----------------------------------------------------------------
		// Recalculate the centroid and store in the seed values
		//-----------------------------------------------------------------
        
        for (int c = 0; c < sigmac.size(); c++) {
            sigmac[c].assign(numk, 0);
        }
		sigmax.assign(numk, 0);
		sigmay.assign(numk, 0);
		clustersize.assign(numk, 0);
        
		for( int j = 0; j < sz; j++ )
		{
			if(!(klabels.ptr<int>()[j] >= 0))
                throw cv::Exception();
            
            for (int c = 0; c < sigmac.size(); c++) {
                sigmac[c][klabels.ptr<int>()[j]] += vec[c].ptr<double>()[j];
            }
			sigmax[klabels.ptr<int>()[j]] += (j%size.width);
			sigmay[klabels.ptr<int>()[j]] += (j/size.width);
            
			clustersize[klabels.ptr<int>()[j]]++;
		}
        
		{for( int k = 0; k < numk; k++ )
		{
			if( clustersize[k] <= 0 ) clustersize[k] = 1;
			inv[k] = 1.0/double(clustersize[k]);//computing inverse now to multiply, than divide later
		}}
		
		{for( int k = 0; k < numk; k++ )
		{
            for (int c = 0; c < kseeds.size(); c++) {
                kseeds[c][k] = sigmac[c][k] * inv[k];
            }
			kseedsx[k] = sigmax[k]*inv[k];
			kseedsy[k] = sigmay[k]*inv[k];
		}}
	}
    
    return klabels;
}