- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如何通过仅遍历整个列表一次来合并 vector 或类似数据结构中的某些元素?有没有比我现有的更有效的方法?
我有一个由点 vector 组成的 vector :std::vector<std::vector<cv::Point>> contours
而且我总是需要比较其中的两个,然后决定是要合并它们还是继续比较。
例如,ContourMoments 有一些辅助函数来计算点之间的距离。函数 merge()
仅从一个 ContourMoments 对象中获取所有点并将它们添加到调用 ContourMoments 对象。
#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc.hpp>
class ContourMoments
{
private:
void init()
{
moments = cv::moments(contour);
center = cv::Point2f(moments.m10 / moments.m00, moments.m01 / moments.m00);
float totalX = 0.0, totalY = 0.0;
for (auto const&p : contour)
{
totalX += p.x;
totalY += p.y;
}
gravitationalCenter = cv::Point2f(totalX / contour.size(), totalY / contour.size());
}
public:
cv::Moments moments;
std::vector<cv::Point2f> contour;
cv::Point2f center;
cv::Point2f gravitationalCenter;
ContourMoments(const std::vector<cv::Point2f> &c)
{
contour = c;
init();
}
ContourMoments(const ContourMoments &cm)
{
contour = cm.contour;
init();
}
void merge(const ContourMoments &cm)
{
contour.insert(contour.end(), std::make_move_iterator(cm.contour.begin()), std::make_move_iterator(cm.contour.end()));
init();
}
float horizontalDistanceTo(const ContourMoments &cm)
{
return std::abs(center.x - cm.center.x);
}
float verticalDistanceTo(const ContourMoments &cm)
{
return std::abs(center.y - cm.center.y);
}
float centerDistanceTo(const ContourMoments &cm)
{
return std::sqrt(std::pow(center.x - cm.center.x, 2) + std::pow(center.y - cm.center.y, 2));
}
ContourMoments() = default;
~ContourMoments() = default;
};
float RandomFloat(float a, float b) {
float random = ((float) rand()) / (float) RAND_MAX;
float diff = b - a;
float r = random * diff;
return a + r;
}
std::vector<std::vector<cv::Point2f>> createData()
{
std::vector<std::vector<cv::Point2f>> cs;
for (int i = 0; i < 2000; ++i) {
std::vector<cv::Point2f> c;
int j_stop = rand()%11;
for (int j = 0; j < j_stop; ++j) {
c.push_back(cv::Point2f(RandomFloat(0.0, 20.0), RandomFloat(0.0, 20.0)));
}
cs.push_back(c);
}
return cs;
}
void printVectorOfVectorsOfPoints(const std::vector<std::vector<cv::Point2f>> &cs) {
std::cout << "####################################################" << std::endl;
for (const auto &el : cs) {
bool first = true;
for (const auto &pt : el) {
if (!first) {
std::cout << ", ";
}
first = false;
std::cout << "{x: " + std::to_string(pt.x) + ", y: " + std::to_string(pt.y) + "}";
}
std::cout << std::endl;
}
std::cout << "####################################################" << std::endl;
}
void merge(std::vector<std::vector<cv::Point2f>> &contours, int &counterMerged){
for(auto it = contours.begin() ; it < contours.end() ; /*++it*/)
{
int counter = 0;
if (it->size() < 5)
{
it = contours.erase(it);
continue;
}
for (auto it2 = it + 1; it2 < contours.end(); /*++it2*/)
{
if (it2->size() < 5)
{
it2 = contours.erase(it2);
continue;
}
ContourMoments cm1(*it);
ContourMoments cm2(*it2);
if (cm1.centerDistanceTo(cm2) > 4.0)
{
++counter;
++it2;
continue;
}
counterMerged++;
cm1.merge(std::move(cm2));
it2 = contours.erase(it2);
}
if (counter > 0)
{
std::advance(it, counter);
}
else
{
++it;
}
}
}
int main(int argc, const char * argv[])
{
srand(time(NULL));
std::vector<std::vector<cv::Point2f>> contours = createData();
printVectorOfVectorsOfPoints(contours);
int counterMerged = 0;
merge(contours, counterMerged);
printVectorOfVectorsOfPoints(contours);
std::cout << "Merged " << std::to_string(counterMerged) << " vectors." << std::endl;
return 0;
}
提前致谢!
祝福
贴出完整的例子——先安装opencv
这会生成最多 10 个点的 2000 个 vector ,如果它们靠得很近,则将它们合并。
最佳答案
对于每个轮廓,您可以预先计算中心。然后,您要做的是对轮廓进行聚类。每对中心最多相距 d
的轮廓应该属于同一个簇。
这可以通过简单的半径查询来完成。像这样:
for each contour ci in all contours
for each contour cj with cluster center at most d away from ci
merge cluster ci and cj
对于半径查询,我会建议类似 k-d tree 的查询.将所有轮廓输入到树中,然后您可以在 O(log n)
中查询邻居,而不是像现在那样在 O(n)
中查询。
对于合并部分,我建议使用 union-find data structure .这使您可以在几乎恒定的时间内进行合并。最后,您可以将所有轮廓数据收集到一个大的集群轮廓中。
关于c++ - 以最有效的方式合并 C++ vector 或类似数据结构中的某些元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52590034/
学习SQL。有一个简单的带有字段标题的桌面游戏。我想根据标题进行搜索。如果我有一款名为 Age of Empires III: Dynasties 的游戏,并且我使用 LIKE 和参数 Age of
我正在尝试为以下数据结构创建镜头。我正在使用lens-family . data Tree = Tree { _text :: String, _subtrees ::
我发现很难理解这一点。比如说,在 Python 中,如果我想要一个根据用户输入在循环中修改的列表,我会有这样的内容: def do_something(): x = [] while(
我有一个像这样的 mysql 查询 SELECT group_name FROM t_groups WHERE group_name LIKE '%PCB%'; 结果是 group_name ----
我的数据库表中有超过一百万条记录。当我使用like时非常慢,当我使用match against时他们丢失了一些记录。 我创建帮助表: 标签列表 tag_id tag_name tag_rel_me
我在我的一个 Java 项目中使用 JXBrowser 来简单显示 googlemaps 网页,以便我可以在那里跟踪路线,但最近我想改进该项目,但我的问题是 JXBrowser 的许可证过期(只有一个
小问题:如何将 mysql_escape_string 变量包含在 like 子句中? "SELECT * FROM table WHERE name LIKE '%". %s . "%'" 或
我尝试使用几个jquery消息插件,例如alertify . 但我注意到的主要事情是系统消息框会停止后台功能,直到用户响应。其他插件没有此功能。 有没有办法将此功能添加到 jquery 插件中?可以扩
我是 Ruby 新手。我过去使用过 shell。我正在将 shell 程序转换为 ruby。我有以下命令 cmd="cat -n " + infile + " | grep '127.0.0.1
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
当我研究 Rust 时,我试图编写一个 Rust 函数来查看任何可迭代的字符串。 我最初的尝试是 fn example_1(iter: impl Iterator); fn example_2(ite
我必须在我的项目中使用代码拆分。但无论如何,第一次初始下载有一些代码。 现在我想向最终用户展示代码下载(.cache.html - 或其他代码拆分)的进度,例如 gmail 启动进度。 请你帮帮我。
我今天找到了一个错误,它最终是由我代码中的以下片段引起的(我试图在列表中仅过滤“PRIMARY KEY”约束): (filter #(= (% :constraint_type "PRIMARY KE
我正在尝试在关键字段上实现检查约束。关键字段由 3 个字符的前缀组成,然后附加数字字符(可以手动提供,但默认是从序列中获取整数值,然后将其转换为 nvarchar)。关键字段定义为 nvarhcar(
我正在尝试使用以下方式创建 List 实例: List listOne = new ArrayList(); List listTwo = new ArrayList(){}; List listTh
我过去曾为 iOS 开发过,最近转向了 mac 开发。我开始了一个“感受”事物的项目,但遇到了一个问题。我试图创建一个 NSTableView 来显示多个项目,包括一个标签、一个 2 UIImageV
我正在尝试编写一个查询,该查询将返回哪些主机缺少某个软件: Host Software A Title1 A
AFAIK,在三种情况下别名是可以的 仅限定符或符号不同的类型可以互为别名。 struct 或 union 类型可以为包含在其中的类型设置别名。 将 T* 转换为 char* 是可以的。 (不允许相反
\s 似乎不适用于 sed 's/[\s]\+//' tempfile 当它为工作时 sed 's/[ ]\+//' tempfile 我正在尝试删除由于命令而出现在每行开头的空格: nl -s ')
我正在使用 ocamlgraph 在 ocaml 中编写程序,并想知道是否要将其移植到 F# 我有哪些选择?谢谢。 最佳答案 QuickGraph .Net 最完整的图形库之一 关于F# 图形库(类似
我是一名优秀的程序员,十分优秀!