www.pudn.com > snake.rar > SnakeProcess.cpp
// SnakeProcess.cpp: implementation of the SnakeProcess class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "mammocad.h" #include "SnakeProcess.h" #include "ROI.h" #include "imageprocess.h" #include#include #include "Matrix.h" #include
#include #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// extern void gradient(USHORT*f , // image buffer of growth region defined by active contour int rows, int cols); SnakeProcess::SnakeProcess() { } SnakeProcess::~SnakeProcess() { } // Snake.cpp : Defines the class behaviors for the application. // ///////////////////////////////////////////////////////////////////////////// // The one and only CSnakeApp object LONG glHeight,glWidth; bool glFlag; struct DIRECTION { bool direction[8]; DIRECTION() { for(int i=0;i<8;i++) direction[i]=FALSE; } }; struct Ppoint { int x,y; Ppoint(int a=-1,int b=-1) { x=a; y=b; } bool operator==(Ppoint tempPoint) { return (x==tempPoint.x && y == tempPoint.y); } Ppoint& operator=(Ppoint& tempPoint) { x=tempPoint.x; y=tempPoint.y; return *this; } }; /* NOTE: * * You must have "mex" command working in your matlab. In matlab, * type "mex gvfc.c" to compile the code. See usage for details of * calling this function. * * Replace GVF(...) with GVFC in the snakedeform.m. The speed is * significantly faster than the Matlab version. */ #include "stdio.h" #include "stdlib.h" #include "math.h" #include "string.h" #define PG_MAX(a,b) (a>b? a: b) #define PG_MIN(a,b) (amax_a) { max_a=pData_a[k*nCols+l]; } //Para_b if(pData_b[k*nCols+l] max_b) { max_b=pData_b[k*nCols+l]; } //Para_c if(pData_c[k*nCols+l] max_c) { max_c=pData_c[k*nCols+l]; } //Para_d if(pData_d[k*nCols+l] max_d) { max_d=pData_d[k*nCols+l]; } }//End for(l=2;l big) big = temp; if(big == 0.0) nrerror(" Singular matrix in routine ludcmp! "); vv[i] = 1.0 / big; } for(j=1; j<=n; j++) { for(i=1; i = big) { big = dum; imax = i; }//求最大值位置 } if(j != imax) { for(k=1; k<=n; k++) { dum = a[imax][k]; a[imax][k] = a[j][k]; a[j][k] = dum; } *d = -(*d); vv[imax] = vv[j]; } indx[j] = imax; if(a[j][j] == 0.0) a[j][j] = TINY; if(j != n) { dum = 1.0 / a[j][j]; for(i=j+1; i<=n; i++) a[i][j] *= dum; } } free_dvector(vv,1,n+1); return; } //和ludcmp共同实现逆矩阵 void lubksb(double **a, int n, int *indx, double b[]) { int i, ii, ip, j; double sum; ii = 0; for(i=1; i<=n; i++) { ip = indx[i]; sum = b[ip]; b[ip] = b[i]; if( ii ) { for(j=ii; j<=i-1; j++) sum -= (a[i][j] * b[j]); } else if( sum ) { ii = i; } b[i] = sum; } for(i=n; i>=1; i--) { sum = b[i]; for(j=i+1; j<=n; j++) sum -= (a[i][j] * b[j]); b[i] = sum / a[i][i]; } return; } //输入:轮廓点x、y坐标数组, 轮廓点数目 array_length; //输出:轮廓点梯度图 diff; //功能:求轮廓点序列的差分图; void ComputeDifference(int array_length, double* diff, double* x, double* y )//计算每个点的梯度-梯度图 { int i, N; double dx, dy; double x_shift[24000], y_shift[24000]; // shift array position by one bit. N = array_length - 1; for(i=0; i 0) // 如果index > 0 ,那么IDX中存的是插值索引 ,此时:threshold=max_dist { for(i=0; i threshold) IDX[i] = 1; else IDX[i] = 0; } } else // 如果index <= 0 ,那么IDX中存的是删除多余点索引 ,此时:threshold=min_dist { for(i=0; i max_value) max_value = diff_array[i]; } return( max_value ); } //输入:插值标识数组:IDX 轮廓点x或者y方向数组:array_i 轮廓点的数目:array_length ; //输出:插值后的轮廓点x或y方向数组:array_d ; //功能:线性插值,用相邻元素取均值进行插值; int interp1(int* IDX, double* array_i, int array_length, double* array_d ) { int i, k; int new_length; k = array_length - 1; new_length = 0; for(i=0; i rows-1||k<1||k>cols-1) { pgFreeDmatrix(fx, 1, rows, 1, cols); return ; } y1 = fx[j][k]; y2 = fx[j+1][k]; y3 = fx[j+1][k+1]; y4 = fx[j][k+1]; t = x1 - (double)(j); u = x2 - (double)(k); //双线性插值 a1 = (1.0 - t) * (1.0 - u) * y1; a2 = t * (1.0 - u) * y2; a3 = t * u * y3; a4 = (1.0 - t) * u * y4; vfx[i] = a1 + a2 + a3 + a4; } pgFreeDmatrix(fx, 1, rows, 1, cols); return; } //输入:轮廓点x、y坐标数组 contour_x、contour_y , 轮廓点的数目 contour_length , // 最大距离和最小距离max_dist 和min_dist ; //输出:插值之后的轮廓x、y坐标数组 contour_x、contour_y //返回:轮廓点的数目; //功能:snake演变之后插值; int SnakeInterp(double* contour_x, double* contour_y, int contour_length, double max_dist, double min_dist ) { int i, k, m, N; int Interp_length; double max_d; double *diff; int *IDX; double *xi, *yi; double *xo, *yo; // convert to double format N = contour_length; m = 30 * N; //申请空间; diff = dvector(1, m); xo = dvector(1, m); xi = dvector(1, m); yo = dvector(1, m); yi = dvector(1, m); IDX = ivector(1, m); for(i=0; i max_dist ) //当轮廓点序列中的最大差分值比max_dist大时,需要继续插值; { if(Interp_length>3000) { max_d=0; break; } DefineIDX(N, IDX, diff, 1, max_dist); //定义插值标识; Interp_length = interp1(IDX, xo, N, xi); //x方向线性插值两次; Interp_length = interp1(IDX, yo, N, yi); //y方向线性插值两次; N = Interp_length; CopyDDArray(N, xi, xo); CopyDDArray(N, yi, yo); ComputeDifference(N, diff, xo, yo); //计算差分图; max_d = FindMaxValue(N, diff); //找差分图中最大值; k ++; } CopyDDArray(N, xo, contour_x); CopyDDArray(N, yo, contour_y); contour_x[N] = 0; contour_y[N] = 0; contour_length = N; //释放空间; free_dvector(diff,1,m); free_dvector(xo,1,m); free_dvector(xi,1,m); free_dvector(yo,1,m); free_dvector(yi,1,m); free_ivector(IDX,1,m); return( contour_length ); } //输出:array_x和array_y,其他参数均为输入; //功能:snake形变 void SnakeDeform(double* array_x, double* array_y, int array_length, //轮廓点x、y数组以及轮廓的长度; double alpha_single, double beta_single, //固定snake形变参数; double gamma_single, double kappa_single, //固定snake形变参数 double* OutputU_buf, double* OutputV_buf, //U、V场 int rows, int cols, int ITER //图像的行和列,以及迭代的次数; )//snake形变 { int i, j, k, m, N; int pixel_count; int *indx; double dv; double *d_buf1, *d_buf2; double *alpha, *beta, *gamma, *kappa; double *alpham1, *alphap1; double *betam1, *betap1; double *a, *b, *c, *d, *e; double *Avec, *Gvec; double *col; double *vfx, *vfy; double *tmpX, *tmpY; PGdouble **Amatrix; PGdouble **InvAmat; N = array_length; m = 4 * N; indx = ivector(1, m); col = dvector(1, m); alpha = dvector(1, m); beta = dvector(1, m); gamma = dvector(1, m); kappa = dvector(1, m); alpham1 = dvector(1, m); alphap1 = dvector(1, m); betam1 = dvector(1, m); betap1 = dvector(1, m); a = dvector(1, m); b = dvector(1, m); c = dvector(1, m); d = dvector(1, m); e = dvector(1, m); tmpX = dvector(1, m); tmpY = dvector(1, m); vfx = dvector(1, m); vfy = dvector(1, m); Avec = dvector(N, N); Gvec = dvector(N, N); Amatrix = pgDmatrix(1, N, 1, N); InvAmat = pgDmatrix(1, N, 1, N);/// for(i=0; i 0) { min_dd = dd; min_i = i; } } i = x_array[k+1]; j = y_array[k+1]; x_array[k+1] = x_array[min_i]; y_array[k+1] = y_array[min_i]; x_array[min_i] = i; y_array[min_i] = j; } return( contour_count); } // record_contour_array() /* ************************************************************************************ * * * This function is used to compute active contour * * * ************************************************************************************ */ int Computing_ActiveContour(USHORT* img_buf, // image buffer of original image USHORT* growth_buf, // image buffer recorded the original growth region (binary image) int rows, int cols, // rows and columns of image buffer int orig_contour_count, // count of contour pixels int* x_array, int* y_array // x, y array of contour pixels )//计算GVF场并计算活动轮廓 { USHORT *r_buf1, *r_buf2; USHORT *EdgeMap_buf; int i, j, k, n; int ITER; int pixel_count; int contour_count; double mu; //固定参数 mu=0.1; double u, v, mag; double max_dist, min_dist; //snakeInterp参数,相邻两点最大的距离max_dist和最小距离min_dist; double alpha, beta, gamma, kappa; //固定sake形变参数; double *FMap_buf; double *OutputU_buf, *OutputV_buf; double *px_buf, *py_buf; double *contour_x, *contour_y; double *f_buf1, *f_buf2, *f_buf3, *f_buf4; //申请空间; contour_count = orig_contour_count; EdgeMap_buf = svector(rows, cols); FMap_buf = dvector(rows, cols); OutputU_buf = dvector(rows, cols); OutputV_buf = dvector(rows, cols); px_buf = dvector(rows, cols); py_buf = dvector(rows, cols); contour_x = dvector(rows*cols/3, 1);//?? contour_y = dvector(rows*cols/3, 1); copy_svector(img_buf, EdgeMap_buf, rows, cols); // read initial contour data array for(k=0; k widthStep; BYTE * pData=(BYTE*)temp->imageData; for(i=0;i<125;i++) for(j=0;j<125;j++) { int jyx; jyx=(*(EdgeMap_buf+125*i+j))/16; if(jyx>255) pData[i*stepsPL+j]=255; else pData[i*stepsPL+j]=jyx; } /* cvNamedWindow("jyx",1); cvShowImage("jyx",temp); //显示梯度图; AfxMessageBox("nihao",MB_OK);*/ // gradient(EdgeMap_buf,rows,cols); //差分梯度; // remove pixels inside growth region pixel_count = rows * cols; r_buf1 = growth_buf; r_buf2 = EdgeMap_buf; while( pixel_count-- ) { if(*r_buf1 == MAX_12_BIT) *r_buf2 = 0; r_buf1 ++; r_buf2 ++; } pixel_count = rows * cols; f_buf1 = FMap_buf; r_buf1 = EdgeMap_buf; while( pixel_count -- ) { *f_buf1 ++ = (double)(*r_buf1 ++); } // compute the GVF of the edge map mu = 0.1; ITER = 80; GVFC(rows, cols, FMap_buf, OutputU_buf, OutputV_buf, mu, ITER); // normalize the GVF external force. f_buf1 = OutputU_buf; f_buf2 = OutputV_buf; f_buf3 = px_buf; f_buf4 = py_buf; pixel_count = rows * cols; double minva,maxva; minva=1.0; maxva=-1.0; while( pixel_count -- ) { u = *f_buf1; v = *f_buf2; mag = sqrt(u * u + v * v) + 1e-10; *f_buf3 = u / mag; *f_buf4 = v / mag; minva=(*f_buf3) maxva?(*f_buf3):maxva; f_buf1 ++; f_buf2 ++; f_buf3 ++; f_buf4 ++; } //测试; for(i=0;i<125;i++) for(j=0;j<125;j++) { pData[i*stepsPL+j]=(BYTE)(((double)255*((*(px_buf+125*i+j))-minva)/(maxva-minva))+0.5); // pData[i*stepsPL+j]=(BYTE)((double)255*(*(px_buf+125*i+j))); } /* cvNamedWindow("jyx",1); cvShowImage("jyx",temp); AfxMessageBox("nihao",MB_OK);*/ // snake deformation max_dist = 2.0; min_dist = 0.5; k = SnakeInterp(contour_x, contour_y, contour_count, max_dist, min_dist); //插值 contour_count = k; // iteration for snake deformation and interpretation. ITER = 5; alpha = 0.05; beta = 0.0; gamma = 1.0; kappa = 0.6; int snake_iter =20; //snack_iter =9;迭代次数多些没关系; for(k=1; k 1&&contour_count<3000) { SnakeDeform(contour_x, contour_y, contour_count, alpha, beta, gamma, kappa, px_buf, py_buf, rows, cols, ITER); j = SnakeInterp(contour_x, contour_y, contour_count, max_dist, min_dist); contour_count = j; } } max_dist=1.0; min_dist=0.5; if(contour_count<3000) { j = SnakeInterp(contour_x, contour_y, contour_count, max_dist, min_dist); contour_count = j; } // record the detected contour cordinate (x, y) into x_array and y_array pixel_count = 0; for(k=0; k 124||j>124) { continue; } n = *(growth_buf+j*cols+i);//用到ActiveContourRegion函数返回的growth_buf值 if(n == 0) { x_array[pixel_count] = (int)(0.5 + contour_x[k]); y_array[pixel_count] = (int)(0.5 + contour_y[k]); pixel_count ++; } } contour_count = pixel_count; x_array[contour_count] = 0; y_array[contour_count] = 0; //释放空间; free_svector(EdgeMap_buf); free_dvector(FMap_buf,rows,cols); free_dvector(OutputU_buf,rows,cols); free_dvector(OutputV_buf,rows,cols); free_dvector(px_buf,rows,cols); free_dvector(py_buf,rows,cols); free_dvector(contour_x,rows*cols/3, 1); free_dvector(contour_y,rows*cols/3, 1); free_svector(Para_a); free_svector(Para_b); free_svector(Para_c); free_svector(OrigImg); cvReleaseImage(&temp); return( contour_count ); } // End of Computing_ActiveContour() //输入:rows,scol;contour_count;x_array,y_array //输出:growth_buf //功能:计算包含肿块区域的矩形,该矩形的功能实际上是限制梯度图和GVF场的范围; void ActiveContourRegion(USHORT* growth_buf, // image buffer of growth region defined by active contour int rows, int cols, // rows and columns of image buffer int contour_count, // number of pixels in boundary contour int* x_array, int* y_array // contour (x, y) arrays )//将growth_buf赋值 { USHORT *LocalGrowth_buf; USHORT *LocalMorph_buf; USHORT *r_buf1; int i, j, k, pixel_count; int contour_pixels; int cent_x, cent_y; int max_x, max_y, min_x, min_y; int scol, srow; double *contour_x, *contour_y; contour_x = dvector(rows*cols/3, 1);//?? contour_y = dvector(rows*cols/3, 1); for(k=0; k max_x) max_x = i; if(j < min_y) min_y = j; if(j > max_y) max_y = j; } r_buf1 ++; } } //将包含肿块的最小矩形向外扩充20个像素点,得到的新矩形区域为受限肿块区域; if(contour_pixels > 0) { cent_x /= contour_pixels; // (cent_x,cent_y)为肿块的几何中心; cent_y /= contour_pixels; min_x -= 20; if(min_x < 0) min_x = 0; max_x += 20; if(max_x >= scol) max_x = scol - 1; min_y -= 20; if(min_y < 0) min_y = 0; max_y += 20; if(max_y >= srow) max_y = srow - 1; } // 将受限肿块区域之外的区域像素点灰度值设为4095;受限肿块区域灰度值设为0; for(j=0; j widthStep; BYTE* pFlagData = (BYTE*)flagImg->imageData; CvPoint candi[4] = {0, 0, flagImg->width-1, 0, 0, flagImg->height-1, flagImg->width-1, flagImg->height-1}; for(i=0; i<4; i++) if(pFlagData[candi[i].y*steps_PL+candi[i].x] != 255) return candi[i]; } //根据边界点修改区域标志:0---背景,178---区域内像素,255---边界像素 void Cal_RegionFlag(IplImage* flagImg)//flagImg: 8U { using namespace std; IplImage* tempImg = cvCloneImage(flagImg); int i, j; int steps_PL = flagImg->widthStep; BYTE* pTempData = (BYTE*)tempImg->imageData; BYTE* pFlagData = (BYTE*)flagImg->imageData; CvPoint seed = FindSeed(flagImg); bool** visited = new bool*[flagImg->height]; for(i=0; i height; i++) visited[i] = new bool[flagImg->width]; for(i=0; i height; i++) for(j=0; j width; j++) { visited[i][j] = false; } //生长 list stack; stack.push_back(seed); pFlagData[seed.y* steps_PL + seed.x] = 0; visited[seed.y][seed.x] = true; int dir[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}}; while(!stack.empty()) { CvPoint curPoint = stack.back();//取出 stack.pop_back();//弹出 for(i=0; i<4; i++) { CvPoint nextPoint = cvPoint(curPoint.x + dir[i][0], curPoint.y + dir[i][1]); if(nextPoint.x < 0 || nextPoint.y <0 || nextPoint.x > flagImg->width-1 || nextPoint.y > flagImg->height-1) continue; if(visited[nextPoint.y][nextPoint.x]) continue; if(pTempData[nextPoint.y* steps_PL + nextPoint.x] == 255)//遇到边界点 continue; pFlagData[nextPoint.y* steps_PL + nextPoint.x] = 0; stack.push_back(nextPoint); visited[nextPoint.y][nextPoint.x] = true; } } for(i=0; i height; i++) delete[] visited[i]; delete[] visited; cvReleaseImage(&tempImg); } //实现平滑; void Gaussion(IplImage *img) { int iTempW=3,iTempH=3; int iTempMY=1,iTempMX=1; float fCoef = 0.065; float fpArray[]={1,2,1,2,4,2,1,2,1}; //平滑模板; float fResult; BYTE * m_pData=(BYTE *)img->imageData; int steps_PL = img->widthStep * 8 / img->depth; int m_height=img->height; int m_width=img->width; BYTE **pTemp=new BYTE*[m_height]; for (int i=0;i 255) m_pData[steps_PL*(m_height-1-i)+j]=255; else m_pData[steps_PL*(m_height-1-i)+j]=(BYTE)(fResult+0.5); } } for(i=0;i maxg1) { maxg1=sum1; pos1.y=centre.y+(5*i+2); } if(sum2>maxg2) { maxg2=sum2; pos2.x=centre.x-(5*i+2); pos2.y=centre.y+(5*i+2); } if(sum3>maxg3) { maxg3=sum3; pos3.x=centre.x-(5*i+2); } if(sum4>maxg4) { maxg4=sum4; pos4.x=centre.x-(5*i+2); pos4.y=centre.y-(5*i+2); } if(sum5>maxg5) { maxg5=sum5; pos5.y=centre.y-(5*i+2); } if(sum6>maxg6) { maxg6=sum6; pos6.x=centre.x+(5*i+2); pos6.y=centre.y-(5*i+2); } if(sum7>maxg7) { maxg7=sum7; pos7.x=centre.x+(5*i+2); } if(sum8>maxg8) { maxg8=sum8; pos8.x=centre.x+(5*i+2); pos8.y=centre.y+(5*i+2); } } //取八个方向上的半径的平均值为最后求得的半径; radius=0; radius=radius+sqrt((pos1.x-centre.x)*(pos1.x-centre.x)+(pos1.y-centre.y)*(pos1.y-centre.y)) +sqrt((pos2.x-centre.x)*(pos2.x-centre.x)+(pos2.y-centre.y)*(pos2.y-centre.y)) +sqrt((pos3.x-centre.x)*(pos3.x-centre.x)+(pos3.y-centre.y)*(pos3.y-centre.y)) +sqrt((pos4.x-centre.x)*(pos4.x-centre.x)+(pos4.y-centre.y)*(pos4.y-centre.y)) +sqrt((pos5.x-centre.x)*(pos5.x-centre.x)+(pos5.y-centre.y)*(pos5.y-centre.y)) +sqrt((pos6.x-centre.x)*(pos6.x-centre.x)+(pos6.y-centre.y)*(pos6.y-centre.y)) +sqrt((pos7.x-centre.x)*(pos7.x-centre.x)+(pos7.y-centre.y)*(pos7.y-centre.y)) +sqrt((pos8.x-centre.x)*(pos8.x-centre.x)+(pos8.y-centre.y)*(pos8.y-centre.y)); radius=radius/8+2; assert(radius<55); return radius; } //输入:轮廓半径; 输出:记录轮廓的缓冲区,轮廓点序列数组; int GetContourPoint(int radius , USHORT * Contour_buf,int * x_array,int * y_array) { const int centre=63; CPoint lefttop,rightbottom; lefttop.x=lefttop.y=63-radius; rightbottom.x=rightbottom.y=63+radius; int i,j; int dist; int index=0; //将到中心的距离为radius的点记为轮廓点; for(i=lefttop.x;i<=rightbottom.x;i++) for(j=lefttop.y;j<=rightbottom.y;j++) { dist=sqrt((i-centre)*(i-centre)+(j-centre)*(j-centre)); if(dist==radius) { *(Contour_buf+i*125+j)=4095; x_array[index]=i; y_array[index]=j; index++; } } return index; } /****计算轮廓点数和肿块的面积,若轮廓点数和肿块的面积大于特定的阈值,就要重新获得初始轮廓, 若重新定初始轮廓,返回true,否则返回false ***/ bool IsGetRoundContour(IplImage * RoiRegion) { const int cont_threshold=200; //定义轮廓点阈值为200; const int area_threshold=1200; //定义肿块面积阈值为1200; int steps_PL = RoiRegion->widthStep * 8 / RoiRegion->depth; BYTE * pData = (BYTE*) RoiRegion->imageData; int i,j; //求肿块的轮廓点数和肿块的面积; int contnum,areanum; contnum=areanum=0; for(i=0;i<125;i++) for(j=0;j<125;j++) { if(pData[i*steps_PL+j]==255) contnum++; else if(pData[i*steps_PL+j]==178) areanum++; else ; } if(contnum>=cont_threshold&&areanum>=area_threshold) //判断; return true; else return false; } //输入:img //输出:resultImg //功能:最小二乘法背景趋势去除; void BackgrdCorrectMatlab(IplImage *img,IplImage * resultImg) { cvSetZero(resultImg); //求最小二乘法拟和的平面参数 int i,j; double a,b,c;//参数 int steps_PL = img->widthStep * 8 / img->depth; BYTE * pData = (BYTE*) img->imageData; BYTE* pDest = (BYTE*) resultImg->imageData; int nRows,nCols; nRows = nCols = img->width; double sumII,sumJJ,sumIJ,sumI,sumJ,sum1; sumII=sumJJ=sumIJ=sumI=sumJ=sum1=0; double sumIPij,sumJPij,sumPij; sumIPij=sumJPij=sumPij=0; for(i=0;i max) max = rawResult[i][j]; if(rawResult[i][j] < min) min = rawResult[i][j]; } } //进行标定,保存成结果图像 for(i=0;i depth == 8); assert(PImage->nChannels == 1); int i, j; int width = PImage->width; int height = PImage->height; int bytesPL = 8 * PImage->widthStep / PImage->depth;//4字节对齐 BYTE* pData = (BYTE*)PImage->imageData; BYTE* pMask ; if(mask != NULL) pMask = (BYTE*)mask->imageData; else pMask = NULL; for(i=0; i 0) histogram[value] ++; } } } //实现Gama校正 IplImage * GamaCorrectMatlab(IplImage *image) { int i,j; const double threshold=0.005; BYTE* pData = (BYTE*) image->imageData; int steps_PL = image->widthStep * 8 / image->depth; int height,width; height = image->height; width = image->width; double maxValue,minValue; maxValue=pData[0]; minValue=pData[0]; int count = (int)(threshold * image->width * image->height); int* histogram = new int[256]; CalHistogram8U(image, histogram, 256, NULL); int sumLo = 0; int sumHi = 0; for(i=0; i<255; i++) { sumLo += histogram[i]; if(sumLo > count) { minValue = i; break; } } for(i=255; i>=0; i--) { sumHi += histogram[i]; if(sumHi > count) { maxValue = i; break; } } //进行标定,保存成结果图像 for(i=0;i 1) rate = 1; if(rate < 0) rate = 0; double temp = 255 * rate * rate ; pData[i*steps_PL + j] = (BYTE) temp; } } delete histogram; return image; } double MaxInterstify(int m,double a[]) { double m_pix1=0; for(int i=0;i<=m;i++) { m_pix1+=a[i]; } double m_pix2=1-m_pix1; double h=0; for(int j=45;j<=m;j++) { if(a[j] > 0.000001) h-=a[j]*log(a[j]); } h=h/m_pix1; double h2=0; for(int t=m+1;t<256;t++) { if(a[t] > 0.000001) h2-=a[t]*log(a[t]); } h2=h2/m_pix2; h+=h2; h+=logf(m_pix1); h+=logf(m_pix2); return h; } //最大熵分割法 void MaxEntropy(IplImage *image) { int m_height,m_width; m_height=image->height; m_width=image->width; BYTE * m_pData=(BYTE *)image->imageData; int steps_PL = image->widthStep * 8 / image->depth; double m_Intensify[256]={0},sum_pix=0; for(int i=0;i maxen) { maxen=entropy[i]; max_inter=i; } for(i=0;i max_inter) m_pData[i*steps_PL + j]=255; else m_pData[i*steps_PL + j]=0; } } //输入:原始图像 img //输出和返回:经过背景趋势去除和最大熵方法得到的肿块区域图,返回的图像是一个二值图像, // 肿块区域灰度值为255,背景区域灰度值为0; IplImage * BackgroundTrendRemoveAndMaxEntropy(IplImage * img) { IplImage * resultimg; resultimg=cvCreateImage(cvSize(125, 125), 8, 1); BackgrdCorrectMatlab(img,resultimg); GamaCorrectMatlab(resultimg); //Gama校正; Gaussion(resultimg); //高斯滤波; MaxEntropy(resultimg); //最大熵方法分割肿块; return resultimg; //返回结果图像; } //输入:img //输出:resultimg //功能:实现背景趋势去除; void BackgroundTrendRemove(IplImage * img,IplImage *resultimg) { BackgrdCorrectMatlab(img,resultimg); GamaCorrectMatlab(resultimg); //Gama校正; } /*******基于四邻域取肿块区域轮廓,令轮廓点灰度值为255,背景区域灰度为0, 肿块内部点灰度为178 ******/ void GetRegionContour(IplImage * ImgRegion) //ImgRegion为8位区域图, //肿块轮廓和背景的灰度为0,肿块区域内部灰度为178。 { int stepsPL= ImgRegion->widthStep; BYTE * pData=(BYTE*)ImgRegion->imageData; int i,j; BYTE top,bottom,left,right; for(i=0;i height;i++) for(j=0;j width;j++) { if((pData[stepsPL*i+j]==0)&&i>1&&j>1&&i<(ImgRegion->height-1)&&j<(ImgRegion->width-1)) { //四领域; top=pData[stepsPL*(i-1)+j]; bottom=pData[stepsPL*(i+1)+j]; left=pData[stepsPL*i+(j-1)]; right=pData[stepsPL*i+(j+1)]; if(top==178||bottom==178||left==178||right==178) { pData[stepsPL*i+j]=255; } } } } //找轮廓,并将轮廓灰度值值为255; void FindContour(IplImage * roi_region) { int i,j; int stepsPL =roi_region->widthStep; BYTE * pData = (BYTE*)roi_region->imageData; int lheight=roi_region->height; int lwidth=roi_region->width; CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* contours = NULL; for(i=0;i total); cvCvtSeqToArray(contours, pointArray, CV_WHOLE_SEQ); int total = contours->total; for(i=0; i widthStep; BYTE * pData = (BYTE*)roi_region->imageData; visited[seed.x][seed.y]=true; //入队时置1 CList queue(10) ; //种子入队 queue.AddTail(seed); long countInRegion=1; while(!queue.IsEmpty()) //队列非空 { CPoint curPoint; //取队列头元素 curPoint=(CPoint)queue.RemoveHead(); //扩展种子点的8领域 for(i=-1;i<=1;i++) { for(j=-1;j<=1;j++) { if(curPoint.x+i<0 || curPoint.x+i>=125 || curPoint.y+j<0 || curPoint.y+j>=125 ) //越界处理 continue; if(i==0 && j==0 ) continue; lpSrc=pData[(curPoint.x+i)*stepsPL+(curPoint.y+j)]; if(!visited[curPoint.x+i][curPoint.y+j]) { visited[curPoint.x+i][curPoint.y+j]=true; if(lpSrc>0) { //入队 CPoint newSeed(curPoint.x+i,curPoint.y+j); queue.AddTail(newSeed); countInRegion++; } } } } } //队列为空 return countInRegion; } //找最大的连通区域作为肿块区域 void FindMostLargeRegion(IplImage * roi_region) { CPoint resultCenter(0,0); //最大连通区域内部的一点; LONG maxCountInRegion=0; //最大连通区域的点数; LONG tempCountInRegion; //临时变量; int stepsPL =roi_region->widthStep; BYTE * pData = (BYTE*)roi_region->imageData; int lHeight=roi_region->height; int lWidth=roi_region->width; int i,j; USHORT lpSrc; bool** visited=new bool*[lHeight]; //访问标志 for(i=0;i 0&&(visited[i][j]==false)) //Not the background and not visited { CPoint startPoint(i,j); tempCountInRegion=RegionGrowth(startPoint,visited,roi_region); //区域增长; if (tempCountInRegion>maxCountInRegion) { maxCountInRegion=tempCountInRegion; resultCenter.x=i; resultCenter.y=j; } //if } //if else visited[i][j]=true; } //for for(i=0;i widthStep / enhanceImg->depth; BYTE * pRoiData = (BYTE*)enhanceImg->imageData; int stepsPLRegion= roi.m_region->widthStep; BYTE * pRegionData=(BYTE*)roi.m_region->imageData; for(i=0;i<125;i++) for(j=0;j<125;j++) { *(img_buf+125*i+j)=(USHORT)(pRoiData[i*stepsPLRoi+j]*16); //将enhanceImg拷贝到img_buf中; *(Contour_buf+125*i+j)=0; } if(IsGetRoundContour(roi.m_region)) //判断是否重新取初始轮廓; { USHORT * Para_a, * Para_b, * Para_c, * OrigImg,*EdgeMap_buf; int rows=125; int cols=125; Para_a = svector(rows, cols); Para_b = svector(rows, cols); Para_c = svector(rows, cols); OrigImg = svector(rows, cols); EdgeMap_buf= svector(rows, cols); int radius; copy_svector(img_buf, OrigImg, rows, cols); MinQuare(Para_a,Para_b,Para_c,EdgeMap_buf,OrigImg); //最小二乘法就梯度图; radius=FindMassRadius(EdgeMap_buf); //求新的圆形初始轮廓的半径; GetContourPoint(radius,Contour_buf,x_array,y_array); //获得新的轮廓点数; //释放空间; free_svector(Para_a); free_svector(Para_b); free_svector(Para_c); free_svector(OrigImg); free_svector(EdgeMap_buf); } else { int index; index=0; for(i=0;i<125;i++) for(j=0;j<125;j++) { if(pRegionData[i*stepsPLRegion+j]==255) //轮廓点的灰度值为最大值255; { *(Contour_buf+125*i+j)=4095; x_array[index]=i; //初始化轮廓点数组; y_array[index]=j; index++; } else { *(Contour_buf+125*i+j)=0; //非轮廓点的灰度值令其为0; } } } Contour_count=record_contour_array(Contour_buf,125,125,x_array,y_array); //将曲线上的点按行走路线有序存储; ActiveContourRegion(growth_buf,125,125,Contour_count,x_array,y_array); //求包含肿块区域的矩形区域,并记录在缓冲区growth_buf中; Contour_count=Computing_ActiveContour(img_buf,growth_buf,125,125,Contour_count,x_array,y_array); //计算活动轮廓; //令轮廓灰度值为255,其他点的灰度值为178; for(i=0;i<125;i++) for(j=0;j<125;j++) { pRegionData[i*stepsPLRegion+j]=178; } for(k=0;k widthStep / enhanceImg->depth; BYTE * pRoiData = (BYTE*)enhanceImg->imageData; int stepsPLRegion= roi.m_region->widthStep; BYTE * pRegionData=(BYTE*)roi.m_region->imageData; int index; index=0; for(i=0;i<125;i++) for(j=0;j<125;j++) { *(img_buf+125*i+j)=(USHORT)(pRoiData[i*stepsPLRoi+j]*16); //将enhanceImg拷贝到img_buf中; if(pRegionData[i*stepsPLRegion+j]==255) //轮廓点的灰度值为最大值255; { *(Contour_buf+125*i+j)=4095; x_array[index]=i; y_array[index]=j; //初始化轮廓点数组; index++; } else { *(Contour_buf+125*i+j)=0; //非轮廓点的灰度值令其为0; } } Contour_count=record_contour_array(Contour_buf,125,125,x_array,y_array); //将曲线上的点按行走路线有序存储; ActiveContourRegion(growth_buf,125,125,Contour_count,x_array,y_array); //求包含肿块区域的矩形区域,并记录在缓冲区growth_buf中; Contour_count=Computing_ActiveContour(img_buf,growth_buf,125,125,Contour_count,x_array,y_array); //计算活动轮廓; //令轮廓灰度值为255,其他点的灰度值为178; for(i=0;i<125;i++) for(j=0;j<125;j++) { pRegionData[i*stepsPLRegion+j]=178; } for(k=0;k