ObjectHeader::ObjectHeader(){ m_Alias =0; m_Name = _T("NAME"); m_Type = LOCAL_SPACE; m_hIcon = NULL; m_Title = _T("Space unconnected!"); SetAreaSize(350,42); m_crText = SS.crBrainViewItemText; };
CLogicView::CRefItem::CRefItem(tstring RefName, tstring WhoRef){ m_RefName = RefName; m_WhoRef = WhoRef; SetAreaSize(300,20); };
CLogicView::CRefItem::CRefItem(){ SetAreaSize(300,20); };
CLogicView::CLogicLabel::CLogicLabel(int32 TypeID,tstring Name,HICON hIcon){ m_Alias = TypeID; m_Name=Name; m_hIcon = hIcon; SetAreaSize(300,20); };
ObjectItem::ObjectItem(int64 ID,tstring& Name,SPACETYPE Type, tstring& Fingerprint,HICON hIcon) :CVSpace2(ID),m_Name(Name),m_Type(Type),m_Fingerprint(Fingerprint),m_hIcon(hIcon) { SetAreaSize(350,22); };
CMemoryView::CTextItem::CTextItem(int Index,int64 ID,tstring Text) :CVSpace2(ID),m_Index(Index),m_Text(Text){ SetAreaSize(200,20); }
CMemoryView::CTitle::CTitle(int64 ID, const tstring& Name) :CVSpace2(ID),m_Text(Name.c_str()) { m_ObjectCount = 0; SetAreaSize(200,20); }
//包含了最小值和最大值的4邻域边界跟踪细胞 void ImageViewer::FourAreaTrackPlasm(int minvalue, int maxvalue) { double m_dCellCompact;//细胞紧凑度 int m_iCellArea; //细胞面积 int m_iCellPerimeter; //细胞周长 Boud_List *m_lp4AreaCellBoudList; //保存4邻域跟踪后的链表信息, //该链表存储每个细胞构成像素点的所有坐标 int i,j,m; int Min_Round = minvalue; int Max_Round = maxvalue; //起始点 int StartX,StartY; //当前点 int CurrentX,CurrentY; //前一点 int PrevX,PrevY; //用来标定当前点的正上方和左边的点 int fup,fleft; //该数组用来标定每一点所属的区域 short img_label[240][320]; short img[240][320]; //建立一个数组,用来判断图象中的点是否已经被选择为边界点,为真就是边界点,否则不是边界点 bool boudary_points[240][320]; //用来标记边界的个数 int label; //法线方向 int BeginDirection; //边界点的个数 int NumPoint; //四邻域方向 //当前的邻域方向如图 // 3 // ^ // | // 2<----当前点----> 0 // | // V // 1 int Direction1[4][2] ={{0,1},{1,0},{0,-1},{-1,0}}; //基本信息的初始化 //可以考虑把图像分割为多个子图像,然后每个子图像分别进行轮廓的提取 //图象的宽度和高度 long lHeight,lWidth; lHeight = m_dwHeight; lWidth = m_dwWidth; label = 1; unsigned char *lpImage=NULL;//指向图像像素的指针 long lLineBytes = LineBytes; //需要把数字图象首先灰度化,然后进行阀值分割,再进行腐蚀掉小的噪声点,最后进行边界跟踪 for(i=0;i<lHeight;i++) { for(j=0;j<lWidth;j++) { lpImage=m_pImage+lLineBytes*(lHeight-1-i)+j; img[i][j] = *lpImage;//转存到二维数组中 img_label[i][j] = 0;//所有点都尚未标识区域 boudary_points[i][j] = false;//尚无边界点 if(img[i][j]==0)//黑点 { if(i==0&&j!=0&&j!=319)//第1行,除了最左上角和最右上角的点 { fup=255;//白点 fleft=img[i][j-1]; } if(j==0&&i!=0&&i!=239)//第1列,除了最左上角和最左下角的点 { fleft=255;//白点 fup = img[i-1][j]; } if(i!=0&&j==319&&i!=239)//最后1列,除了最右上角和最右下角的点 { fleft = img[i][j-1]; fup = img[i-1][j]; } if(i==239&&j!=0&&j!=319)//最后1行,除了最左下角和最右下角的点 { fleft = img[i][j-1]; fup = img[i-1][j]; } if(i==0&&j==0)//最左上角的点 { fleft=255;//白点 fup=255;//白点 } if(i!=0&&j!=0&&i!=239&&j!=319)//中间点 { fup = img[i-1][j]; fleft = img[i][j-1]; } if(i==0&&j==319)//最右上角的点 { fup = 255; fleft = img[i][j-1]; } if(j==0&&i==239)//最左下角点 { fup = img[i-1][j]; fleft = 255; } if(j==319&&i==239)//最右下角点 { fup = img[i-1][j]; fleft = img[i][j-1]; } if(fup==fleft&&fup==0) img_label[i][j] = img_label[i-1][j];//up point if(fleft==0&&fup==255) img_label[i][j] = img_label[i][j-1];//left point if(fleft==255&&fup==0) img_label[i][j] = img_label[i-1][j];//up point if(fup==fleft&&fup==0&&img_label[i-1][j]==img_label[i][j-1]) img_label[i][j] = img_label[i-1][j]; if(fup==fleft&&fup==255)//new area point { img_label[i][j]=label;//new area label label++;//label add 1 } if(fup==fleft&&fup==0&&img_label[i-1][j]!=img_label[i][j-1])//标号往小值赶 { if(img_label[i-1][j]>=img_label[i][j-1])//up > left { img_label[i][j]=img_label[i][j-1];//left point img_label[i-1][j]=img_label[i][j-1];//up point = left point } else//up < left { img_label[i][j]=img_label[i-1][j];//up point img_label[i][j-1]=img_label[i-1][j];//left point = up point } } } } } //获取第1次得到的区域的个数,这个值偏大 int Max_label = label; //定义一个数组存放每个区域的起点的坐标 //这个数组的大小要动态确定 int start_point[76800][2]; int *label_kind; label_kind = (int *)malloc((label + 1) * sizeof(int)); int *area_point; area_point = (int *)malloc((label + 1) * sizeof(int)); //这个数组用来计算区域的个数 for(m=0;m<label+1;m++) { label_kind[m] = 0; area_point[m] = 0; } //顺序记录区域起点的坐标 int flag=1; //标定区域的实际个数以及每个区域的起始坐标点 //这个算法的运算量太大 for(i=0;i<=239;i++) { for(j=0;j<=319;j++) { for(m=0;m<=Max_label;m++) { //物体点且标号值存在,必然是从小到大 if(m==img_label[i][j]&&img[i][j]==0) { if(label_kind[m]==0)//第1次发现这种标号 { //记录下的坐标 start_point[flag][0]=i; start_point[flag][1]=j; flag++;//顺序前移 } label_kind[m]++;//累加此种类型标号的数量 break; } } } } //用来保存区域的面积的大小 int *area_size; area_size = (int *)malloc((Max_label + 1) * sizeof(int)); //计算区域的个数,这个区域数目也并非是真正的数目,其中有一些在物体中, //但和其他点的label不一样的点 label=0; for(m=0;m<=Max_label;m++) { if(label_kind[m]>0)//该区域存在 { label++;//区域数累加,it's not real label } area_size[m]=0;//every area's area is 0 } //有多少个区域就要扫描多少次,注意它是从1开始的 int scan_times=1; //用来移动数组area_point的指针 int count=1; //用来计算所有区域的边界点的个数 int total_points=0; int real_label; //对每一个区域分别进行4邻域的边界跟踪 //armstrong added 把每个封闭区域的头链接起来 Boud_List *listhead; listhead = (Boud_List *)malloc(sizeof(Boud_List)); listhead->lnext = NULL; listhead->phead = NULL; //armstrong added 把每个封闭区域的头链接起来 //这一段程序的耗时最多 while(scan_times<=label) { //找到开始点 StartX = start_point[scan_times][0]; StartY = start_point[scan_times][1]; //表示该区域不在其他区域之中,为独立区域,且从一个物体点开始 if(label_kind[img_label[StartX][StartY]]>0&&img[StartX][StartY]==0) { boudary_points[StartX][StartY] = true;//开始点是边界点 NumPoint = 1;//当前边界点个数 //armstrong added 创建链表 11-10 Boudary *head,*PrevP,*CurrentP,*pnew,*p; head = (Boudary *)malloc(sizeof(Boudary)); //此处一定要这样处理,因为在数组中存放是逐行再逐列,数组中的行其实就是实际像素点所在的列, //而数组中的列其实就是实际像素所在的行 head->x = StartY; head->y = StartX; head->next = NULL; head->head = head; //armstrong added 创建链表 11-10 //找到边界的第2点 for(i=0; i<4; i++) { if(img[StartX+Direction1[i][0]][StartY+Direction1[i][1]]==0)//非空白点 { CurrentX = StartX+Direction1[i][0];//记录当前点的坐标 CurrentY = StartY+Direction1[i][1]; boudary_points[CurrentX][CurrentY] = true;//第2点也是边界点 NumPoint++;//边界点个数递增 //armstrong added 11-10 p = (Boudary *)malloc(sizeof(Boudary)); p->x = CurrentY; p->y = CurrentX; head->next = p;//和第1个结点链接起来 p->next = NULL; p->head = head; //armstrong added 11-10 break; } } //最初的开始点 PrevX = StartX; PrevY = StartY; //armstrong added 11-10 PrevP = (Boudary *)malloc(sizeof(Boudary)); PrevP = head; //开始扫描前,前一个结点指向head结点 CurrentP = (Boudary *)malloc(sizeof(Boudary)); CurrentP = p; //开始扫描前,当前结点指向第2个结点 //armstrong added 11-10 //找其他的边界点 if(i==4) { //该起始点是孤立点,请重新选择起点 } else { while(1)//当找到起点 { //边界已经闭合 if((CurrentX == StartX)&&(CurrentY == StartY)) { //边界跟踪成功完毕,要求记录此时区域的边界点的个数 //边界点周长大于预设值 if(NumPoint>Min_Round && NumPoint<Max_Round) { total_points = total_points + NumPoint; //这个数组中具体存放每个区域的周长 area_point[count] = NumPoint; count++; //armstrong added 把每个封闭区域的头链接起来 if(listhead->lnext==NULL)//只有头结点 { Boud_List *blist; blist = (Boud_List *)malloc(sizeof(Boud_List)); listhead->lnext = blist;//让头结点指向第1个结点 blist->phead = head;//第1个结点指向的第1个封闭区域的头结点 blist->lnext = NULL; } else//已经超过1个结点 { Boud_List *blist,*newlist; blist = (Boud_List *)malloc(sizeof(Boud_List)); blist = listhead; while(blist->lnext)//检索链表,直到某个结点的lnext为空 { blist = blist->lnext; } newlist = (Boud_List *)malloc(sizeof(Boud_List)); blist->lnext = newlist;//将该结点加入到链表的尾部 newlist->phead = head;//并将该结点指向当前封闭区域的头结点 newlist->lnext = NULL; } //armstrong added 把每个封闭区域的头链接起来 // break; } break; } else//找下一个边界点 { //首先确定当前标准方向的外法线方向 if((CurrentX ==PrevX)&&(CurrentY ==(PrevY+1))) BeginDirection = 3;//方向3 if((CurrentX ==PrevX)&&(CurrentY ==(PrevY-1))) BeginDirection = 1;//方向1 if((CurrentX ==(PrevX+1))&&(CurrentY ==PrevY)) BeginDirection = 0;//方向0 if((CurrentX ==(PrevX-1))&&(CurrentY ==PrevY)) BeginDirection = 2;//方向2 i=BeginDirection;//记录开始扫描方向 while(1) { //外法线的方向为优先考虑 if(img[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]]==0&&CurrentX+Direction1[i][0]>=0&&CurrentX+Direction1[i][0]<240&&CurrentY+Direction1[i][1]>=0&&CurrentY+Direction1[i][1]<320) { //如果这个点尚未选中,即新的当前点是边界点 if(!boudary_points[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]]) { //该点是目标点 boudary_points[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]] = true; //如果当前点的label值和四邻域中的点的label值不等,则校正四邻域中点label的值 //并且置这种label的个数的值为0 if(img_label[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]]!=img_label[CurrentX][CurrentY]) { //留着再扫描一遍,如果这个值变成了0,则相应的label值要变 //记录需要修正的label值,将要更新的值直接给label_kind; //以后在扫描时,只要把这个值取反即可 if(img_label[CurrentX][CurrentY] < img_label[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]]) { label_kind[img_label[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]]] = -img_label[CurrentX][CurrentY]; //当前边界点的label值立即被更新 img_label[CurrentX+Direction1[i][0]][CurrentY+Direction1[i][1]] = img_label[CurrentX][CurrentY]; } } //armstrong added 11-10 pnew = (Boudary *)malloc(sizeof(Boudary)); pnew->x = CurrentY+Direction1[i][1]; pnew->y = CurrentX+Direction1[i][0]; pnew->next = NULL; pnew->head = head; CurrentP->next = pnew;//把它加入到当前链表的尾部 PrevP = CurrentP;//更新前一个结点指针 CurrentP = pnew;//更新当前结点指针 //armstrong added 11-10 //边界点数目递增 NumPoint++; } //修改前一点坐标 PrevX = CurrentX; PrevY = CurrentY; //新的当前点 CurrentX = CurrentX+Direction1[i][0]; CurrentY = CurrentY+Direction1[i][1]; break; } else { i=(i+1)%4;//循环寻找下一个点 } } } } } } scan_times++;//扫描次数累加 }//while end //计算面积 for(i=0; i<=239; i++) { for(j=0; j<=319; j++) { if(img[i][j]==0) { //区域中应该是相同label的点的label值都要更新 if(label_kind[img_label[i][j]]<0) { img_label[i][j] = -label_kind[img_label[i][j]]; } //区域的面积加1 //例如区域的label值为2,此时area_size[2]加1 area_size[img_label[i][j]]++; //is a boudary pix if (boudary_points[i][j]) { lpImage = m_pImage + lLineBytes * (lHeight - i - 1) + j; *lpImage = (unsigned char)0; } else { lpImage = m_pImage + lLineBytes * (lHeight - i - 1) + j; *lpImage = (unsigned char)255; } } else { lpImage = m_pImage + lLineBytes * (lHeight - i - 1) + j; *lpImage = (unsigned char)255; } } } fpDest = fopen("ContourFollowing.bmp", "wb"); fwrite(&(bf.bfType), sizeof(bf.bfType), 1, fpDest); fwrite(&(bf.bfSize), sizeof(bf.bfSize), 1, fpDest); fwrite(&(bf.bfReserved1), sizeof(bf.bfReserved1), 1, fpDest); fwrite(&(bf.bfReserved2), sizeof(bf.bfReserved2), 1, fpDest); fwrite(&(bf.bfOffBits), sizeof(bf.bfOffBits), 1, fpDest); fwrite(&(bi.biSize), sizeof(bi.biSize), 1, fpDest); fwrite(&(bi.biWidth), sizeof(bi.biWidth), 1, fpDest); fwrite(&(bi.biHeight), sizeof(bi.biHeight), 1, fpDest); fwrite(&(bi.biPlanes), sizeof(bi.biPlanes), 1, fpDest); fwrite(&(bi.biBitCount), sizeof(bi.biBitCount), 1, fpDest); fwrite(&(bi.biCompression), sizeof(bi.biCompression), 1, fpDest); fwrite(&(bi.biSizeImage), sizeof(bi.biSizeImage), 1, fpDest); fwrite(&(bi.biXPelsPerMeter), sizeof(bi.biXPelsPerMeter), 1, fpDest); fwrite(&(bi.biYPelsPerMeter), sizeof(bi.biYPelsPerMeter), 1, fpDest); fwrite(&(bi.biClrUsed), sizeof(bi.biClrUsed), 1, fpDest); fwrite(&(bi.biClrImportant), sizeof(bi.biClrImportant), 1, fpDest); fseek(fpDest, 54, SEEK_SET); fwrite(ipRGB, bf.bfOffBits - 54, 1, fpDest); fwrite(lpImage, bf.bfSize - bf.bfOffBits, 1, fpDest); QPixmap dst("ContourFollowing.bmp"); imageLabel->setPixmap(dst); int total_area=0; int area_num=0; for(m=1;m<Max_label+1;m++) { //面积和阀值的比较 if(area_size[m]>Min_Round &&area_size[m]<Max_Round) { total_area = total_area+area_size[m]; area_num++; } else { //把所有label值等于m的面积中的点换为baidian area_size[m] = 0; /* if(remove) { for(i=0; i<=239; i++) { for(j=0; j<=319; j++) { if(img_label[i][j]==m) { lpImage = m_pImage+lLineBytes*(lHeight-1-i)+j; *lpImage = 255; } } } } */ } } real_label = count-1;//真实的区域的个数 if(real_label>0) avg_round = total_points/real_label;//平均周长 else avg_round = 0; if(area_num>0) avg_area = total_area/area_num;//平均面积 else avg_area = 0; //把几个关键值传到图像类的成员变量中 if(real_label>0) { SetLabel(real_label);//设置符合周长要求的区域的个数 SetNumPoint(area_point);//设置周长动态数组 SetMinRound(Min_Round);//设置最小周长 SetAvgRound(avg_round);//设置平均周长 sprintf(msg_round,"周长大于%d小于%d的细胞区域%d个,平均周长%d个像素\n",\ Min_Round,Max_Round,real_label,avg_round); QMessageBox::information(this, tr("information"), tr(msg_round).arg(fileName)); } if(area_num>0) { SetAreaNum(area_num);//设置符合要求的面积个数 SetAreaSize(area_size,Max_label);//设置面积动态数组 SetMaxLabel(Max_label);//设置最大的区域数目 SetAvgArea(avg_area);//设置平均面积值 sprintf(msg_area,"面积大于%d小于%d的细胞区域%d个,平均面积%d个像素\n",\ Min_Round,Max_Round,area_num,avg_area); QMessageBox::information(this, tr("information"), tr(msg_area).arg(fileName)); } if(real_label==area_num&&area_num==1&&avg_area!=0)//只有1个区域 { //细胞的紧凑度 m_dCellCompact = (double)(avg_round*avg_round)/(double)avg_area; //细胞面积 m_iCellArea = avg_area; //细胞周长 m_iCellPerimeter = avg_round; } else { m_dCellCompact = 0; m_iCellArea = 0; m_iCellPerimeter = 0; } m_lp4AreaCellBoudList = new Boud_List; m_lp4AreaCellBoudList = listhead;//保存获取的细胞区域的链表结构 Set4AreaTracked(true);//设置4邻域跟踪完成 if(real_label>0&&area_num>0)//如果均满足要求则输出提示信息 { strcat(msg_round,msg_area); //AfxMessageBox(msg_round,MB_ICONINFORMATION|MB_OK); } else { //AfxMessageBox("没有满足条件的区域!"); } free(label_kind); free(area_point); free(area_size); }