www.pudn.com > MyImageDB(imageobject).rar > SegmenterMS.cpp
// SegmenterMS.cpp: implementation of the SegmenterMS class.
// from《Robust Analysis of Feature Spaces》
// author:Dorin Comaniciu & Peter Meer
// Source is available from
// http://www.caip.rutgers.edu/~meer/RIUL/uploads.html
// which is an alpha version of the code and works with ppm images only.
// I edited it a little, so that it can now run in VC.
// and a single independent class, and support some other format, etc.
// by dzj, 04.07.02
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SegmenterMS.h"
#include "include\imageobject.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
SegmenterMS::SegmenterMS()
{
}
SegmenterMS::~SegmenterMS()
{
}
*/
//Color Image Segmentation
//This is the implementation of the algorithm described in
//D. Comaniciu, P. Meer,
//Robust Analysis of Feature Spaces: Color Image Segmentation,
//http://www.caip.rutgers.edu/~meer/RIUL/PAPERS/feature.ps.gz
//appeared in Proceedings of CVPR'97, San Juan, Puerto Rico.
// ===========================================================================
// ===== Module: segm.cc
// ===== -------------------------------------------------------------- ======
// ===== Version 01 Date: 04/22/97
// ===== -------------------------------------------------------------- ======
// ===========================================================================
// ===== Written by Dorin Comaniciu
// ===== e-mail: comanici@caip.rutgers.edu
// ===========================================================================
// Permission to use, copy, or modify this software and its documentation
// for educational and research purposes only is hereby granted without
// fee, provided that this copyright notice appear on all copies and
// related documentation. For any other uses of this software, in original
// or modified form, including but not limited to distribution in whole
// or in part, specific prior permission must be obtained from
// the author(s).
//
// THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL RUTGERS UNIVERSITY BE LIABLE FOR ANY SPECIAL,
// INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
// DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY
// THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
// ===========================================================================
//
#include
#include
#include
#include
#include
#include
int option = 2;
static const int rect_gen_contor=3;
// Radius of the searching window
static float gen_RADIUS[3]={2, 3, 4};
static float rect_RADIUS[rect_gen_contor]={8, 6, 4};
static float fix_RADIUS[rect_gen_contor];
static float final_RADIUS;
static float RADIUS2;
static float RADIUS;
static float max_dist;
static int my_threshold[3]={50, 100, 400};
static int my_rap[3]={4, 2, 1};
static int act_threshold;
#define my_abs(a) ((a) > 0 ? (a): (-a))
#define SQRT2 1.4142
#define SQRT3 1.7321
static const float BIG_NUM = (float) 1.0e+20;
// Coefficient matrix for xyz and rgb spaces
static const int XYZ[3][3] = { { 4125, 3576, 1804 },
{ 2125, 7154, 721 },
{ 193, 1192, 9502 } };
static const float RGB[3][3] = { { (float)3.2405, (float)-1.5371, (float)-0.4985 },
{(float)-0.9693, (float)1.8760, (float)0.0416 },
{ (float)0.0556, (float)-0.2040, (float)1.0573 } };
// Constants for LUV transformation
static const float Xn = (float)0.9505;
static const float Yn = (float)1.0;
static const float Zn = (float)1.0888;
static const float Un_prime = (float)0.1978;
static const float Vn_prime = (float)0.4683;
static const float Lt = (float)0.008856;
// # of samples
static const int Max_J = 25;
// Limit of the number of failed trials
static const int Max_trials = 50;
// Defaults values for the parameters.
static const int sam_max = 60;
// Few more trials at the end
static const int MAX_TRIAL=10;
// Used in 3-D histogram computation
static const int FIRST_SIZE=262144; // 2^18
static const int SEC_SIZE=64; // 2^6
// Make coordinate computation faster
// my_neigh is for auto_segm, my_neigh_r works with region
static int my_neigh[8];
static int my_neigh_r[8];
// Results
static int ORIG_COLORS;
static int SEGM_COLORS;
/*
void covariance_w(const int N, int M, const int p, int ** data,
int *w, float T[], float C[p_max][p_max]);
void mean_s(const int N, const int p, int J[], int **data, float T[]);
void my_convert(int, float *, int *);
void reverse_map(Octet *, Octet *, int *, Octet *, float T[][p_max]);
*/
// Class constructor
SegmenterMS::SegmenterMS( )
{
_p = 0;
_p_ptr = 0;
_rrows = 0;
_rcolms = 0;
_data_all = nil;
_data = nil;
_NJ = Max_J;
result_contour = NULL;//by dzj;
}
// Class destructor
SegmenterMS::~SegmenterMS( )
{
if ( _data_all ) {
for ( register int i = 0; i < _p; i++ )
if ( _data_all[i] ) delete [] _data_all[i];
delete [] _data_all;
}
if ( _data ) {
for ( register int i = 0; i < _p; i++ )
if ( _data[i] ) delete [] _data[i];
delete [] _data;
}
if (result_contour!=NULL)
{
delete [] result_contour; result_contour = NULL;
}
}
// LUV (final_T[]) to RGB (TI[]) conversion
void SegmenterMS::my_convert(int selects, float *final_T, int *TI)
{
// this condition is always true
if ( selects & Lightness && selects & Ustar && selects & Vstar )
{
if(final_T[0]<0.1)
{
TI[0]=0;TI[1]=0;TI[2]=0;
}
else
{
float my_x, my_y, my_z;
if(final_T[0]< 8.0)
my_y = (float) ( Yn * final_T[0] / 903.3 );
else
my_y = (float) ( Yn * pow((final_T[0] + 16.0) / 116.0, 3) );
float u_prime = (float) ( final_T[1] / (13 * final_T[0]) + Un_prime );
float v_prime = (float) ( final_T[2] / (13 * final_T[0]) + Vn_prime );
my_x = 9 * u_prime * my_y / (4 * v_prime);
my_z = (12 - 3 * u_prime - 20 * v_prime) * my_y / (4 * v_prime);
TI[0] =int((RGB[0][0]*my_x + RGB[0][1]*my_y + RGB[0][2]*my_z)*255.0);
TI[1] =int((RGB[1][0]*my_x + RGB[1][1]*my_y + RGB[1][2]*my_z)*255.0);
TI[2] =int((RGB[2][0]*my_x + RGB[2][1]*my_y + RGB[2][2]*my_z)*255.0);
if(TI[0]>255) TI[0]=255;
else if(TI[0]<0) TI[0]=0;
if(TI[1]>255) TI[1]=255;
else if(TI[1]<0) TI[1]=0;
if(TI[2]>255) TI[2]=255;
else if(TI[2]<0) TI[2]=0;
}
}
else
{
TI[0]=(int)final_T[0];
TI[1]=(int)final_T[1];
TI[2]=(int)final_T[2];
}
}
// RGB to LUV conversion
// To gain speed the conversion works on a table of colors (_col_RGB[])
// rather than on the whole image
void SegmenterMS::convert_RGB_LUV( RasterIpChannels* signal, long selects )
{
int x, y, z, my_temp;
float l_star, u_star, v_star;
float u_prime, v_prime;
register int temp_col, temp_index, temp_ind;
register int j,k;
int a00=XYZ[0][0], a01=XYZ[0][1], a02=XYZ[0][2];
int a10=XYZ[1][0], a11=XYZ[1][1], a12=XYZ[1][2];
int a20=XYZ[2][0], a21=XYZ[2][1], a22=XYZ[2][2];
int *A00 = new int[MAXV]; int *A01 = new int[MAXV]; int *A02 = new int[MAXV];
int *A10 = new int[MAXV]; int *A11 = new int[MAXV]; int *A12 = new int[MAXV];
int *A20 = new int[MAXV]; int *A21 = new int[MAXV]; int *A22 = new int[MAXV];
for(j=0; jchdata(0);
Octet* temp_ch1 = signal->chdata(1);
Octet* temp_ch2 = signal->chdata(2);
int pp;
int *temp0, *temp1, *temp2;
pp = _p_ptr;
if ( selects & Lightness ) temp0 = _data_all[pp++];
if ( selects & Ustar ) temp1 = _data_all[pp++];
if ( selects & Vstar ) temp2 = _data_all[pp++];
_p_ptr=pp;
for ( j = 0; j < _n_colors; j++)
{
temp_col=_col_RGB[j];
int R=temp_col>>16; int G=(temp_col>>8) & 255; int B=temp_col & 255;
x = A00[R] + A01[G] + A02[B];
y = A10[R] + A11[G] + A12[B];
z = A20[R] + A21[G] + A22[B];
float tval = (float) ( y / 2550000.0 ); //Yn==1
if ( tval > Lt) l_star = my_pow[(int)(tval*255+0.5)];
else l_star = (float) ( 903.3 * tval );
my_temp = x + 15 * y + 3 * z;
if(my_temp)
{
u_prime = (float) ( (float)(x << 2) / (float)(my_temp) );
v_prime = (float) ( (float)(9 * y) / (float)(my_temp) );
}
else
{
u_prime = (float) 4.0;
v_prime = (float) (9.0/15.0);
}
tval=13*l_star;
u_star = tval* (u_prime - Un_prime); // Un_prime = 0.1978
v_star = tval* (v_prime - Vn_prime); // Vn_prime = 0.4683
_col0[j] = (int)(l_star+0.5);
if(u_star>0) _col1[j] = (int)(u_star+0.5);
else _col1[j] = (int)(u_star-0.5);
if(v_star>0) _col2[j] = (int)(v_star+0.5);
else _col2[j] = (int)(v_star-0.5);
}
for(j=0;j<_ro_col;j++)
{
temp_col=(((((int)temp_ch0[j])<<8)+(int)temp_ch1[j])<<8)+(int)temp_ch2[j];
temp_ind=_col_misc[temp_col>>6];
for(k=temp_ind;kchdata(0);
register Octet* ch1 = signal->chdata(1);
register Octet* ch2 = signal->chdata(2);
//first_tab -> how many
for(k=0;k<_ro_col;k++)
{
temp_ind=(((ch0[k]<<8)+ch1[k])<<2)+(ch2[k]>>6);
first_tab[temp_ind]++;
}
//_col_misc -> memo position
for(k=0;k>6);
sec_ind=ch2[k] & 63;
third_ind=_col_misc[temp_ind];
third_tab[third_ind][fourth_tab[third_ind]]=sec_ind;
fourth_tab[third_ind]++;
}
for(k=0;k=0 && k<_ro_col && local_class[k])
{
if(auto_segm && gen_class[k]!=255) continue;
neigh_contor++;
if(neigh_contor>how_many)
{
no_neigh=0;
break;
}
}
}
if(!no_neigh)
{
if(auto_segm) selected[*my_contor]=i;
*my_contor=*my_contor+1;
}
}
}
for(i=temp_contor;i<*my_contor;i++)
local_class[selected[i]]=1;
}
// Find the feature vectors inside the given window
// Use Improved Absolute Error Inequality Criterion
// when computing Euclidean distance
// See J.S.Pan el al, Fast Clustering Alg. for VQ, Pattern Recognition,
// Vol. 29, No. 3, pp. 511-518, 1996
void SegmenterMS::new_auto_loop(float *final_T, Octet *sel_col)
{
float L,U,V,RAD2,R;
register int TT0=0, TT1=0, TT2=0;
register int local_contor=0;
float final_T0=final_T[0]
, final_T1=final_T[1]
, final_T2=final_T[2];
float RADIUS_S2=(float) ( SQRT2*RADIUS )
, RADIUS_S3=(float) ( SQRT3*RADIUS );
for ( register int p=0, k; p<_n_col_remain; p++ )
{
k = _col_remain[p];
L = _col0[k]-final_T0; if((L=my_abs(L))>=RADIUS) continue;
U = _col1[k]-final_T1; if((R=my_abs(U)+L)>=RADIUS_S2) continue;
V = _col2[k]-final_T2; if(R+my_abs(V)>=RADIUS_S3) continue;
RAD2 = L*L+U*U+V*V;
if ( RAD2=RADIUS) continue;
U=_data[1][k]-final_T1; if((R=my_abs(U)+L)>=RADIUS_S2) continue;
V=_data[2][k]-final_T2; if(R+my_abs(V)>=RADIUS_S3) continue;
RAD2=L*L+U*U+V*V;
if(RAD2=RADIUS) continue;
U=_data1[k]-ptr[1]; if(my_abs(U)>=RADIUS) continue;
V=_data2[k]-ptr[2]; if(my_abs(V)>=RADIUS) continue;
RAD2=L*L+U*U+V*V;
if(RAD2=0 && u<_ro_col)
if((pres_class=gen_class[u])!=n_rects)
{
ptr=T[pres_class];
L=_data0[k]-ptr[0]; if(my_abs(L)>=RADIUS) continue;
U=_data1[k]-ptr[1]; if(my_abs(U)>=RADIUS) continue;
V=_data2[k]-ptr[2]; if(my_abs(V)>=RADIUS) continue;
RAD2=L*L+U*U+V*V;
if(RAD2my_class<*n_rects &&
!valid_class[current_region->my_class]))
for(k=0;kmy_contor;k++)
gen_class[current_region->my_region[k]]=*n_rects;
if(current_region->next_region_str)
current_region=current_region->next_region_str;
else break;
}
Octet my_map[Max_rects];
reverse_map(inv_map,my_map,n_rects,valid_class,T);
for(k=0;k<_ro_col;k++)
my_class[k]=my_map[gen_class[k]];
delete [] valid_class;
memcpy(gen_class,my_class,_ro_col);
}
// Eliminate regions with less than "my_lim" pixels
void SegmenterMS::eliminate_region(int *n_rects,int my_lim, float T[][p_max], REGION* first_region)
{
register int j,u,k,p, pres_class, min_ind;
register REGION *current_region=first_region;
register int* region;
float *ptr;
float L,U,V,RAD2,minRAD2;
int increm;
while(1)
{
if(current_region->my_contormy_region;
for(k=0;kmy_contor;k++)
gen_class[region[k]]=*n_rects;
while(1)
{
Boolean my_flag=0;
RADIUS+=increm; RADIUS2=RADIUS*RADIUS; increm+=4;
for(k=0;kmy_contor;k++)
if(gen_class[p=region[k]]==(*n_rects))
{
minRAD2=RADIUS2;
for(j=1;j<8;j+=2)
{
u=p+my_neigh[j];
if(u>=0 && u<_ro_col)
if((pres_class=gen_class[u])!=(*n_rects))
{
ptr=T[pres_class];
L=_data0[p]-ptr[0]; U=_data1[p]-ptr[1];
V=_data2[p]-ptr[2]; RAD2=L*L+U*U+V*V;
if(RAD2next_region_str)
current_region=current_region->next_region_str;
else break;
}
}
// Destroy the region list
void SegmenterMS::destroy_region_list(REGION *first_region)
{
register REGION *current_region=first_region;
while(1)
{
delete [] current_region->my_region;
first_region=current_region;
if(current_region->next_region_str)
{
current_region=current_region->next_region_str;
delete first_region;
}
else
{
delete first_region;
break;
}
}
}
// Connected component main routine
void SegmenterMS::find_other_neigh(int k, int *my_ptr_tab, REGION *current_region)
{
register int *ptr_tab=my_ptr_tab;
register int i,u, j=k, sec_signal;
register int contor=0;
register int region_contor=current_region->my_contor;
register int region_class=current_region->my_class;
ptr_tab[contor]=j;
while(1)
{
sec_signal=0;
for(i=1;i<9;i+=2)
{
u=j+my_neigh[i];
if(u>=0 && u<_ro_col)
if(gen_class[u]==region_class && !taken[u])
{
sec_signal=1;
conn_selected[region_contor++]=u;
taken[u]=1;
ptr_tab[++contor]=u;
}
}
if(sec_signal) j=ptr_tab[contor];
else
{
if(contor>1) j=ptr_tab[--contor];
else break;
}
}
current_region->my_contor=region_contor;
}
// Create the region list
REGION *SegmenterMS::create_region_list(int *my_max_region, int change_type)
{
register int k, local_label=0;
register REGION *first_region, *prev_region, *current_region;
taken = new Octet[_ro_col];
memset(taken,0,_ro_col);
conn_selected = new int[_ro_col];
int *ptr_tab=new int[_ro_col];
for(k=0;k<_ro_col;k++)
if(!taken[k])
{
current_region=new REGION;
current_region->my_contor=0;
current_region->my_class=gen_class[k];
current_region->my_label=local_label;
if(k!=0) prev_region->next_region_str=current_region;
if(k==0){ first_region=current_region;}
local_label++;
conn_selected[current_region->my_contor++]=k;
taken[k]=1;
find_other_neigh(k,ptr_tab,current_region);
if(change_type==0)
if(my_max_region[current_region->my_class]my_contor)
my_max_region[current_region->my_class]=current_region->my_contor;
current_region->my_region=new int[current_region->my_contor];
memcpy(current_region->my_region,conn_selected,sizeof(int)*current_region->my_contor);
prev_region=current_region;
}
current_region->next_region_str=0;
delete [] ptr_tab; delete [] taken; delete [] conn_selected;
return first_region;
}
// Find connected components and remove small regions of classes
// with small regions
void SegmenterMS::conn_comp(Octet *my_class, int *n_rects, Octet *inv_map, float T[][p_max],int my_lim, int change_type)
{
REGION *first_region;
int *my_max_region;
if(change_type==0)
{
my_max_region = new int[(*n_rects)+1];
memset(my_max_region,0,sizeof(int)*((*n_rects)+1));
}
first_region=create_region_list(my_max_region, change_type);
if(change_type==0) //elliminate classes with small regions
eliminate_class(my_class,my_max_region,n_rects,my_lim,inv_map,T,first_region);
else if(change_type==1) //elliminate small regions
eliminate_region(n_rects,my_lim,T,first_region);
destroy_region_list(first_region);
if(change_type==0) delete [] my_max_region;
cerr<<":";
}
// Cut a rectangle from the entire input data
// Deletes the previous rectangle, if any
void SegmenterMS::cut_rectangle( sRectangle* rect )
{
if ( _data ) {
for ( register int i = 0; i < _p; i++ )
if ( _data[i] ) delete [] _data[i];
delete [] _data;
}
// Set the dimensions of the currently processed region.
_rrows = rect->height;
_rcolms = rect->width;
_data = new int*[_p];
register int my_x = rect->x;
register int my_y = rect->y;
register int i, j, d;
for ( i = 0; i < _p; i++ )
_data[i] = new int[_rcolms*_rrows];
if(auto_segm)
for ( d = 0; d < _p; d++ )
memcpy(_data[d], _data_all[d],sizeof(int)*_ro_col);
else
{
int idx1 = my_y * _colms + my_x;
int idx2 = 0;
for ( j = my_y, d;
j < my_y + _rrows; j++, idx1 += _colms - _rcolms )
for ( i = my_x; i < my_x + _rcolms; i++, idx1++, idx2++ )
{
for ( d = 0; d < _p; d++ )
_data[d][idx2] = _data_all[d][idx1];
}
}
cerr<<":";
}
// Compute the mean of N points given by J[]
void SegmenterMS::mean_s(const int N, const int p, int J[], int **data, float T[])
{
int TT[p_max];
register int k, i, j;
for ( i = 0; i < p; i++ )
TT[i] = 0;
for ( i = 0; i < N; i++ )
{
k = J[i];
for ( j = 0; j < p; j++ )
TT[j] += data[j][k];
}
for ( i = 0; i < p; i++ )
T[i] = (float)TT[i] / (float)N;
}
// Build a subsample set of 9 points
int SegmenterMS::subsample(float *Xmean )
{
int J[9];
register int my_contor=0, uj, i0;
if(auto_segm)
i0=J[my_contor]=
gen_remain[int(float(n_remain)*float(rand())/float(SHRT_MAX))];
else
i0=J[my_contor]=int(float(_n_points)*float(rand())/float(SHRT_MAX));
my_contor++;
for(register i=0;i<8;i++){
uj=i0 + my_neigh_r[i];
if(uj>=0 && uj<_n_points)
{
if((auto_segm && gen_class[uj]!=255)) break;
else
{
J[my_contor] = uj;
my_contor++;
}
}
}
mean_s(my_contor, _p, J, _data, Xmean);
return 1;
}
// Sampling routine with all needed tests
float SegmenterMS::my_sampling( int rect, float T[Max_rects][p_max])
{
register int k, c;
register float L,U,V;//,Res;by dzj;
register float my_dist=max_dist, my_sqrt_dist=fix_RADIUS[0];
float TJ[Max_J][p_max];
int l = 0; //contor of number of subsample sets
int ll = 0; //contor of trials
float Xmean[p_max];
float Obj_fct[Max_J];
//Max_trials = max number of failed trials
//_NJ = max number of subsample sets
while ( (ll < Max_trials) && (l < _NJ ) )
{
if ( subsample(Xmean) ) // the subsample procedure succeeded
{
ll = 0; c=0;
// Save the mean
for ( k = 0; k < _p; k++ ) TJ[l][k] = Xmean[k];
// Compute the square residuals (Euclid dist.)
if(auto_segm)
{
for ( register int p = 0; p < _n_col_remain; p++ )
{
k=_col_remain[p];
L=_col0[k]-Xmean[0]; if(my_abs(L)>=my_sqrt_dist) continue;
U=_col1[k]-Xmean[1]; if(my_abs(U)>=my_sqrt_dist) continue;
V=_col2[k]-Xmean[2]; if(my_abs(V)>=my_sqrt_dist) continue;
if(L*L+U*U+V*V=my_sqrt_dist) continue;
U=_data[1][k]-Xmean[1];
if(my_abs(U)>=my_sqrt_dist) continue;
V=_data[2][k]-Xmean[2];
if(my_abs(V)>=my_sqrt_dist) continue;
if(L*L+U*U+V*V L)
{
L = Obj_fct[k];
c = k;
}
}
if(Obj_fct[c]>0)
{
for(k=0;k<_p;k++)
T[rect][k]=TJ[c][k];
}else
{
return -BIG_NUM; // Not enough points
}
return ( 0 );
}
// Compute the weighted covariance of N points
void SegmenterMS::covariance_w(const int N, int M, const int p, int **data,
int *w, float T[], float C[p_max][p_max])
{
register int i, j, k, l;
int TT[p_max];
for ( i = 0; i < p; i++ )
TT[i] = 0;
for ( i = 0; i < M; i++ )
for ( j = 0; j < p; j++ )
TT[j] += w[i]*data[j][i];
for ( i = 0; i < p; i++ )
T[i] = (float) TT[i] / (float)N;
for ( i = 0; i < p; i++ )
for ( j = i; j < p; j++ )
C[i][j] = 0.0;
for ( i = 0; i < M; i++ )
{
for ( k = 0; k < p; k++ )
for ( l = k; l < p; l++ )
C[k][l]+=w[i]*(data[k][i]-T[k])*(data[l][i]-T[l]);
}
for ( k = 0; k < p; k++ )
{
for ( l = k; l < p; l++ )
C[k][l] /= (float)(N-1);
for ( l = 0; l < k; l++ )
C[k][l] = C[l][k];
}
}
// initialization
void SegmenterMS::init_neigh(void)
{
my_neigh[0]= -_colms-1; my_neigh[1]= -_colms;
my_neigh[2]= -_colms+1; my_neigh[3]= +1;
my_neigh[4]= +_colms+1; my_neigh[5]= +_colms;
my_neigh[6]= +_colms-1; my_neigh[7]= -1;
my_neigh_r[0]= -_rcolms-1; my_neigh_r[1]= -_rcolms;
my_neigh_r[2]= -_rcolms+1; my_neigh_r[3]= +1;
my_neigh_r[4]= +_rcolms+1; my_neigh_r[5]= +_rcolms;
my_neigh_r[6]= +_rcolms-1; my_neigh_r[7]= -1;
}
// Init matrices parameters
void SegmenterMS::init_matr(void)
{
// General statistic parameters for X.
float Mg[p_max]; //sample mean of X
float C[p_max][p_max]; //sample covariance matrix of X
covariance_w(_ro_col, _n_colors, _p, _col_all, _m_colors, Mg, C);
// Adaptation
float my_th=C[0][0]+C[1][1]+C[2][2];
int active_gen_contor=1;
if(auto_segm)
fix_RADIUS[0]=(float) ( gen_RADIUS[option]*sqrt(my_th/100) );
else
{
active_gen_contor=rect_gen_contor;
for(int i=0;isqrt(_ro_col)/my_rap[option])?
my_threshold[option]:sqrt(_ro_col)/my_rap[option]);
cerr<<":";
}
// Init
void SegmenterMS::initializations(RasterIpChannels* pic, sRectangle rects[], int *n_rects, long selects, int *active_gen_contor)
{
register int i;
XfRaster::Info info;
pic->raster_info(info);
_colms = info.columns; _rows = info.rows; _ro_col = _rows * _colms;
_data_all = new int*[_p];//_p为维数=3;
for ( i = 0; i < _p; i++ )
_data_all[i] = new int[_ro_col];
_data0=_data_all[0]; _data1=_data_all[1]; _data2=_data_all[2];
init_neigh();
my_histogram(pic, selects);
convert_RGB_LUV( pic, selects );
gen_class = new Octet[_ro_col];
memset(gen_class,255,_ro_col);
if(!(*n_rects))
{
auto_segm=1;
*n_rects=Max_rects;
n_remain=_ro_col;
_n_col_remain=_n_colors;
gen_remain = new int[_ro_col];
_col_remain = new int[_n_colors];
_m_col_remain = new int[_n_colors];
for ( i = 0; i< _ro_col ; i++ )
gen_remain[i] = i;
for ( i = 0; i< _n_colors ; i++ )
_col_remain[i] = i;
memcpy(_m_col_remain,_m_colors,sizeof(int)*_n_colors);
for ( i = 0; i < Max_rects ; i++ )
{
rects[i].width=_colms; rects[i].height=_rows;
rects[i].x = 0; rects[i].y = 0;
}
*active_gen_contor=1;
}
else
{
auto_segm=0;
n_remain=0;
*active_gen_contor=rect_gen_contor;
option=2;
}
init_matr();
delete [] _m_colors;
}
// Mean shift segmentation applied on the selected region(s) of an image or
// on the whole image
Boolean SegmenterMS::ms_segment( RasterIpChannels* pic, sRectangle rects[],
int n_rects, long selects ,
unsigned int seed_default, Boolean block)
{
int t = time(0);
if (n_rects > Max_rects) return false;
if ( selects & Lightness || selects & Ustar || selects & Vstar )
_p=3;
else return false;
int contor_trials=0, active_gen_contor;
float T[Max_rects][p_max];
int TI[Max_rects][p_max];
float L,U,V,RAD2,q;
register int i,k;
srand( seed_default ); cerr<<":";
initializations(pic, rects, &n_rects, selects, &active_gen_contor);
// Mean shift algorithm and removal of the detected feature
int rect;
for ( rect=0; rect(_ro_col-_colms) )
{
my_class[k] = 0;
}
else
{
for (j=1; j<8; j+=2)
{
int u=k+my_neigh[j];
if(u>=0 && u<_ro_col && (pres_classchdata(0)[k];
isegment1[k] = /*TI[temp_class][1];*/pic->chdata(1)[k];
isegment2[k] = /*TI[temp_class][2];*/pic->chdata(2)[k];
}
}
}
if(auto_segm)
{
delete [] _m_col_remain;
delete [] _col_remain;
delete [] gen_remain;
}
delete [] gen_class;
delete [] _col_index;
delete [] _col0; delete [] _col1; delete [] _col2;
delete [] _col_all;
XfRaster::Info info;
pic->raster_info(info);
result_ras_ = new RasterIpChannels( info, 3, eDATA_OCTET,
isegment, true );
cerr << endl << "Original Colors: " << _n_colors << endl;
cerr << "Segment. Colors: " << n_rects << endl;
return true;
}
void SegmenterMS::SaveContour2Buf(Octet* signal, int _rows, int _colms)
//保存结果轮廓
{
INT w = _colms;
INT h = _rows;
if (result_contour!=NULL)
{
delete [] result_contour; result_contour = NULL;
}
result_contour = new BOOL[w*h];
for (INT y=0; y0)
{
result_contour[pos] = TRUE;
}else
{
result_contour[pos] = FALSE;
}
}
}
}
Boolean SegmenterMS::my_write_Contour_file( CString outfname, Octet* signal,int _rows, int _colms )
//输出结果轮廓图像;
{
/* by dzj;
ofstream fp( fname, ios::out );
if ( fp.fail() )
return false;
fp << "P5\n" << _colms << ' ' << _rows<< "\n255" << endl;
fp.write(signal,_rows*_colms);
fp.close( );
*/
CImageObject myresult;
INT w = _colms;
INT h = _rows;
BYTE* resultdata = new BYTE[w*h*3];
for (INT y=0; ychdata_[0];
Octet *temp1 = signal->chdata_[1];
Octet *temp2 = signal->chdata_[2];
int width = signal->columns_;
int height = signal->rows_;
BYTE* imagedata = new BYTE[width*height*3];
for (int y=0; yCreateDIBFromBits(width, height, imagedata);
myimage->SaveToFile(outfname);
return true;
}
//add by dzj;
RasterIpChannels* SegmenterMS::read_IMG_file( CString filename )
{
Octet** datain = new Octet*[p_max];
int w, h;
CImageObject* myimage = new CImageObject(filename);
w = myimage->GetWidth();
h = myimage->GetHeight();
BYTE* imagedata = new BYTE[w*h*3];
myimage->LoadDIBToBuf(imagedata);
for ( INT i = 0; i < p_max; i++ )
{
datain[i] = new Octet[w * h];
}
for ( int j = 0; j < h; j++ )
{
int lstart = j*w;
for ( int i = 0; i < w; i++ )
{
int lpos = (lstart + i);
datain[0][lpos] = imagedata[lpos*3+2];
datain[1][lpos] = imagedata[lpos*3+1];
datain[2][lpos] = imagedata[lpos*3];
}
}
delete [] imagedata; imagedata = NULL;
delete myimage; myimage = NULL;
XfRaster::Info info;
info.rows = h;
info.columns = w;
info.origin_x = 0;
info.origin_y = 0;
return (new RasterIpChannels( info, p_max, eDATA_OCTET,
datain, true ) );
}
// Class constructor
// The `data' may be taken away from the caller in order to
// avoid time-consuming copying of the data. However,
// the caller has to give explicit permission for this.
RasterIpChannels::RasterIpChannels(
const XfRaster::Info& info, const int n_channels,
const DataType dtype, Octet* data[], const Boolean do_take
) {
rows_ = info.rows;
columns_ = info.columns;
dtype_ = dtype;
clipf_ = false;
n_channels_ = n_channels;
if (n_channels_ == 0) {
n_channels_ = 1;
}
size_t size = (size_t)(rows_ * columns_);
chdata_ = new Octet*[n_channels_];
for (int channel = 0; channel < n_channels_; channel++) {
if ( do_take == true ) { // take over the data from the caller
chdata_[channel] = (Octet* )data[channel];
data[channel] = nil;
} else {
if ( dtype_ == eDATA_FLOAT ) size *= sizeof(float);
chdata_[channel] = new Octet[size];
if (data != nil && data[channel] != nil) {
memmove( chdata_[channel], data[channel], size );
} else {
memset( chdata_[channel], 0, size );
}
}
}
delete [] data;
}
RasterIpChannels::~RasterIpChannels() {
for (int channel = 0; channel < n_channels_; channel++) {
if (chdata_[channel]) delete [] chdata_[channel];
chdata_[channel] = nil;
}
delete [] chdata_;
}
// RANGE forces `a' to be in the range [b..c] (inclusive)
inline void RANGE( int& a, const int b, const int c )
{
if ( a < b ) {
a = b;
} else if ( a > c ) {
a = c;
}
}
void RasterIpChannels::raster_info(Info& i) {
i.rows = rows_;
i.columns = columns_;
i.origin_x = 0;
i.origin_y = 0;
}
// Move floating point array to Octet array, i.e. to [0..255]
// The result is either scaled to the range [0..255] or
// clipped to this range, depending on the flag `clipf'.
// Note: Handles only 1-Octet per pixel pictures
// (i.e. mono/pseudo color pictures)
Octet** RasterIpChannels::raster_float_to_Octet(
RasterIpChannels& ras
) {
assert( ras.dtype() == eDATA_FLOAT );
float maxv = (float) -1.0e38;
XfRaster::Info info;
ras.raster_info(info);
size_t size = (size_t)(info.rows * info.columns);
Octet** data = ras.chdata();
int channels = ras.n_channels();
Octet** picRes = new Octet*[channels];
int i;
for ( i = 0; i < channels; i++ )
picRes[i] = new Octet[ size ];
if ( ras.clipf() == true ) { // clip the values outside the range [0..255]
int p;
for ( i = 0; i < channels; i++ ) {
register float* ptr1 = (float* )data;
register Octet* ptr2 = picRes[i];
for ( register int off = 0; off < size; off++, ptr1++, ptr2++ ) {
p = int(*ptr1);
RANGE( p, 0, 255 );
*ptr2 = Octet(p);
}
}
} else { // scale the values to the range [0..255]
for ( i = 0; i < channels; i++ ) {
float minv = (float) 1.e38;
float maxv = (float) -1.e38;
register float* ptr1 = (float* ) data[i];
register Octet* ptr2 = picRes[i];
register int off;
for ( off = 0; off < size; off++, ptr1++ ) {
if ( *ptr1 < minv ) minv = *ptr1;
if ( *ptr1 > maxv ) maxv = *ptr1;
}
ptr1 = (float* ) data[i];
float ratio = (float) 255.0 / (maxv - minv);
for ( off = 0; off < size; off++, ptr1++, ptr2++ )
*ptr2 = Octet( (*ptr1 - minv) * ratio );
}
}
return ( picRes );
}