沿着明亮的像素拟合线条

时间:2015-12-09 19:07:56

标签: computer-vision opencv3.0 data-fitting

我正在尝试检测短的"细丝"在图像中,通过在亮像素簇的最长轴上拟合线。有没有办法使用可用计算机视觉库(即OpenCV)的工具来做到这一点?

Intended result

1 个答案:

答案 0 :(得分:1)

你可以:

  1. 使用findContours
  2. 查找每个连接的组件
  3. 使用minAreaRect
  4. 找到每个连接组件的最小方向边界框
  5. 画线(平行于最长边)穿过中心。
  6. 结果:

    enter image description here

    既然你提到过:

      

    我想将每个“blob”减少到具有属性的对象1)长度2)质心3)角度

    我将一些功能包含在课程Blob中。这是代码:

    #include <opencv2/opencv.hpp>
    #include <vector>
    using namespace std;
    using namespace cv;
    
    struct Blob
    {
        float _length;
        Point2f _centroid;
        float _angle;
    
        Blob(float length, const Point2f& centroid, float angle) :
            _length(length), _centroid(centroid), _angle(angle) {};
    
        Blob(const Blob& other) :
            _length(other._length), _centroid(other._centroid), _angle(other._angle) {};
    
        Blob(const RotatedRect& r)
        {
            _centroid = r.center;
            _angle = r.angle*CV_PI / 180.;
            _length = r.size.height;
            if (r.size.width >= r.size.height)
            {
                _angle = (CV_PI / 2.0) + _angle;
                _length = r.size.width;
            }
        }
    
        void draw(const Mat3b& img)
        {
            // Draw line
            Point2f p1, p2;
            float b = (float)cos(_angle)*0.5f;
            float a = (float)sin(_angle)*0.5f;
            p1.x = _centroid.x - a*_length;
            p1.y = _centroid.y + b*_length;
            p2.x = _centroid.x + a*_length;
            p2.y = _centroid.y - b*_length;
    
            line(img, p1, p2, Scalar(0,0,255));
        };
    };
    
    int main()
    {
        Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
    
        // Apply a threshold to remove JPEG artifacts
        Mat1b img2 = img > 200;
    
        // Prepare output image
        Mat3b result;
        cvtColor(img, result, COLOR_GRAY2BGR);
    
        // Apply a small border to take care of blobs on image boundary
        copyMakeBorder(img2, img2, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));
    
        // Find connected components
        vector<vector<Point>> contours;
        findContours(img2.clone(), contours, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
    
        // The vector of blobs
        vector<Blob> blobs;
    
        for (int i = 0; i < contours.size(); ++i)
        {
            // Account for border
            for (int j = 0; j < contours[i].size(); ++j)
            {
                contours[i][j] -= Point(1,1);
            }
    
            // Find minimum oriented bounding box
            RotatedRect r = minAreaRect(contours[i]);
    
            Blob b(r);
            b.draw(result);
    
            // Append to blobs
            blobs.push_back(b);
        }
    
        imshow("Result", result);
        waitKey();
    
        return 0;
    }