問題是這樣的,有一組扇形位圖,求其中每一個扇形的圓心,半徑,圓心角
位圖類似以下:這是一副一般掃描儀輸出的結果

首先是opencv 能幫我們做得,提取圖像邊緣 效果如圖:
void getEdge(const IplImage* pImg,IplImage* pCannyImg,int pos){
IplImage* pGray = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);
cvCvtColor(pImg,pGray,CV_BGR2GRAY);
cvSmooth(pGray,pCannyImg,CV_BLUR,3,3,0,0);
cvNot(pGray,pCannyImg);
cvCanny(pGray,pCannyImg,pos,pos*3,3);
cvRelease(&pGray);
}
然后就要對邊緣分割來得到一個個扇形,因為這些扇形都是整齊排列的,所以不需要什么封閉軌跡檢查,直接根據點的坐標的連續性就可以判定了。不妨設橫豎相差大于3個像素點為不同扇形的點。
const int hgap=3;
const int vgap=3;
for(int row=0;row<edge->height;++row){
for(int col=0;col<edge->width;++col){
const uchar* value=(const uchar*)edge->imageData+row*edge->widthStep+col;
if( *value == 255){
// printf("%d,%d = %d\n",row,col,*value);
points.push_back(std::make_pair(col,row));
}
}
}
Points::const_iterator iter;
Point prev=std::make_pair(0,0);
for(iter=points.begin();iter!=points.end();++iter){
if(iter->second-prev.second > vgap){
Area area;
areas.push_front(area);
}
areas[0].push_back(*iter);
prev=*iter;
}
prev=std::make_pair(0,0);
for(Areas::iterator iter= areas.begin();iter!=areas.end();++iter){
std::sort(iter->begin(),iter->end());
for(Area::const_iterator iter2=iter->begin();iter2!=iter->end();++iter2){
if((iter2->first-prev.first>hgap) || (iter2->first-prev.first<0)){
Area area;
result.push_front(area);
}
result[0].push_back(*iter2);
prev=*iter2;
}
}
這樣我們就得到了一組扇形的邊緣軌跡。因為這些軌跡是無序排列的,所以我們需要求出這個扇形的邊緣鏈碼,才能對軌跡進行分析。
又由于掃描得到的圖片有明顯失真,所以用一般的8領域并不能準確得到鏈碼,我們需要更大的領域矩陣。
求N階領域函數:
Points getNearPoints(const Point& point,int gap=1){
std::set<Point> s_points;
Points points;
int x(point.first),y(point.second);
for(int i=gap;i>=-gap;--i){
for(int j=gap;j>=-gap;--j){
s_points.insert(std::make_pair(x+i,y+j));
}
}
for(std::set<Point>::const_iterator iter = s_points.begin();iter!=s_points.end();++iter){
if(*iter!=point)
points.push_back(*iter);
}
return points;
}
這里有一點算法優化,因為可以保證:扇形2條半徑中右邊的一條必定斜率為0,所以求出右邊半徑的2個斷點很簡單。因為斜率為0,即此區間上的微分為0,也即差分為0。所以半徑的右斷點和圓心為軌跡上最長的差分為0區間的2個端點。
有了圓心點,再根據鏈碼 向下尋找,得到左邊半徑的軌跡:

由于直線的二階導數為0 左端點即為以上軌跡中二階差分為0的最長區間的左端點
有了2條半徑的端點,不難求得此扇形的圓心角。
由于圓形角代表了每一個扇形紅色的分度值,所以可以將原圖修復如下:
posted on 2008-11-28 15:27
zarra 閱讀(387)
評論(1) 編輯 收藏