1

画像のピクセル座標を含む Qvector があります。主な目標は、これらのピクセルを相互の距離に関してグループ化し、それらのピクセルのグループから長方形を取得することです。ベクトル内のすべてのピクセルは互いに近接していないため、それらをグループ化したいと考えています。

私はopenCvとQtを使用しています。私は非常に遅い OpenCV から blobDetector を避けたいと思います。それが可能であれば、自分でこれを行います。

これを管理する方法を知っている人はいますか?

編集:

白い点が互いにピクセルに近いとしましょう。主な目的は、これらのピクセルが互いに近接していることを検出し、それらのピクセルの長方形を取得できるようにすることです。これは可能ですか?

ここに画像の説明を入力

EDIT2:

クラスターを取得した後、次のコードを使用して、それらのクラスターの周囲の境界四角形を取得しようとしました。この関数を正しい方法で使用していない可能性があります。

cv::partition(cvCoordsTable, testVector, Dist(eqludianThreshold));
std::vector<cv::Rect> rectTable;

for(int in = 0; in < testVector.size(); in++)
{
    rectTable.push_back(cv::boundingRect(cvCoordsTable.at(in)));
}

ご協力ありがとうございました

4

2 に答える 2

3

これはそもそもクラスタリングの問題です。クラスター (グループ) の数がわからないため、入力としてクラスターの数を必要としないアルゴリズムを使用する必要があります。 C++ で次の署名を持つ単純なcv::partitionを実行できます。

int cv::partition(const vector<_Tp>& vec, vector<int>& labels, _EqPredicate predicate=_EqPredicate())

使用例:

    std::vector<cv::Point> pixelCoordinatesTable,
    std::vector<int> labelsTable;
    double threshold= 5;//Max eqludian distance between one cluster points
    cv::partition(pixelCoordinatesTable, labelsTable, [&threshold](auto const& l, auto const& r){
        return cv::norm(l - r))<threshold;
    });

もう 1 つのより成熟したオプションは、 DBSCANのような実際のクラスタリング アルゴリズムを使用することです。これは、密度ベースのクラスタリング アルゴリズムです。C++ の実装はこちらで確認できます。

(任意の方法で) クラスターを取得したら、cv::boundingRectそれぞれの周りに適用して、必要なclusterものを取得しrectangleます。

編集:

長方形の問題を解決するには:

auto cluster_count = cv::partition(cvCoordsTable, testVector, Dist(eqludianThreshold)); // gettting the number of clusters
std::vector<cv::Rect> rectTable;
rectTable.reserve(cluster_count);//Optimiaztion
for(int in = 0; in < cluster_count; in++){
    std::vector<cv::Point> temp;
    temp.reserve(testVector.size());
    for(size_t i=0;i<testVector.size();++i){
        if(testVector[i]==in){
             temp.emplace_back(rectTable[i]);
        }
    }
    rectTable.emplace_back(cv::boundingRect(temp));
}

私はアイデアを説明しただけで、できる限り最適化することができます。

于 2016-02-09T09:29:29.247 に答える
2

@Humam Helfawi はここで私を打ち負かしましたが、とにかく、中心点のリストを取得した場合は、cv::partition を使用して (教師なし) クラスタリングを実行します。

struct Dist
{
    double D;
    Dist(double d) : D(d) {}
    bool operator()(const Point &a, const Point &b)
    {
        return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) < D;
    }
};
vector<Point> centers; // e.g. from findContours -> boundingRect
vector<int> labels;
cv::partition(centers,labels,Dist(800));
cerr << Mat(labels).t() << endl;

[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ]

于 2016-02-09T09:46:11.750 に答える