随笔 - 67  文章 - 79  trackbacks - 0
<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用链接

留言簿(1)

随笔档案

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜

问题是这样的,有一组扇形位图,求其中每一个扇形的圆心,半径,圆心角
位图类似以下:这是一副一般扫描仪输出的结果

首先是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 阅读(379) 评论(1)  编辑  收藏

FeedBack:
# re: 对于给定离散轨迹 拟合其中存在的直线方程的分析[未登录] 2008-12-02 15:10 apple
好崇拜~~~~~~
差分求导又是怎么弄的??您搞的东西越来越深奥,越来越不懂!!!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: