首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

求算法高手帮解决一个有关问题

2013-08-09 
求算法高手帮解决一个问题如图,我的代码功能就是把图中的白色球用矩形框出来,想优化下算法。下面贴找白色球

求算法高手帮解决一个问题
求算法高手帮解决一个有关问题

如图,我的代码功能就是把图中的白色球用矩形框出来,想优化下算法。
下面贴找白色球部分的代码。


        public static bool init(Bitmap bmp)
        {
            try
            {
                lightPoints = new Rectangle[POINTNUM];
                int DIA = 20;                           //光斑最小直径
                int[,] Centers = new int[POINTNUM, 3];  //圆心二维数组【横坐标,纵坐标,半径】
                int Gate = 100;                          //亮度临界点
                int Count = 0;                          //圆心计数器
                int xPoint = 0;                         //圆顶点横坐标
                int yPoint = 0;                         //圆顶点纵坐标
                int radius = 0;                         //圆半径
                int ox = 0;                             //圆心横坐标
                int oy = 0;                             //圆心纵坐标


                int yTraversal = 0;                     //纵向遍历标记0
                bool touchCircle = false;            //没有接触到圆
                bool topPoint = false;                  //未找到顶点
                bool firstPoint = false;                //未找到横向首点

                //下面的循环找顶点
                for (yTraversal = 10; yTraversal < bmp.Height - 10; yTraversal = yTraversal + 10)                               //之所以要留出10像素的框是因为边界颜色是淡灰色的,容易被误认为是圆内
                {
                    for (int xTra = 10; xTra < bmp.Width - 10; xTra = xTra + 10)                                                //先横向扫描,+10为了提高效率
                    {
                        if (Count < POINTNUM)
                        {
                            
                            if (inFoundCircle(Centers, xTra, yTraversal, Count))                                                //如果这个点在已经发现的圆内了,那就没必要判断了,我们要找的是圆的定点


                            {
                                continue;
                            }
                            else
                            {
                                if (getPixelByGray(bmp, xTra, yTraversal) > Gate && !firstPoint)                                //圆内了,且是首次进圆
                                {
                                    xTra = xTra - 11;                                                                           //使横坐标倒退1
                                    touchCircle = true;
                                }
                                else if (getPixelByGray(bmp, xTra, yTraversal) < Gate && touchCircle && !firstPoint)            //刚到圆外,且未找到首点,横坐标+1即可确定首点横坐标


                                {
                                    xPoint = xTra;                                                                              //理论上圆的顶点是个点,但是图片中圆的顶部可能是条线,我们算它的中点作为顶点,所以要记收尾坐标
                                    xTra = xTra - 9;
                                    firstPoint = true;
                                }
                                else if (getPixelByGray(bmp, xTra, yTraversal) > Gate && touchCircle && firstPoint)             //又到圆内了,且是首点
                                {
                                    xTra = xTra - 9;
                                }
                                else if (getPixelByGray(bmp, xTra, yTraversal) < Gate && touchCircle && firstPoint)             //刚出圆,且是尾点


                                {
                                    xPoint = (xPoint + xTra - 1) / 2;        //顶点横坐标
                                    yPoint = yTraversal;                        //顶点纵坐标
                                    topPoint = true;
                                    firstPoint = false;
                                    touchCircle = false;
                                }
                            }   //end else

                            //找到顶点了,开始找直径
                            if (topPoint)
                            {
                                for (int iTra = yTraversal; iTra > 10; iTra--)
                                {


                                    if (getPixelByGray(bmp, xPoint, iTra) < Gate)                               //出圆了!
                                    {
                                        yTraversal = iTra + 1; 
                                        break;
                                    }
                                }
                                for (int iTra = yTraversal; iTra < bmp.Height - 10; iTra++)                     //后纵向扫描
                                {
                                        if (getPixelByGray(bmp, xPoint, iTra) < Gate && iTra -DIA  > yTraversal) //出圆了!
                                        {
                                            radius = (iTra - yTraversal - 1) / 2;       //半径


                                            ox = xPoint;                                //圆心横坐标
                                            oy = (iTra + yTraversal - 1) / 2;           //圆心纵坐标
                                            Centers[Count,0] = ox;                    //保存圆心的横坐标
                                            Centers[Count,1] = oy;                    //保存圆心的纵坐标
                                            Centers[Count,2] = radius;                  //保存圆的半径
                                            //记录矩形
                                            lightPoints[Count].X = ox - radius;         //矩形左上角横坐标
                                            lightPoints[Count].Y = oy - radius;         //矩形左上角纵坐标


                                            lightPoints[Count].Width = 2 * radius;      //矩形宽
                                            lightPoints[Count].Height = 2 * radius;     //矩形长
                                            topPoint = false;
                                            Count++;
                                            break;
                                        }
                                }
                            }
                        }   //end if
                        else break;
                    }
                }
                return true;
            }   //end try

            catch (System.Exception ex)


            {
                MessageBox.Show(ex.ToString() + "IIPOINT");
                return false;
            }

        }

        //判断图片上一点是否在光斑内
        public static bool inFoundCircle(int[,] centers, int x, int y, int num)
        {
            for (int iTra = 0; iTra < num; iTra++)
            {
                if (((x - centers[iTra, 0]) * (x - centers[iTra, 0]) + (y - centers[iTra, 1]) * (y - centers[iTra, 1])) <= (centers[iTra, 2] + 20) * (centers[iTra, 2] + 20))
                //为了效率,避免了除法和开方,原公式为计算点到圆心距离与半径大小,这个经过了变形
                //原式:[(x-ox)^2+(y-oy)^2]<=r^2把圆扩大了一圈(r=r+10)
                {
                    return true;
                }
            }
            return false;
        }

        //计算图片上一点的灰度值
        public static int getPixelByGray(Bitmap bmp, int x, int y)
        {
            Color color = bmp.GetPixel(x, y);
            return color.R + color.G + color.B;//算平均值获得灰度,为了效率不除3了,反正只判断大小
        }

算法 性能优化
[解决办法]
楼主这个算法叫什么,有相关理论链接吗?发一个,有空研究下,比较有趣
[解决办法]
直接用OpenCV好了,代码少,效率高。

http://wenku.baidu.com/view/96e75a41a8956bec0975e327
[解决办法]
http://www.aiseminar.cn/bbs/forum.php?mod=viewthread&tid=617

http://www.cnblogs.com/tornadomeet/archive/2012/12/11/2813534.html

http://blog.csdn.net/byxdaz/article/details/5807639

热点排行