opencv c++获取轮廓

1、查找和绘制轮廓

findContours 会找到

vector<vector<cv::Point>> contours;
vector<Vec4i> hierarchy;

f4 = Mat::zeros(frame.rows, frame.cols, CV_8UC3);
f5 = Mat::zeros(frame.rows, frame.cols, CV_8UC3);

findContours(f2, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, cv::Point());

int idx=0;
for( ; idx >= 0; idx = hierarchy[idx][0] ){
    Scalar color( arc4random()&255, arc4random()&255, arc4random()&255 );
    drawContours( f4, contours, idx, color, CV_FILLED, LINE_8, hierarchy );
    drawContours( f5, contours, idx, color, 3, LINE_8, hierarchy );
}
//  drawContours(f5, contours, -1, {0,255,0}, CV_FILLED, LINE_8);

如果在空mat上绘制,先把mat的区域设置好,填充满黑色。

2、获得轮廓的矩形区域, 优化轮廓

获得轮廓

Moments m = moments(contours[idx]);

质心

int cx = int(m.m10/m.m00);
int cy = int(m.m01/m.m00);

面积 (面积小可以踢掉
m.m00
曲线优化 (epsilon百分比越低,越贴近原轮廓

vector<cv::Point> approxCurve;
double epsilon = 0.002*arcLength(contours[idx], true);
approxPolyDP(contours[idx], approxCurve, epsilon, true);
vector<vector<cv::Point>> poolApproxCurve;
poolApproxCurve.push_back(approxCurve);
drawContours( f5 , poolApproxCurve, 0, color, CV_FILLED, LINE_8 );

opencv c++获取轮廓_第1张图片

3、凸包 hull

将所有点囊括在内

convexHull(contours[idx], approxCurve,false,true);
for (int i=0; i<approxCurve.size(); i++) {
    circle(f3, approxCurve[i], 2, Scalar(255),30);
}

opencv c++获取轮廓_第2张图片
简化
opencv c++获取轮廓_第3张图片

4、获得外切矩形 和 最小外切矩形(带旋转

外框

cv::Rect r = boundingRect(approxCurve);
rectangle(f5, {r.x,r.y}, {r.x+r.width,r.y+r.height}, color,5);

旋转外框

cv::RotatedRect rr = minAreaRect(approxCurve);
Mat boxPoints2f,boxPointsCov;
boxPoints(rr, boxPoints2f);
boxPoints2f.assignTo(boxPointsCov,CV_32S);
polylines(f5, boxPointsCov, true,color,5);

opencv c++获取轮廓_第4张图片

5、获得外切圆 和 外切椭圆

外切圆

Point2f pot;
float radius;
minEnclosingCircle(approxCurve, pot, radius);
circle(f5, pot, radius, color,5);

外切椭圆

RotatedRect re = fitEllipse(approxCurve);
ellipse(f5, re, color,5);

opencv c++获取轮廓_第5张图片

6、拟合直线

Vec4f lineData;
fitLine(approxCurve, lineData, DIST_L2, 0, 0.01, 0.01);
int lefty = (-lineData[2]*lineData[1]/lineData[0])+lineData[3];
int righty = ((f5.cols-lineData[2])*lineData[1]/lineData[0])+lineData[3];
line(f5, cv::Point(f5.cols-1,righty),cv::Point(0,lefty), color, 10);

opencv c++获取轮廓_第6张图片

参考:OpenCV C++ 简单小技巧 - 轮廓 (14
参考:opencv学习之路(26)、轮廓查找与绘制(五)——最小外接矩形

7、轮廓提取

findContours发现轮廓

findContours(
InputOutputArray  binImg, //输入8bit图像,0值像素值不变,非0的像素看成1;(变为二值图像)
 OutputArrayOfArrays  contours,//输出找到的轮廓对象
OutputArray,  hierachy// 图像的拓扑结构
int mode, //轮廓返回的模式(RETR_TREE等)
int method,//发现方法(CHAIN_APPROX_SIMPLE等)
Point offset=Point()//轮廓像素的位移(默认没有位移(0, 0))
)

8、drawContours绘制轮廓

drawContours(
InputOutputArray  binImg, // 输出图像
 OutputArrayOfArrays  contours,//找到的全部轮廓对象
Int contourIdx//轮廓索引号
const Scalar & color,//绘制颜色
int  thickness,//绘制线宽
int  lineType ,//线的类型(默认8)
InputArray hierarchy,//拓扑结构图
int maxlevel,//最大层数(0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓)
Point offset=Point()//轮廓位移
)

示例:

#include
using namespace cv;

int main()
{
    Mat src,dst;
    src = imread("E:/image/image/shape.jpg");
    if(src.empty())
    {
        printf("can not load image \n");
        return -1;
    }
    namedWindow("input", CV_WINDOW_AUTOSIZE);
    imshow("input", src);
    dst = Mat::zeros(src.size(), CV_8UC3);

    blur(src,src,Size(3,3));
    cvtColor(src,src,COLOR_BGR2GRAY);
    Canny(src, src, 20, 80, 3, false);
    std::vector<std::vector<Point>> contours;
    std::vector<Vec4i> hierarchy;
    findContours(src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    RNG rng(0);
    for(int i = 0; i < contours.size(); i++)
    {
        Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
        drawContours(dst, contours, i, color, 2, 8, hierarchy, 0, Point(0,0));
    }
    namedWindow("output", CV_WINDOW_AUTOSIZE);
    imshow("output",dst);
    waitKey();
    return 0;
}

opencv c++获取轮廓_第7张图片
opencv c++获取轮廓_第8张图片

参考:opencv3/C++轮廓的提取与筛选

参考:【OpenCV(C++)】查找并绘制图像轮廓

你可能感兴趣的:(C++,opencv)