2015-12-09 76 views
0

我試圖通過擬合明亮像素簇的最長軸上的線來檢測圖像中的短「細絲」。有沒有辦法使用可用的計算機視覺庫(即OpenCV)的工具來做到這一點?沿着明像素的擬合線

Intended result

+0

你能提供一幅圖像和預期的結果嗎?你想要一條直線嗎?這些線是否需要完全放在blob內? – Miki

+0

(見編輯)。直線很好,我不想做多項式擬合。理想情況下,我想將每個「斑點」減少到具有以下屬性的對象:1)長度2)質心3)角度(相對於x軸)。我希望開發一種隨着時間的推移,隨着這些斑點的增長而開發的工具。 – batlike

回答

1

用戶可以:

  1. 找到每個連接的組件,與findContours
  2. 找到每個連接的組件的最小方向包圍盒,具有minAreaRect
  3. 畫線(平行於最長的一邊)通過中心。

結果:

enter image description here

既然你提到:

我想每個 「斑點」 減少到與屬性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; 
} 
+0

謝謝Mik!這太棒了! – batlike