OpenCV:曲线的检测与提取-0

2025-10-30 21:12:17

1、基本思想:

给出一个带有曲线像素宽度为1的二值图像;

①遍历图像像素,找到第一个白色的点;

②在此点的八邻域内找到下一个白色的点;

③将找到的点的灰度值置为0;保存找到点的坐标;

④八邻域内没有找到白色点,则表示一端搜索完成;

原图如下:

OpenCV:曲线的检测与提取-0

2、【注】:

①第一个找到的点不一定是曲线的端点,

因此应该分别向两边寻找相邻的点;

②在搜寻相邻像素点时,

会首先搜寻此点与上一个点相邻像素相对的位置;

这样可以减少寻找的次数,而且当有相交的曲线时,能连接到我们一般认为的曲线。

OpenCV:曲线的检测与提取-0

3、程序如下:

//寻找二值图像上的第一个点

//maskImg二值图像,标记

//outPoint输出查找的点

bool findFirstPoint(Mat &maskImg, Point &outPoint)

{

       bool success = false;

       for (int i = 0; i < maskImg.rows; i++)

       {

              unsigned char *pData = (unsigned char*)(maskImg.data+i*maskImg.step);

              for (int j = 0; j < maskImg.cols; j++)

              {

                     if (pData[j] == 255)//找到第一个白色的点

                     {

                            success = true;

                            outPoint.x = j;

                            outPoint.y = i;

                            pData[j] = 0;//将此点像素设为0

                            break;

                     }

              }

              if (success)

                     break;

       }

       return success;

}

OpenCV:曲线的检测与提取-0

4、//八邻域中寻找曲线上某个点的下一个点

//neiPoint八邻域点

//currPt当前点

bool findNextPoint(vector<Point> &neiPt, Mat &image, Point currPt, int currFlag, Point& outPt, int &outFlag)

{

       int i = currFlag;//0,6

       int count = 1;

       bool success = false;

       while (count <= 7)

       {

              Point tpPt = currPt + neiPt[i];//邻域像素点

              if (tpPt.x > 0 && tpPt.y > 0 && tpPt.x < image.cols && tpPt.y < image.rows)//在图像内部

              {

                     if( ((unsigned char*)(image.data+tpPt.y*image.step))[tpPt.x]==255 )

                     {

                            outPt = tpPt;

                            outFlag = i;

                            success = true;

                            ((unsigned char*)(image.data+tpPt.y*image.step))[tpPt.x]=0;

                            break;//跳出循环

                     }

              }

              if (count % 2)//奇数

              {

                     i += count;

                     if (i > 7)

                     {

                            i -= 8;

                     }

              }

              else

              {

                     i += -count;

                     if (i < 0)

                     {

                            i += 8;

                     }

              }

              count++;

       }

       return success;

}

OpenCV:曲线的检测与提取-0

5、//寻找曲线 :

void findLines(Mat &binaryImg, vector<deque<Point>> &outLines)

{

       //八邻域

       vector<Point> neighborPtVec;

       neighborPtVec.push_back(Point(-1,-1));

       neighborPtVec.push_back(Point(0,-1));

       neighborPtVec.push_back(Point(1,-1));

       neighborPtVec.push_back(Point(1,0));

       neighborPtVec.push_back(Point(1,1));

       neighborPtVec.push_back(Point(0,1));

       neighborPtVec.push_back(Point(-1,1));

       neighborPtVec.push_back(Point(-1,0));

       Point firstPt;

       while (findFirstPoint(binaryImg, firstPt))

       {

              deque<Point> line;//点的队列

              line.push_back(firstPt);//存储第一个点

              //由于第一个点不一定是线段的起始位置,

              //因此两个方向都要查找

              Point currPt = firstPt;//当前点

              int currFlag = 0;//标志

              Point nextPt;//下一个点

              int nextFlag;//下一点的标志

              while (findNextPoint(neighborPtVec, binaryImg, currPt, currFlag, nextPt, nextFlag))//一端

              {

                     line.push_back(nextPt);//压入队列

                     currPt = nextPt;

                     currFlag = nextFlag;

              }

              //找另一端

              currPt = firstPt;

              currFlag = 0;

              while (findNextPoint(neighborPtVec, binaryImg, currPt, currFlag, nextPt, nextFlag))

              {

                     line.push_front(nextPt);

                     currPt = nextPt;

                     currFlag = nextFlag;//邻域与中心像素的位置

              }

              if (line.size() > 10)

              {

                     outLines.push_back(line);

              }

       }

}

OpenCV:曲线的检测与提取-0

6、//主函数main:

//用deque<Point> 描述曲线

//随机取色画曲线

Scalar random_color(RNG& _rng)

{

       int icolor = (unsigned)_rng;

       return Scalar(icolor & 0xFF, (icolor >> 8) & 0xFF, (icolor >> 16) & 0xFF);

}

int main()

{

       Mat binaryImg = imread("1.jpg",0);

       vector<deque<Point>> lines;

       findLines(binaryImg, lines);

       cout << lines.size() << endl;

       //draw lines

       Mat draw_img;

       cvtColor(binaryImg,draw_img,CV_GRAY2BGR);

       RNG rng(123);

       Scalar color;

       for (int i = 0; i < lines.size(); i++)

       {

              color = random_color(rng);

              for (int j = 0; j < lines[i].size(); j++)

              {

                     draw_img.at<Vec3b>(lines[i][j]) = Vec3b(color[0], color[1], color[2]);

              }

       }

       imshow("draw_img", draw_img);

       imwrite("draw_img.jpg", draw_img);

       waitKey(0);

       return 0;

}

OpenCV:曲线的检测与提取-0

OpenCV:曲线的检测与提取-0

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢