问题是这样的,有一组扇形位图,求其中每一个扇形的圆心,半径,圆心角
位图类似以下:这是一副一般扫描仪输出的结果
首先是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 阅读(382)
评论(1) 编辑 收藏