沿明亮像素拟合线条

Fitting lines along bright pixels

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

您可以:

  1. 找到每个连通分量,findContours
  2. 找到每个连通分量的最小定向边界框,minAreaRect
  3. 画一条通过中心的线(平行于最长边)。

结果:

既然你提到了:

I'd like to reduce each "blob" to an object with the attributes 1) length 2) centroid 3) angle

我将一些功能封装到 class 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;
}