计算像素坐标周围的矩形
Computing rectangle around pixel coordinates
我有一个包含图像像素坐标的 Qvector。主要目标是根据彼此之间的距离对这些像素进行分组,并从这些像素组中得到一个矩形。矢量中的每个像素都彼此不靠近,这就是我想将它们分组的原因。
我正在使用 openCv 和 Qt。我想避免使用 OpenCV 中的 blobDetector,它非常慢,如果可能的话,我自己做。
有人知道如何管理这个吗?
编辑:
假设白点彼此像素接近。主要的 objective 将是检测这些像素彼此靠近并能够获得这些像素的矩形。这可能吗?
编辑2:
获得集群后,我尝试使用以下代码获取这些集群周围的边界矩形。我可能没有以正确的方式使用这个功能。
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)));
}
感谢您的帮助
这首先是聚类问题。由于您不知道集群(组)的数量,因此您必须使用一些不需要集群数量作为输入的算法。您可以执行简单的 cv::partition,它在 C++ 中具有以下签名:
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;
});
另一个更成熟的选择是使用真正的聚类算法,如 DBSCAN. Which is a density based clustering algorithm. and you can find a C++ implementation here。
获得簇后(以任何方法)只需在每个 cluster
周围应用 cv::boundingRect
即可获得所需的 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));
}
我相信有更好更快的方法,我只是在解释这个想法,你可以优化它。
@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]
我有一个包含图像像素坐标的 Qvector。主要目标是根据彼此之间的距离对这些像素进行分组,并从这些像素组中得到一个矩形。矢量中的每个像素都彼此不靠近,这就是我想将它们分组的原因。
我正在使用 openCv 和 Qt。我想避免使用 OpenCV 中的 blobDetector,它非常慢,如果可能的话,我自己做。
有人知道如何管理这个吗?
编辑:
假设白点彼此像素接近。主要的 objective 将是检测这些像素彼此靠近并能够获得这些像素的矩形。这可能吗?
编辑2:
获得集群后,我尝试使用以下代码获取这些集群周围的边界矩形。我可能没有以正确的方式使用这个功能。
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)));
}
感谢您的帮助
这首先是聚类问题。由于您不知道集群(组)的数量,因此您必须使用一些不需要集群数量作为输入的算法。您可以执行简单的 cv::partition,它在 C++ 中具有以下签名:
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;
});
另一个更成熟的选择是使用真正的聚类算法,如 DBSCAN. Which is a density based clustering algorithm. and you can find a C++ implementation here。
获得簇后(以任何方法)只需在每个 cluster
周围应用 cv::boundingRect
即可获得所需的 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));
}
我相信有更好更快的方法,我只是在解释这个想法,你可以优化它。
@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]