zoukankan      html  css  js  c++  java
  • opencv:轮廓逼近与拟合

    轮廓逼近,本质上是减少编码点

    拟合圆,生成最相似的圆或椭圆

    #include <opencv2/opencv.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    RNG rng(12345);
    
    void fit_circle_demo(Mat &image);
    
    int main(int argc, char** argv)
    {
        //Mat src = imread("f:/images/qq/jihe.png");
        Mat src = imread("f:/images/qq/stuff.png");
        if (src.empty())
        {
            printf("Could not find the image!
    ");
            return -1;
        }
    
        namedWindow("input", WINDOW_AUTOSIZE);
        imshow("input", src);
    
        // 做一个高斯模糊,消除一些细微的东西
        GaussianBlur(src, src, Size(3, 3), 0);
    
        Mat gray, binary;
        cvtColor(src, gray, COLOR_BGR2GRAY);
        imshow("gray", gray);
    
        // 二值化
        threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
        imshow("binary", binary);
    
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        //findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
        // 只绘制最外层的轮廓
        findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
    
        fit_circle_demo(src);
        src = imread("f:/images/qq/stuff.png");
    
        //多边形逼近演示
        for (size_t t = 0; t < contours.size(); t++) {
            Moments mm = moments(contours[t]);
            // 计算每个轮廓的中心位置
            double cx = mm.m10 / mm.m00;
            double cy = mm.m01 / mm.m00;
            circle(src, Point(cx, cy), 3, Scalar(0, 255, 0), 2, 8, 0);
    
            double area = contourArea(contours[t]);
            double clen = arcLength(contours[t], true);
    
            Mat result;
            approxPolyDP(contours[t], result, 4, true);
            printf("corners: %d, colums: %d, contour area: %.2f, contour length: %.2f
    ", result.rows, result.cols, area, clen);
            if (result.rows == 6) {
                putText(src, "poly", Point(cx, cy-10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);
            }
            if (result.rows == 4) {
                putText(src, "rectangle", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);
            }
            if (result.rows == 3) {
                putText(src, "trangle", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);
            }
            if (result.rows > 10) {
                putText(src, "circle", Point(cx, cy - 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);
            }
        }
    
        imshow("result", src);
    
        waitKey(0);
        destroyAllWindows();
    
        return 0;
    }
    
    void fit_circle_demo(Mat& image) {
        Mat gray, binary;
        cvtColor(image, gray, COLOR_BGR2GRAY);
        // 二值化
        threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
        imshow("binary", binary);
    
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        //findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
        // 只绘制最外层的轮廓
        findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
    
        //拟合圆或者椭圆
        for (size_t t = 0; t < contours.size(); t++) {
            //drawContours(image, contours, t, Scalar(0, 0, 255), 2, 8);
            RotatedRect rrt = fitEllipse(contours[t]);
            float w = rrt.size.width;
            float h = rrt.size.height;
            Point center = rrt.center;
            circle(image, center, 3, Scalar(255, 0, 0), 2, 8, 0);
            ellipse(image, rrt, Scalar(0, 255, 0), 2, 8);
        }
        imshow("fit demo", image);
    }
    
  • 相关阅读:
    Linux-配置共享目录
    Linux-expect脚本-编写一个expect脚本
    MySQL-Linux下安装
    ETL-拉链算法-1
    ETL-拉链算法-带删除的拉链算法
    postgresql-基础-1
    Oracle-sql*plus
    【剑指offer11二进制中1的个数】
    【剑指offer10 矩形覆盖】
    【剑指offer080 09 跳台阶、变态跳台阶】
  • 原文地址:https://www.cnblogs.com/wbyixx/p/12323857.html
Copyright © 2011-2022 走看看