精华内容
下载资源
问答
  • 2022-03-31 11:02:08

    import cv2
    import numpy as np
    
    if __name__ == "__main__":
        orig = cv2.imread('mask.jpg', flags=cv2.IMREAD_COLOR)
        mask = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
        _, mask = cv2.threshold(mask, 200, 255, 0)
        image = orig.copy()
        contours, hierarchy = cv2.findContours(mask, mode=cv2.RETR_LIST, method=cv2.CHAIN_APPROX_SIMPLE)
        for c in contours:
            # 绘制轮廓
            image = cv2.drawContours(image, [c], 0, (255, 0, 0), 2)
            # 外接矩形框,没有方向角
            x, y, w, h = cv2.boundingRect(c)
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
            # 最小外接矩形框,有方向角
            rect = cv2.minAreaRect(c)
            print(rect)
            box = np.int0(cv2.boxPoints(rect))
            cv2.drawContours(image, [box], 0, (0, 0, 255), 2)
            # 绘制最小外接圆
            (x, y), radius = cv2.minEnclosingCircle(c)
            center = (int(x), int(y))
            radius = int(radius)
            cv2.circle(image, center, radius, (0, 255, 255), 2)
            # 用轮廓数据来拟合椭圆
            ellipse = cv2.fitEllipse(c)
            cv2.ellipse(image, ellipse, (255, 0, 255), 2)
            # 直线拟合
            rows, cols = image.shape[:2]
            [vx, vy, x, y] = cv2.fitLine(c, cv2.DIST_L2, 0, 0.01, 0.01)
            lefty = int((-x * vy / vx) + y)
            righty = int(((cols - x) * vy / vx) + y)
            image = cv2.line(image, (cols - 1, righty), (0, lefty), (0, 0, 255), 2)
            cv2.imshow("image", image)
            cv2.waitKey(0)
    

    原图

    更多相关内容
  • 使用opencv画出图形的最小外接矩形与最小外接圆,首先求出图形的轮廓,设有滚动条可以选择最佳阈值,然后画出图形的最小外接圆与最小外接矩形,算法的效果很好!
  • Opencv中求点集的最小外结矩使用方法minAreaRect,求点集的最小外接圆使用方法minEnclosingCircle。 minAreaRect方法原型: RotatedRect minAreaRect( InputArray points ); 输入参数points是所要求最小外结矩的...
  • 在使用OPENCV2.4.10时,对轮廓点集进行取最小外接圆操作,半径总是较实际值大。如下图:  (红色为点集,紫色为最小外接圆结果) 后来用OPENCV3.3.1时,想起来这个BUG,重新试了一下,对轮廓点集进行取最小外接圆...

    函数名:

    //! computes the minimal enclosing circle for a set of points
    CV_EXPORTS_W void minEnclosingCircle( InputArray points,
                                          CV_OUT Point2f& center, CV_OUT float& radius );
    
    

    在使用OPENCV2.4.10时,对轮廓点集进行取最小外接圆操作,半径总是较实际值大。如下图:

       (红色为点集,紫色为最小外接圆结果)


    后来用OPENCV3.3.1时,想起来这个BUG,重新试了一下,对轮廓点集进行取最小外接圆操作,半径正确。如下图

     (红色为点集,紫色为最小外接圆结果)




    展开全文
  • 主要为大家详细介绍了Opencv实现最小外接矩形和,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 本章内容: 1. 轮廓查找 2. 绘制轮廓 ...opencv.hpp> #include <math.h> int main(int argc, char *argv[]) { /* 本章内容: 1. 轮廓查找 */ cv::String fileName = "/home/wang/de...

    本章内容:


    1. 轮廓查找
    2. 绘制轮廓

    3. 凸包

    4.最小外接矩形

    5.最小外接圆

    6.最小外接椭圆

     

    1.搜索轮廓

    2.绘制轮廓

    输出结果

    3.凸包

    输出结果

    4.最小外接矩形

    输出结果

    5.最小外接圆

    输出结果:

    6. 最小外接椭圆

    输出结果

     

    代码


    #include <ostream>
    #include <opencv.hpp>
    #include <math.h>

    int main(int argc, char *argv[])
    {
        /*
         本章内容:
            1. 轮廓查找
            2. 绘制轮廓
            3. 凸包
            4.最小外接矩形
            5.最小外接圆
            6.最小外接椭圆
        */
        cv::String fileName = "/home/wang/dev/Image/QT.jpg";
        cv::String fileName1 = "/home/wang/dev/Image/hei.png";
        cv::Mat src = cv::imread(fileName);
        cv::Mat src1 = cv::imread(fileName1);
        if(src.data == NULL){
            printf("图像读入失败\n");
            return -1;
        }
        /* 轮廓查找
         * api接口: CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours,
                                  OutputArray hierarchy, int mode,
                                  int method, Point offset = Point());
            参数分析:
                @param contours. std::vector<std::vector<cv::Point> >
                @param hierarchy Optional output vector
                @param mode Contour retrieval mode, see #RetrievalModes
                @param method Contour approximation method, see #ContourApproximationModes
            enum RetrievalModes{
                    RETR_EXTERNAL  = 0,
                    RETR_LIST      = 1,
                    RETR_CCOMP     = 2,
                    RETR_TREE      = 3,
                    RETR_FLOODFILL = 4
                }
            enum ContourApproximationModes{
            enum ContourApproximationModes {
                    CHAIN_APPROX_NONE      = 1,
                    CHAIN_APPROX_SIMPLE    = 2,
                    CHAIN_APPROX_TC89_L1   = 3,
                    CHAIN_APPROX_TC89_KCOS = 4
                }
        */
        cv::imshow("src",src);
        cv::Mat dstCany;
        cv::Mat gray;
        cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
        cv::Canny(gray,dstCany,50,150);
        std::vector<std::vector<cv::Point>> contours;
        std::vector<cv::Vec4i> hierarchy;
        cv::findContours(dstCany,contours,hierarchy,cv::RETR_TREE,cv::CHAIN_APPROX_SIMPLE,cv::Point(0,0));
        cv::RNG rng(1234);
        cv::Mat dst(src.size(),src.type());
        /* 绘制轮廓
            api接口: CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
                                          int contourIdx, const Scalar& color,
                                          int thickness = 1, int lineType = LINE_8,
                                          InputArray hierarchy = noArray(),
                                          int maxLevel = INT_MAX, Point offset = Point() );
            参数分析:
                @param contourIdx Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
                @param color Color of the contours.
        */
        for(int i=0; i <contours.size();i++){
            cv::Scalar color = cv::Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
            cv::drawContours(dst,contours,i,color,4);
        }

        /* 3.凸包
         * api接口:CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,
                                  bool clockwise = false, bool returnPoints = true );
                @param points 二维点集,vector
                @param hull Output convex hull. vector<Point>
        */
        std::vector<cv::Point> hull;
        cv::convexHull(contours[0],hull);
        for(int i=0;i<hull.size();i++){
            cv::line(dst,hull[i],hull[(i+1)%hull.size()],cv::Scalar(0,255,0),4);
        }


        /* 4.最小外接矩形
            apie接口: CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );
        */
        cv::RotatedRect rect = cv::minAreaRect(contours[1]);
        cv::Point2f Ps[4];
        rect.points(Ps);
        for(int i=0;i<4;i++) cv::line(dst,Ps[i],Ps[(i+1)%4],cv::Scalar(0,0,255),4);

        /* 5.最小外接圆
         * api接口: CV_EXPORTS_W void minEnclosingCircle( InputArray points,
                                          CV_OUT Point2f& center, CV_OUT float& radius );
        */
        cv::Point2f pc;
        float radius;
        cv::minEnclosingCircle(contours[2],pc,radius);
        cv::circle(dst,pc,radius,cv::Scalar(255,0,0),4);

        /*6.最小外接椭圆
         * api接口:CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );
        */
        cv::RotatedRect ell = cv::fitEllipse(contours[1]);
        cv::ellipse(dst,ell,cv::Scalar(0,255,255),4);

        cv::imshow("dst",dst);
        cv::waitKey(0);
        return 1;
    }

     

     

    展开全文
  • 计算最小外接圆函数,输出圆心坐标及圆的半径 计算最小外接三角形 二、boundingRect函数 该函数计算并返回灰度图像的指定点集或非零像素的最小上边界矩形。 2、源码代码 三、MinAreaRect函数 ...

    一、函数原型

            计算点集或灰度图像的非零像素的直立边界矩形。

    Rect 	cv::boundingRect (InputArray array)

            计算最小外接矩形函数

    RotatedRect 	cv::minAreaRect (InputArray points)

            计算最小外接圆函数,输出圆心坐标及圆的半径 

    void 	cv::minEnclosingCircle (InputArray points, Point2f &center, float &radius)

            计算最小外接三角形 

    double 	cv::minEnclosingTriangle (InputArray points, OutputArray triangle)

            拟合椭圆

    RotatedRect 	cv::fitEllipse (InputArray points)

    二、boundingRect函数

            该函数计算并返回灰度图像的指定点集或非零像素的最小上边界矩形。

    1、源码路径

    opencv\modules\imgproc\src\shapedescr.cpp

    2、源码代码 

    static Rect maskBoundingRect( const Mat& img )
    {
        CV_Assert( img.depth() <= CV_8S && img.channels() == 1 );
    
        Size size = img.size();
        int xmin = size.width, ymin = -1, xmax = -1, ymax = -1, i, j, k;
    
        for( i = 0; i < size.height; i++ )
        {
            const uchar* _ptr = img.ptr(i);
            const uchar* ptr = (const uchar*)alignPtr(_ptr, 4);
            int have_nz = 0, k_min, offset = (int)(ptr - _ptr);
            j = 0;
            offset = MIN(offset, size.width);
            for( ; j < offset; j++ )
                if( _ptr[j] )
                {
                    have_nz = 1;
                    break;
                }
            if( j < offset )
            {
                if( j < xmin )
                    xmin = j;
                if( j > xmax )
                    xmax = j;
            }
            if( offset < size.width )
            {
                xmin -= offset;
                xmax -= offset;
                size.width -= offset;
                j = 0;
                for( ; j <= xmin - 4; j += 4 )
                    if( *((int*)(ptr+j)) )
                        break;
                for( ; j < xmin; j++ )
                    if( ptr[j] )
                    {
                        xmin = j;
                        if( j > xmax )
                            xmax = j;
                        have_nz = 1;
                        break;
                    }
                k_min = MAX(j-1, xmax);
                k = size.width - 1;
                for( ; k > k_min && (k&3) != 3; k-- )
                    if( ptr[k] )
                        break;
                if( k > k_min && (k&3) == 3 )
                {
                    for( ; k > k_min+3; k -= 4 )
                        if( *((int*)(ptr+k-3)) )
                            break;
                }
                for( ; k > k_min; k-- )
                    if( ptr[k] )
                    {
                        xmax = k;
                        have_nz = 1;
                        break;
                    }
                if( !have_nz )
                {
                    j &= ~3;
                    for( ; j <= k - 3; j += 4 )
                        if( *((int*)(ptr+j)) )
                            break;
                    for( ; j <= k; j++ )
                        if( ptr[j] )
                        {
                            have_nz = 1;
                            break;
                        }
                }
                xmin += offset;
                xmax += offset;
                size.width += offset;
            }
            if( have_nz )
            {
                if( ymin < 0 )
                    ymin = i;
                ymax = i;
            }
        }
    
        if( xmin >= size.width )
            xmin = ymin = 0;
        return Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1);
    }
    
    }
    
    cv::Rect cv::boundingRect(InputArray array)
    {
        CV_INSTRUMENT_REGION();
    
        Mat m = array.getMat();
        return m.depth() <= CV_8U ? maskBoundingRect(m) : pointSetBoundingRect(m);
    }

    三、MinAreaRect函数

            查找包含输入 2D 点集的最小区域的旋转矩形。

            该函数计算并返回指定点集的最小面积边界矩形(可能已旋转)。 开发人员应记住,当数据接近包含 Mat 元素边界时,返回的 RotatedRect 可能包含负索引。

    1、源码路径

    opencv\modules\imgproc\src\rotcalipers.cpp

    2、源码代码 

    cv::RotatedRect cv::minAreaRect( InputArray _points )
    {
        CV_INSTRUMENT_REGION();
    
        Mat hull;
        Point2f out[3];
        RotatedRect box;
    
        convexHull(_points, hull, false, true);
    
        if( hull.depth() != CV_32F )
        {
            Mat temp;
            hull.convertTo(temp, CV_32F);
            hull = temp;
        }
    
        int n = hull.checkVector(2);
        const Point2f* hpoints = hull.ptr<Point2f>();
    
        if( n > 2 )
        {
            rotatingCalipers( hpoints, n, CALIPERS_MINAREARECT, (float*)out );
            box.center.x = out[0].x + (out[1].x + out[2].x)*0.5f;
            box.center.y = out[0].y + (out[1].y + out[2].y)*0.5f;
            box.size.width = (float)std::sqrt((double)out[1].x*out[1].x + (double)out[1].y*out[1].y);
            box.size.height = (float)std::sqrt((double)out[2].x*out[2].x + (double)out[2].y*out[2].y);
            box.angle = (float)atan2( (double)out[1].y, (double)out[1].x );
        }
        else if( n == 2 )
        {
            box.center.x = (hpoints[0].x + hpoints[1].x)*0.5f;
            box.center.y = (hpoints[0].y + hpoints[1].y)*0.5f;
            double dx = hpoints[1].x - hpoints[0].x;
            double dy = hpoints[1].y - hpoints[0].y;
            box.size.width = (float)std::sqrt(dx*dx + dy*dy);
            box.size.height = 0;
            box.angle = (float)atan2( dy, dx );
        }
        else
        {
            if( n == 1 )
                box.center = hpoints[0];
        }
    
        box.angle = (float)(box.angle*180/CV_PI);
        return box;
    }

    四、MinEnclosingTriangle函数

            找到包含 2D 点集的最小面积三角形并返回其面积。

            该函数找到一个包含给定二维点集的最小面积三角形并返回其面积。 给定 2D 点集的输出如下图所示。 2D 点用红色* 表示,封闭的三角形用黄色表示。

            该算法的实现基于 O'Rourke 以及 Klee 和 Laskowski 的论文。 O'Rourke 提供了一种 θ(n) 算法,用于找到具有 n 个顶点的 2D 凸多边形的最小封闭三角形。 由于 minEnclosureTriangle 函数将 2D 点集作为输入,因此需要额外的预处理步骤来计算 2D 点集的凸包。 凸包函数的复杂度为 O(nlog(n)),高于 θ(n)。 因此函数的整体复杂度为 O(nlog(n))。

    1、源码路径

    opencv\modules\imgproc\src\min_enclosing_triangle.cpp

    2、源码代码 

    double cv::minEnclosingTriangle(cv::InputArray points, CV_OUT cv::OutputArray triangle) {
        double area;
    
        minEnclosingTriangle::findMinEnclosingTriangle(points, triangle, area);
    
        return area;
    }
    
    static void findMinEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
                                         std::vector<cv::Point2f> &triangle, double &area) {
        initialise(triangle, area);
    
        if (polygon.size() > 3) {
            findMinimumAreaEnclosingTriangle(polygon, triangle, area);
        } else {
            returnMinimumAreaEnclosingTriangle(polygon, triangle, area);
        }
    }
    
    static void findMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
                                                 std::vector<cv::Point2f> &triangle, double &area) {
        // Algorithm specific variables
    
        unsigned int validationFlag;
    
        cv::Point2f vertexA, vertexB, vertexC;
    
        cv::Point2f sideAStartVertex, sideAEndVertex;
        cv::Point2f sideBStartVertex, sideBEndVertex;
        cv::Point2f sideCStartVertex, sideCEndVertex;
    
        unsigned int a, b, c;
        unsigned int nrOfPoints;
    
        // Variables initialisation
    
        nrOfPoints = static_cast<unsigned int>(polygon.size());
    
        a = 1;
        b = 2;
    
        // Main algorithm steps
    
        for (c = 0; c < nrOfPoints; c++) {
            advanceBToRightChain(polygon, nrOfPoints, b, c);
            moveAIfLowAndBIfHigh(polygon, nrOfPoints, a, b, c);
            searchForBTangency(polygon, nrOfPoints, a ,b, c);
    
            updateSidesCA(polygon, nrOfPoints, a, c, sideAStartVertex, sideAEndVertex,
                          sideCStartVertex, sideCEndVertex);
    
            if (isNotBTangency(polygon, nrOfPoints, a, b, c)) {
                updateSidesBA(polygon, nrOfPoints, a, b, c, validationFlag, sideAStartVertex,
                              sideAEndVertex, sideBStartVertex, sideBEndVertex,
                              sideCStartVertex, sideCEndVertex);
            } else {
                updateSideB(polygon, nrOfPoints, a, b, c, validationFlag,
                            sideBStartVertex,  sideBEndVertex);
            }
    
            if (isLocalMinimalTriangle(vertexA, vertexB, vertexC, polygon, nrOfPoints, a, b,
                                       validationFlag, sideAStartVertex, sideAEndVertex,
                                       sideBStartVertex, sideBEndVertex, sideCStartVertex,
                                       sideCEndVertex)) {
                updateMinimumAreaEnclosingTriangle(triangle, area, vertexA, vertexB, vertexC);
            }
        }
    }
    
    static void returnMinimumAreaEnclosingTriangle(const std::vector<cv::Point2f> &polygon,
                                                   std::vector<cv::Point2f> &triangle, double &area) {
        unsigned int nrOfPoints = static_cast<unsigned int>(polygon.size());
    
        for (int i = 0; i < 3; i++) {
            triangle.push_back(polygon[i % nrOfPoints]);
        }
    
        area = areaOfTriangle(triangle[0], triangle[1], triangle[2]);
    }

    五、minEnclosingCircle 函数

            查找包含 2D 点集的最小面积的圆。该函数使用迭代算法找到 2D 点集的最小封闭圆。

    1、源码路径 

    opencv\modules\imgproc\src\shapedescr.cpp

    2、源码代码 

    void cv::minEnclosingCircle( InputArray _points, Point2f& _center, float& _radius )
    {
        CV_INSTRUMENT_REGION();
    
        Mat points = _points.getMat();
        int count = points.checkVector(2);
        int depth = points.depth();
        CV_Assert(count >= 0 && (depth == CV_32F || depth == CV_32S));
    
        _center.x = _center.y = 0.f;
        _radius = 0.f;
    
        if( count == 0 )
            return;
    
        bool is_float = depth == CV_32F;
        const Point* ptsi = points.ptr<Point>();
        const Point2f* ptsf = points.ptr<Point2f>();
    
        switch (count)
        {
            case 1:
            {
                _center = (is_float) ? ptsf[0] : Point2f((float)ptsi[0].x, (float)ptsi[0].y);
                _radius = EPS;
                break;
            }
            case 2:
            {
                Point2f p1 = (is_float) ? ptsf[0] : Point2f((float)ptsi[0].x, (float)ptsi[0].y);
                Point2f p2 = (is_float) ? ptsf[1] : Point2f((float)ptsi[1].x, (float)ptsi[1].y);
                _center.x = (p1.x + p2.x) / 2.0f;
                _center.y = (p1.y + p2.y) / 2.0f;
                _radius = (float)(norm(p1 - p2) / 2.0) + EPS;
                break;
            }
            default:
            {
                Point2f center;
                float radius = 0.f;
                if (is_float)
                {
                    findMinEnclosingCircle<Point2f>(ptsf, count, center, radius);
                    #if 0
                        for (size_t m = 0; m < count; ++m)
                        {
                            float d = (float)norm(ptsf[m] - center);
                            if (d > radius)
                            {
                                printf("error!\n");
                            }
                        }
                    #endif
                }
                else
                {
                    findMinEnclosingCircle<Point>(ptsi, count, center, radius);
                    #if 0
                        for (size_t m = 0; m < count; ++m)
                        {
                            double dx = ptsi[m].x - center.x;
                            double dy = ptsi[m].y - center.y;
                            double d = std::sqrt(dx * dx + dy * dy);
                            if (d > radius)
                            {
                                printf("error!\n");
                            }
                        }
                    #endif
                }
                _center = center;
                _radius = radius;
                break;
            }
        }
    }

    六、fitEllipse函数 

            围绕一组 2D 点拟合椭圆。

    1、源码路径 

    opencv\modules\imgproc\src\shapedescr.cpp

    2、源码代码 

    static RotatedRect fitEllipseNoDirect( InputArray _points )
    {
        CV_INSTRUMENT_REGION();
    
        Mat points = _points.getMat();
        int i, n = points.checkVector(2);
        int depth = points.depth();
        CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));
    
        RotatedRect box;
    
        if( n < 5 )
            CV_Error( CV_StsBadSize, "There should be at least 5 points to fit the ellipse" );
    
        // New fitellipse algorithm, contributed by Dr. Daniel Weiss
        Point2f c(0,0);
        double gfp[5] = {0}, rp[5] = {0}, t, vd[25]={0}, wd[5]={0};
        const double min_eps = 1e-8;
        bool is_float = depth == CV_32F;
    
        AutoBuffer<double> _Ad(n*12+n);
        double *Ad = _Ad.data(), *ud = Ad + n*5, *bd = ud + n*5;
        Point2f* ptsf_copy = (Point2f*)(bd + n);
    
        // first fit for parameters A - E
        Mat A( n, 5, CV_64F, Ad );
        Mat b( n, 1, CV_64F, bd );
        Mat x( 5, 1, CV_64F, gfp );
        Mat u( n, 1, CV_64F, ud );
        Mat vt( 5, 5, CV_64F, vd );
        Mat w( 5, 1, CV_64F, wd );
    
        {
        const Point* ptsi = points.ptr<Point>();
        const Point2f* ptsf = points.ptr<Point2f>();
        for( i = 0; i < n; i++ )
        {
            Point2f p = is_float ? ptsf[i] : Point2f((float)ptsi[i].x, (float)ptsi[i].y);
            ptsf_copy[i] = p;
            c += p;
        }
        }
        c.x /= n;
        c.y /= n;
    
        double s = 0;
        for( i = 0; i < n; i++ )
        {
            Point2f p = ptsf_copy[i];
            p -= c;
            s += fabs(p.x) + fabs(p.y);
        }
        double scale = 100./(s > FLT_EPSILON ? s : FLT_EPSILON);
    
        for( i = 0; i < n; i++ )
        {
            Point2f p = ptsf_copy[i];
            p -= c;
            double px = p.x*scale;
            double py = p.y*scale;
    
            bd[i] = 10000.0; // 1.0?
            Ad[i*5] = -px * px; // A - C signs inverted as proposed by APP
            Ad[i*5 + 1] = -py * py;
            Ad[i*5 + 2] = -px * py;
            Ad[i*5 + 3] = px;
            Ad[i*5 + 4] = py;
        }
    
        SVDecomp(A, w, u, vt);
        if(wd[0]*FLT_EPSILON > wd[4]) {
            float eps = (float)(s/(n*2)*1e-3);
            for( i = 0; i < n; i++ )
            {
                Point2f p = ptsf_copy[i] + getOfs(i, eps);
                ptsf_copy[i] = p;
            }
    
            for( i = 0; i < n; i++ )
            {
                Point2f p = ptsf_copy[i];
                p -= c;
                double px = p.x*scale;
                double py = p.y*scale;
                bd[i] = 10000.0; // 1.0?
                Ad[i*5] = -px * px; // A - C signs inverted as proposed by APP
                Ad[i*5 + 1] = -py * py;
                Ad[i*5 + 2] = -px * py;
                Ad[i*5 + 3] = px;
                Ad[i*5 + 4] = py;
            }
            SVDecomp(A, w, u, vt);
        }
        SVBackSubst(w, u, vt, b, x);
    
        // now use general-form parameters A - E to find the ellipse center:
        // differentiate general form wrt x/y to get two equations for cx and cy
        A = Mat( 2, 2, CV_64F, Ad );
        b = Mat( 2, 1, CV_64F, bd );
        x = Mat( 2, 1, CV_64F, rp );
        Ad[0] = 2 * gfp[0];
        Ad[1] = Ad[2] = gfp[2];
        Ad[3] = 2 * gfp[1];
        bd[0] = gfp[3];
        bd[1] = gfp[4];
        solve( A, b, x, DECOMP_SVD );
    
        // re-fit for parameters A - C with those center coordinates
        A = Mat( n, 3, CV_64F, Ad );
        b = Mat( n, 1, CV_64F, bd );
        x = Mat( 3, 1, CV_64F, gfp );
        for( i = 0; i < n; i++ )
        {
            Point2f p = ptsf_copy[i];
            p -= c;
            double px = p.x*scale;
            double py = p.y*scale;
            bd[i] = 1.0;
            Ad[i * 3] = (px - rp[0]) * (px - rp[0]);
            Ad[i * 3 + 1] = (py - rp[1]) * (py - rp[1]);
            Ad[i * 3 + 2] = (px - rp[0]) * (py - rp[1]);
        }
        solve(A, b, x, DECOMP_SVD);
    
        // store angle and radii
        rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert from APP angle usage
        if( fabs(gfp[2]) > min_eps )
            t = gfp[2]/sin(-2.0 * rp[4]);
        else // ellipse is rotated by an integer multiple of pi/2
            t = gfp[1] - gfp[0];
        rp[2] = fabs(gfp[0] + gfp[1] - t);
        if( rp[2] > min_eps )
            rp[2] = std::sqrt(2.0 / rp[2]);
        rp[3] = fabs(gfp[0] + gfp[1] + t);
        if( rp[3] > min_eps )
            rp[3] = std::sqrt(2.0 / rp[3]);
    
        box.center.x = (float)(rp[0]/scale) + c.x;
        box.center.y = (float)(rp[1]/scale) + c.y;
        box.size.width = (float)(rp[2]*2/scale);
        box.size.height = (float)(rp[3]*2/scale);
        if( box.size.width > box.size.height )
        {
            float tmp;
            CV_SWAP( box.size.width, box.size.height, tmp );
            box.angle = (float)(90 + rp[4]*180/CV_PI);
        }
        if( box.angle < -180 )
            box.angle += 360;
        if( box.angle > 360 )
            box.angle -= 360;
    
        return box;
    }
    }
    
    cv::RotatedRect cv::fitEllipse( InputArray _points )
    {
        CV_INSTRUMENT_REGION();
    
        Mat points = _points.getMat();
        int n = points.checkVector(2);
        return n == 5 ? fitEllipseDirect(points) : fitEllipseNoDirect(points);
    }

    七、示例图像

            下面的参考代码是MinEnclosingCircle函数,类似功能的还有诸如approxPolyDP(逼近多边形曲线函数)、fitEllipse(椭圆拟合函数等),基本都是找轮廓,利用轮廓的点集合进行寻找和绘制。

    this.mat = Cv2.ImRead("pictures\\kl.jpg");
        Mat temp = new Mat();
        //灰度化
        Cv2.CvtColor(mat, temp, ColorConversionCodes.BGR2GRAY);
        //二值化
        Cv2.Threshold(temp, temp, 0, 255, ThresholdTypes.Otsu);
    
        //寻找轮廓            
        OpenCvSharp.Point[][] contours;
        HierarchyIndex[] hierachy;
        Cv2.FindContours(temp, out contours, out hierachy, RetrievalModes.List, ContourApproximationModes.ApproxNone);
    
        //循环进行绘制
        Point2f center;  //定义圆中心坐标
        float radius;  //定义圆半径
        for (int i = 0; i < contours.Length; i++)  //依次遍历每个轮廓
        {
            if(this.radioButton1.Checked)
            {
                //寻找最小外接圆,输出中心点和半径
                Cv2.MinEnclosingCircle(contours[i], out center, out radius);
                            
                //绘制外接圆
                Cv2.Circle(mat, (int)center.X, (int)center.Y, (int)radius, new Scalar(0, 255, 0), 2, LineTypes.Link8);  //绘制第i个轮廓的最小外接圆
            }
            else if(this.radioButton2.Checked)
            {
                RotatedRect rotatedRect = Cv2.MinAreaRect(contours[i]);
                //绘制轮廓
                Cv2.DrawContours(mat, contours, i, new Scalar(0, 0, 255), 2, LineTypes.Link8);
                List<List<OpenCvSharp.Point>> list = new List<List<OpenCvSharp.Point>>();
                List<OpenCvSharp.Point> listc = new List<OpenCvSharp.Point>();
                foreach(OpenCvSharp.Point p in rotatedRect.Points())
                {
                    listc.Add(p);
                }
                list.Add(listc);
                Cv2.Polylines(mat, list, true, new Scalar(0, 255, 0), 2);
            }
            else if (this.radioButton3.Checked)
            {
                Point2f[] triangle;
                Cv2.MinEnclosingTriangle(contours[i], out triangle);
                //绘制轮廓
                Cv2.DrawContours(mat, contours, i, new Scalar(0, 0, 255), 2, LineTypes.Link8);
                List<List<OpenCvSharp.Point>> list = new List<List<OpenCvSharp.Point>>();
                List<OpenCvSharp.Point> listc = new List<OpenCvSharp.Point>();
                foreach (OpenCvSharp.Point p in triangle)
                {
                    listc.Add(p);
                }
                list.Add(listc);
                Cv2.Polylines(mat, list, true, new Scalar(0, 255, 0), 2);
            }
        }
        this.pictureBox1.Image = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
    原图

    二值图
    最小外接直立矩形
    最小外接圆​​​​
    最小外接矩形
    最小外接三角形
    拟合椭圆

     

    展开全文
  • # 最小外接圆 (x, y), radius = cv2.minEnclosingCircle(cnt) center = (int(x), int(y)) radius = int(radius) cv2.circle(im, center, radius, (255, 0, 0), 2) # 椭圆拟合 ellipse = cv2.fitEllipse(cnt)...
  • OpenCV python 轮廓(连通域)最小外接圆形 原图:[cc.jpg] import cv2 import numpy as np def main(): # 1.导入图片 img_src = cv2.imread("cc.jpg") # 2.灰度化,二值化 img_gray = cv2.cvtColor(img_src, ...
  • 目录一、绘制最小外接矩形1.1 函数API1.2 程序设计1.3 结果可视化二、绘制最小外接圆形2.1 函数API2.2 程序设计2.3 结果可视化 一、绘制最小外接矩形 1.1 函数API 函数:rect = cv2.minAreaRect(contours) 参数介绍...
  • 包含多个区域的最小外接矩形''' image = cv2.imread('./label.png') B, G, R = cv2.split(image) ret, thresh = cv2.threshold(G, 128, 255, cv2.THRESH_BINARY) print(thresh.shape) # 单通道复制为三通道 ...代替...
  • OpenCV4查找绘制点集的最小外接矩形、最小外接圆、最小外接三角形 C++代码: #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <iostream> using namespace cv; using namespace ...
  • 最小外接圆函数原型—minEnclosingCircle()void minEnclosingCircle( InputArray points, CV_OUT Point2f& center, CV_OUT float& radius );points: 输入的二维点集, 可以填Mat类型或std::vector center: Point2f&...
  • Opencv绘制最小外接矩形、最小外接圆 Opencv中求点集的最小外结矩使用方法minAreaRect,求点集的最小外接圆使用方法minEnclosingCircle。 minAreaRect方法原型: RotatedRectminAreaRect(InputArraypoints); ...
  • 要获得轮廓的最小外矩形,必须首先获得轮廓的近似多边形。使用 Douglas-Puck 细化 (DP) 算法和 Douglas-Puck 细化算法。它是一种将曲线近似为一系列点并减少点数的算法。 该算法的细化过程如下: 1)虚构...
  • 内容:图像外接矩形、最小外接矩形、凸包、外接圆、拟合椭圆的绘制 import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 封装图片显示函数 def image_show(image): if image.ndim == 2: ...
  • 任务:给定这样一张图片求图片中白色区域的外接矩形、最小外接矩形、拟合多边形以及外接圆 外接矩形 x, y, w, h = cv2.boundingRect(points) 输入:点集 返回值:左上角点坐标以及宽高 实现代码: import cv2 ...
  • # 颜色空间转换 # img为要转换的图像,后者为转换的格式 # 颜色空间有很多种,最常见的就是RGB颜色空间 # R红色,G绿色,B蓝色,OpenCV中顺序是BGR!!!!!!! # [255, 0,0]是蓝色,[0, 255, 0]表示绿色,[0, 0...
  • src = cv::imread(“D:\QtProject\Opencv_Example\convexHull\convexHull.png”, cv::IMREAD_GRAYSCALE); if (src.empty()) { cout << “Cannot load image” << endl; return; } cv::imshow(“src”, ...
  • OpenCV中求点集的最小外接矩形使用方法 minAreaRect,求点集的最小外接圆使用方法 minEnclosingCircle。 minAreaRect方法原型: RotatedRect minAreaRect(InputArray points); 输入参数points是所要求最小外接...
  • OpenCV提供了函数approxPolyDP()、boundRect()、minEnclosingCircle()分别计算给定点集的外接多边形,最小立式矩形和最小外接圆,下面分别给出这三个函数的原型和参数意义。 approxPolyDP函数(计算外接多边形): ...
  • opencv-python最小外接矩形

    千次阅读 2021-05-06 18:18:02
    所用函数: ...cv2.minAreaRect —— 找到最小外接矩形(矩形具有一定的角度) cv2.boxPoints —— 外接矩形的坐标位置 cv2.drawContours(image, [box], 0, (0, 0, 255), 3) —— 根据点画出矩形 # -*- cod
  • opencv-python 最小外接矩形

    千次阅读 2020-02-03 23:01:36
    opencv—python 最小外接矩形 (编程小白,如有问题还请各位大佬多指教) 所用函数: cv2.threshold() —— 阈值处理 cv2.findContours() —— 轮廓检测 cv2.boundingRect() —— 最大外接矩阵 cv2.rectangle() ——...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,182
精华内容 472
关键字:

opencv最小外接圆