围绕像素坐标计算矩形

时间:2016-02-09 08:05:17

标签: c++ qt opencv blobs

我有一个包含图像像素坐标的Qvector。主要目标是将这些像素与彼此的距离进行分组,并从这些像素组中获取矩形。向量中的每个像素彼此不相近,这就是我想将它们分组的原因。

我正在使用openCv和Qt。我想避免使用OpenCV中的blobDetector这是非常慢的,如果可能的话,我自己做这个。

有人知道如何管理这个吗?

修改

让我们说白点是彼此接近的像素。主要目标是检测这些像素彼此接近并且能够获得这些像素的矩形。这可能吗?

enter image description here

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)));
}

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

这首先是集群问题。由于您不知道群集(组)的数量,因此必须使用一些不需要群集数量作为输入的算法。你可以做简单的gains from it,它在C ++中有以下签名:

    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;
    });

使用它的示例:

cv::boundingRect

另一个更成熟的选择是使用真正的聚类算法,如cv::partition。这是一种基于密度的聚类算法。你可以找到一个C ++ DBSCAN

获得群集后(在任何方法中)只需在每个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)); }

修改

解决矩形问题:

<md-input-container flex>
    <label>Length</label>
    <input type="number" ng-model="length" flex="80">
    <span flex>seconds</span>
</md-input-container>

我确信有更好更快的方法,我只是在解释这个想法,你可以尽可能地优化它。

答案 1 :(得分: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,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2, 2,2]