龙空技术网

图像轮廓和分水岭算法

业余天王 107

前言:

目前我们对“vc轮廓算法”大概比较讲究,大家都需要知道一些“vc轮廓算法”的相关知识。那么小编也在网上网罗了一些有关“vc轮廓算法””的相关文章,希望姐妹们能喜欢,看官们一起来了解一下吧!

1. 寻找轮廓

findContours() 函数用于在二值图像中寻找轮廓。常与 drawContours() 函数配合使用;findContours() 函数检测到图像的轮廓后,就可以用 drawContours() 函数将检测到的轮廓绘制出来。

2. 绘制轮廓

drawContours() 函数用于在图像中绘制外部或内部轮廓。

3. 综合例子

利用图像平滑技术(blur ()函数)和边缘检测技术(canny()函数),根据滑动条,动态地检测出图形的轮廓。

例子代码:

#include<opencv2/opencv.hpp>#include<iostream>using namespace std;using namespace cv;Mat srcImg, grayImg,cannyOutImg;int ThreshValue = 80;int ThrashValueMax = 255;vector<vector<Point>> vContours;vector<Vec4i> vHierarchy;RNG rng(12345);void ThreshChange(int, void*);void test(){    srcImg = imread("home.jpg");    if (srcImg.empty())    {        cout << "could not load image...\n" << endl;    }    namedWindow("Original iamge", CV_WINDOW_NORMAL);    imshow("Original iamge", srcImg);    cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);    blur(grayImg, grayImg, Size(3, 3));    namedWindow("ThreshWindow", CV_WINDOW_NORMAL);    createTrackbar("canny_ThreshValue", "ThreshWindow", &ThreshValue, ThrashValueMax, ThreshChange);    ThreshChange(0, 0);}void ThreshChange(int, void*){    Canny(grayImg, cannyOutImg, ThreshValue, ThreshValue*2,3);    //寻找轮廓    findContours(cannyOutImg, vContours, vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));    //会出轮廓    Mat drawing = Mat::zeros(cannyOutImg.size(), CV_8UC3);    for (int i = 0; i < vContours.size(); i++)    {        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));        drawContours(drawing, vContours, i, color, 2, 8, vHierarchy, 0, Point());    }    imshow("ThreshWindow", drawing);}int main(){    test();    waitKey(0);    return 0;}

效果图:

4. 分水岭算法

例子代码:

#include<opencv2/opencv.hpp>#include<iostream>using namespace std;using namespace cv;Mat srcImg, maskImg, cannyOutImg;Point prevPt(-1, -1);//鼠标回调函数static void Mouse(int event, int x, int y, int flags, void*);static void ShowHelpText();  //提升用户操作函数void test(){    srcImg = imread("home.jpg");    if (srcImg.empty())    {        cout << "could not load image...\n" << endl;    }    //namedWindow("Original image", CV_WINDOW_NORMAL);    imshow("WindowOne", srcImg);    Mat srcImg2, grayImg;    srcImg.copyTo(srcImg2);    cvtColor(srcImg, maskImg, COLOR_BGR2GRAY);    cvtColor(maskImg, grayImg, COLOR_GRAY2BGR);    maskImg = Scalar::all(0);    setMouseCallback("WindowOne", Mouse, 0);  //鼠标回调函数    //轮询按键,进行处理    while (true)    {        int c = waitKey(0);        //按键值为 ESC ,退出        if ((char)c == 27)            break;        //按键值为 2 ,回复源图像        if ((char)c == '2')        {            maskImg = Scalar::all(0);            srcImg2.copyTo(srcImg);            imshow("image", srcImg);        }        //按键值为 1 或者空格 ,则进行处理        if ((char)c == '1' || (char)c == ' ')        {            //定义一些参数            int i, j, compCount = 0;              vector<vector<Point>> contours;            vector<Vec4i> hierarchy;            //寻找轮廓            findContours(maskImg, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);            //轮廓为空时的处理            if (contours.empty())                continue;            //复制掩膜            Mat maskImg2(maskImg.size(), CV_32S);            maskImg2 = Scalar::all(0);            //循环绘制出轮廓            for (int i = 0; i >= 0; i = hierarchy[i][0], compCount++)                drawContours(maskImg2, contours, i, Scalar::all(compCount+1), -1, 8, hierarchy, INT_MAX);                //compCount 为零时的处理                if (compCount == 0)                    continue;                    //生成随机颜色                    vector<Vec3b> colorTab;                    for (int j = 0; j < compCount; j++)                    {                        int b = theRNG().uniform(0, 255);                        int g = theRNG().uniform(0, 255);                        int r = theRNG().uniform(0, 255);                        colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));                    }                    //计算处理的时间                    double dTime = (double)getTickCount();                    watershed(srcImg2, maskImg2);                    dTime = (double)getTickCount() - dTime;                    cout << "\t处理时间为:" << dTime*1000. / getTickFrequency();                    //双层循坏,将分水岭图像遍历存入 watershedImg 中                    Mat watershedImg(maskImg2.size(), CV_8UC3);                    for (int i = 0; i < maskImg2.rows; i++)                        for (int j = 0; j < maskImg2.cols; j++)                        {                            int index = maskImg2.at<int>(i, j);                            if (index == -1)                                watershedImg.at<Vec3b>(i, j) = Vec3b(255, 255, 255);                            else if (index <= 0 || index > compCount)                                watershedImg.at<Vec3b>(i, j) = Vec3b(0, 0, 0);                            else                                watershedImg.at<Vec3b>(i, j) = colorTab[index - 1];                        }                        //混合灰度图像和分水岭效果图并显示最终的窗口                        watershedImg = watershedImg*0.5 + grayImg*0.5;                        imshow("watershed transform", watershedImg);            }    }}static void Mouse(int event, int x, int y, int flags, void*){    //处理鼠标不在窗口中的情况    if (x < 0 || x >= srcImg.cols || y < 0 || y >= srcImg.rows)        return;    //处理鼠标左键相关消息    if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))        prevPt = Point(-1, -1);    //处理鼠标左键按下并移动,绘制出白色线条    else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))    {        Point pt(x, y);        if (prevPt.x < 0)            prevPt = pt;        line(maskImg, prevPt, pt, Scalar::all(255), 5, 8, 0);        line(srcImg, prevPt, pt, Scalar::all(255), 5, 8, 0);        prevPt = pt;        imshow("WindowOne", srcImg);    }}static void ShowHelpText(){    cout << "请先用鼠标在图片窗口中标记出大致的区域" << endl;    cout << "然后再按键【1】或者【SPACE】启动算法" << endl;    cout << "按键【1】或者【SPACE】启动算法" << endl;    cout << "按键【2】- 恢复原始图像" << endl;    cout << "按键【ESC】- 退出程序" << endl;}int main(){    ShowHelpText();    test();    waitKey(0);    return 0;}

效果图:

标签: #vc轮廓算法