C++ 程序使用 OpenCV 可视化和分析两个图像之间特征点的对应关系

文章目录

    • 代码功能
    • 源码文件
    • 编译文件

请添加图片描述

代码功能

  1. 创建图像和生成随机特征点

    • 程序首先创建两个灰度图像(m_image_Left_BGRm_image_Right_BGR),并将它们转换为彩色图像。
    • 然后,生成两组随机特征点(mvKeysmvKeysRight),分别对应于这两个图像。
  2. 关联左右图特征点

    • 使用一个二维向量 vRowIndices 假设存储与左图特征点在 Y 轴上对应的右图特征点索引。这里简单地假设左图中的每个特征点对应于右图中具有相同索引的特征点。
  3. 合并图像并绘制特征点

    • 对于左图的每个特征点,程序创建一张包含左右图的合并图像。
    • 在合并图像上绘制坐标轴,并显示图像的宽度和高度。
    • 在合并图像的左侧部分(对应于 m_image_Left_BGR),标记左图特征点的位置,并在右侧部分(对应于 m_image_Right_BGR)标记对应的右图特征点的位置。
  4. 保存和绘制特征点信息

    • 对于每个左图特征点及其对应的右图特征点,程序绘制一个红色圆圈表示特征点的位置,并添加包含特征点索引和坐标的文本标签。
    • 然后,将包含这些信息的合并图像保存为 PNG 文件,文件名基于左图特征点的索引和对应的右图特征点的索引。
  5. 文件保存路径

    • 保存的文件路径被设置为当前目录下的一个子目录。

总的来说,这个程序用于可视化和分析两个图像之间特征点的对应关系。它在合并的图像上显示了左右图的特征点,以及相关的坐标信息,这在图像处理、立体视觉或特征点匹配分析中非常有用。

源码文件

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>

#include <string>  // 确保包含这个头文件

using namespace std;

std::vector<cv::KeyPoint> generateRandomKeyPoints(const cv::Mat& image, int numPoints) {
    std::vector<cv::KeyPoint> keypoints;
    cv::RNG rng;
    for (int i = 0; i < numPoints; ++i) {
        cv::Point2f pt(rng.uniform(0.f, (float)image.cols), rng.uniform(0.f, (float)image.rows));
        keypoints.push_back(cv::KeyPoint(pt, 1.f));
    }
    return keypoints;
}

int main() {
    // 创建两个简单的灰度图像,并转换为彩色图像
    cv::Mat m_image_Left_BGR = cv::Mat::zeros(240, 320, CV_8UC1);
    cv::Mat m_image_Right_BGR = cv::Mat::zeros(240, 320, CV_8UC1);
    cv::cvtColor(m_image_Left_BGR, m_image_Left_BGR, cv::COLOR_GRAY2BGR);
    cv::cvtColor(m_image_Right_BGR, m_image_Right_BGR, cv::COLOR_GRAY2BGR);

    // 生成一些随机特征点
    std::vector<cv::KeyPoint> mvKeys = generateRandomKeyPoints(m_image_Left_BGR, 100);
    std::vector<cv::KeyPoint> mvKeysRight = generateRandomKeyPoints(m_image_Right_BGR, 100);

    // 假设 vRowIndices 是一个二维向量,存储与左图特征点在 Y 轴上对应的右图特征点索引
    std::vector<std::vector<size_t>> vRowIndices(m_image_Left_BGR.rows);
    for (int i = 0; i < mvKeys.size(); ++i) {
        vRowIndices[mvKeys[i].pt.y].push_back(i); // 为了演示,我们简单地假设每个左图特征点与相同索引的右图特征点对应
    }

       for(int iL=0; iL<mvKeys.size(); iL++)
        {
            const cv::KeyPoint &kpL = mvKeys[iL];

            // 循环绘制和左目当前特征点 和 vRowIndices[i]
            // 1. 这里生成一张大图包括左右目
            const int height = max(m_image_Left_BGR.rows, m_image_Right_BGR.rows);
            const int width = m_image_Left_BGR.cols + m_image_Right_BGR.cols;
            cv::Mat output(height, width, CV_8UC3, cv::Scalar(0, 0, 0));
            m_image_Left_BGR.copyTo(output(cv::Rect(0, 0, m_image_Left_BGR.cols, m_image_Left_BGR.rows)));
            m_image_Right_BGR.copyTo(output(cv::Rect(m_image_Left_BGR.cols, 0, m_image_Right_BGR.cols, m_image_Right_BGR.rows)));

            // 左目绘制x轴
            cv::line(output, cv::Point(5, 5), cv::Point(m_image_Left_BGR.cols - 100, 5), cv::Scalar(0, 0, 255), 2);
            cv::arrowedLine(output, cv::Point(m_image_Left_BGR.cols - 100, 5), cv::Point(m_image_Left_BGR.cols - 10, 5), cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
            cv::putText(output, "X", cv::Point(m_image_Left_BGR.cols - 150, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
            cv::putText(output, "Width Col: " + std::to_string(m_image_Left_BGR.cols), cv::Point(m_image_Left_BGR.cols - 150, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);

            // 右目绘制x轴
            cv::line(output, cv::Point(m_image_Left_BGR.cols + 5, 5), cv::Point(m_image_Left_BGR.cols + m_image_Right_BGR.cols - 100, 5), cv::Scalar(0, 0, 255), 2);
            cv::arrowedLine(output, cv::Point(m_image_Left_BGR.cols + m_image_Right_BGR.cols - 100, 5), cv::Point(m_image_Left_BGR.cols + m_image_Right_BGR.cols - 10, 5), cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
            cv::putText(output, "X", cv::Point(m_image_Left_BGR.cols + m_image_Right_BGR.cols - 150, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
            cv::putText(output, "Width Col: " + std::to_string(m_image_Right_BGR.cols), cv::Point(m_image_Left_BGR.cols + m_image_Right_BGR.cols - 150, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);

            // 左目绘制Y轴
            cv::line(output, cv::Point(5, 5), cv::Point(5, m_image_Left_BGR.rows - 100), cv::Scalar(0, 255, 0), 2);
            cv::arrowedLine(output, cv::Point(5, m_image_Left_BGR.rows - 100), cv::Point(5, m_image_Left_BGR.rows - 5), cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
            cv::putText(output, "Y", cv::Point(10, m_image_Left_BGR.rows - 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
            cv::putText(output, "Height Row: " + std::to_string(m_image_Left_BGR.rows), cv::Point(10, m_image_Left_BGR.rows - 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1, cv::LINE_AA);

            // 右目绘制Y轴
            cv::line(output, cv::Point(m_image_Left_BGR.cols + 5, 5), cv::Point(m_image_Left_BGR.cols + 5, m_image_Right_BGR.rows - 100), cv::Scalar(0, 255, 0), 2);
            cv::arrowedLine(output, cv::Point(m_image_Left_BGR.cols + 5, m_image_Right_BGR.rows - 100), cv::Point(m_image_Left_BGR.cols + 5, m_image_Right_BGR.rows - 5), cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
            cv::putText(output, "Y", cv::Point(m_image_Left_BGR.cols + 10, m_image_Right_BGR.rows - 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2, cv::LINE_AA);
            cv::putText(output, "Height Row: " + std::to_string(m_image_Right_BGR.rows), cv::Point(m_image_Left_BGR.cols + 10, m_image_Right_BGR.rows - 40), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1, cv::LINE_AA);

            // 2. 这里把左目特征点绘制大图的左目上
            circle(output, kpL.pt, 2, cv::Scalar(255, 0, 0), 2);
            cv::putText(output,"iL " + std::to_string(int(iL)) + ", X " + std::to_string(int(kpL.pt.x)) + ", Y " + std::to_string(int(kpL.pt.y)),
                        cv::Point(kpL.pt.x - 25, kpL.pt.y - 10), cv::FONT_HERSHEY_SIMPLEX, 0.4,
                        cv::Scalar(255, 0, 0), 1);

            for(size_t iC=0; iC<vRowIndices[kpL.pt.y].size(); iC++) {
                const size_t iR = vRowIndices[kpL.pt.y][iC];
                const cv::KeyPoint &kpR = mvKeysRight[iR];

                // 3. 这里把右目特征点绘制大图的右目上,并且每一个特征点是一张图像
                circle(output, (kpR.pt + cv::Point2f((float) m_image_Left_BGR.cols, 0.f)), 2,cv::Scalar(255, 0, 0), 2);
                cv::putText(output,"iC " + std::to_string(int(iC)) + ", X " + std::to_string(int(kpR.pt.x)) + ", Y " + std::to_string(int(kpR.pt.y)),
                            cv::Point(kpR.pt.x + m_image_Left_BGR.cols - 15,kpR.pt.y - 15),
                            cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(255, 0, 0), 1);
                cv::imwrite("./" + to_string(iL) + "_" + to_string(iC) + ".png",output);
            }
        }


    return 0;
}

编译文件

cmake_minimum_required(VERSION 3.10)
project(ImagePyramid)

# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 找到OpenCV包
find_package(OpenCV REQUIRED)

# 包含OpenCV头文件
include_directories(${OpenCV_INCLUDE_DIRS})

# 添加可执行文件
add_executable(ImagePyramid main.cpp)

# 链接OpenCV库
target_link_libraries(ImagePyramid ${OpenCV_LIBS})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/358845.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

线段树分治总结

线段树分治总结 概念例题二分图 /【模板】线段树分治[HAOI2017] 八纵八横[FJOI2015] 火星商店问题EnvyExtending Set of PointsForced Online Queries Problem「雅礼集训 2018 Day10」贪玩蓝月BZOJ4184-shallot[bzoj4644]经典**题 概念 \qquad 线段树分治一般用来解决带有如下两…

强敌环伺:金融业信息安全威胁分析——整体态势

从早期的Zeus和其他以银行为目标的特洛伊木马程序&#xff0c;到现在的大规模分布式拒绝服务&#xff08;DDoS&#xff09;攻击&#xff0c;再到新颖的钓鱼攻击和勒索软件&#xff0c;金融服务业已成为遭遇网络犯罪威胁最严重的行业之一。金融服务业的重要性不言而喻&#xff0…

浙政钉(专有钉钉)

专有钉钉是浙政钉的测试版本&#xff0c;可在正式发布之前进行业务开发。 专有钉钉 原名政务钉钉 是高安全、强管控、灵活开放的面向大型组织专有独享的协同办公平台。支持专有云、混合云等多种方式灵活部署&#xff0c;以满足客户特定场景所需为目标&#xff0c;最大化以“平…

Docker 搭建MySQL主从复制-读写分离

一. 介绍 MySQL主从复制是一种常用的数据库高可用性解决方案&#xff0c;通过在主数据库上记录的数据变更&#xff0c;同步到一个或多个从数据库&#xff0c;实现数据的冗余备份和读写分离。在Docker环境下搭建MySQL主从复制和读写分离&#xff0c;不仅方便管理&#xff0c;还…

【干货】【常用电子元器件介绍】【电容】(二)--电容器的主要参数、测量、选择与应用

声明&#xff1a;本人水平有限&#xff0c;博客可能存在部分错误的地方&#xff0c;请广大读者谅解并向本人反馈错误。 一、 电容器的主要参数 1.1 耐压 耐压(Voltage Rating)是指电容器在电路中长期有效地工作而不被击穿所能承受的最大直流电压。对于结构、介质、容量相同的…

Linux--redhat9创建软件仓库

1.插入光盘&#xff0c;挂载镜像 模拟插入光盘: 点击:虚拟机-可移动设备-CD/DVD 设备状态全选&#xff0c;使用ISO影响文件选择当前版本镜像&#xff0c;点击确认。 2.输入: df -h 可以显示&#xff0c;默认/dev/sr0文件为光盘文件&#xff0c;挂载点为/run/media/root/镜像…

Linux(CentOS7)常见指令的常见用法(上)

指令功能hostname查看当前的主机名hostnamectl set-hostname修改主机名adduser添加用户passwd给用户设置密码userdel -r 删除用户ls显示某路径下的文件名ls -l ll 显示某路径下每个文件及其属性ls -la ls -al 显示某路径下所有文件包括隐藏文件及属性ls -d只看指定文件夹&…

ElementUI安装与使用指南

Element官网-安装指南 提醒一下&#xff1a;下面实例讲解是在Mac系统演示的&#xff1b; 一、开发环境配置 电脑需要先安装好node.js和vue2或者vue3 安装Node.js Node.js 中文网 安装node.js命令&#xff1a;brew install node node.js安装完后&#xff0c;输入&#xff1…

第九节HarmonyOS 常用基础组件18-checkBox

1、描述 提供多选框组件&#xff0c;通常用于某选项的打开或关闭。 2、接口 Checkbox(options:{name?: string, group?: string}) 3、参数 参数名 参数类型 必填 描述 name string 否 多选框名称 group string 否 多选框群组名称。&#xff08;未配合使用Chec…

【芯片设计- RTL 数字逻辑设计入门 番外篇 8 -- MBIST 详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 MBISTMBIST 背景MBIST的主要特点和优势MBIST的工作原理举例 MBIST MBIST&#xff08;Memory Built-In Self-Test&#xff09;是一种在系统级芯片&#xff08;SoC&#xff09;中内置的内建自测试&#xff0c;用于检测和验证片上存储…

centos下静态链接:/usr/bin/ld: cannot find -l某某某

问题&#xff1a;/usr/bin/ld: cannot find -l某某某 前言解法相关文章 前言 我是在静态链接的时候碰到了/usr/bin/ld: cannot find -lstdc的问题&#xff0c;这里来记录一下我是如何解决的。 如果你是动态链接的时候出了问题&#xff0c;可以直接看我给出的倒数第二篇文章&a…

C#,贝尔数(Bell Number)的计算方法与源程序

1 埃里克坦普尔贝尔 贝尔数是组合数学中的一组整数数列&#xff0c;以埃里克坦普尔贝尔&#xff08;Eric Temple Bell&#xff09;命名&#xff0c; 埃里克坦普尔贝尔&#xff08;生于1883年2月7日&#xff0c;苏格兰阿伯丁郡阿伯丁&#xff0c;于1960年12月21日在美国加利福尼…

Abp 创建一个WPF的项目

开发环境&#xff1a;VS2022、.NET6 1、创建项目&#xff1a;MyWpfApp&#xff0c;这里不再废话了。 2、NuGet添加&#xff1a; 2.1、Volo.Abp.Autofac 2.2、Serilog.Sinks.File 2.3、Serilog.Sinks.Async 2.4、Serilog.Extensions.Logging 2.5、Serilog.Extensions.Hos…

算法沉淀——滑动窗口(leetcode真题剖析)

算法沉淀——滑动窗口 01.长度最小的子数组02.无重复字符的最长子串03.最大连续1的个数 III04.将 x 减到 0 的最小操作数05.水果成篮06.找到字符串中所有字母异位词07.串联所有单词的子串08.最小覆盖子串 滑动窗口算法是一种用于解决数组或列表中子数组或子序列问题的有效技巧。…

【C++版】排序算法详解

目录 直接插入排序 希尔排序 选择排序 冒泡排序 堆排序 快速排序 hoare法 挖坑法 前后指针法 非递归版本 快速排序中的优化 归并排序 递归版本 非递归版本 计数排序 总结 直接插入排序 直接插入排序的思想是&#xff1a;把待排序的记录按其关键码值的大小逐个插入…

【Java程序设计】【C00174】基于SSM在线医院管理系统(论文+PPT)

基于SSM在线医院管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的在线医院管理系统 本系统分为前台系统、后台管理员、后台医生以及后台用户4个功能模块。 前台系统&#xff1a;当游客打开系统的网址后&#xf…

flask基于python的个人理财备忘录记账提醒系统vue

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。 “备忘记账系统”是基于Mysql数据库&#xff0c;在python程序设计的基础上实现的。为确保中国经济的持续发展&#xff0c;信息时代日益更新&#xff0c;蓬勃发展。同时&#xff0c;随着信息社…

在 Android 中使用 C/C++:初学者综合指南

在 Android 中使用 C/C&#xff1a;初学者综合指南 一、为什么有人在他们的 Android 项目中需要 C/C 支持&#xff1f;二、了解 C 如何集成到 Android 应用程序中三、C和Java程序的编译3.1 Java3.2 Android ART 和 DEX 字节码 四、使用 JNI 包装 C 源代码五、CMake和Android ND…

【讲座分享】| 复旦大学张奇教授——《自然语言发表论文如何打怪升级?NLP顶会论文发表》

文章目录 1 基础关1.1 基础书籍1.2 提高书籍1.3 课程链接1.4 编程实战 2 阅读关2.1 分层过滤2.2 集团作战&#xff0c;信息获取2.3 论文如何泛读 3 动机 方向关3.1 快速发论文3.2 好的研究 4 写作关4.1 论文写作流程4.2 从读者角度出发4.3 每一部分怎么写4.3.1 Abstract摘要4.3…

浅谈一下软件 QA 方法论 和 工具

浅谈一下软件 QA 方法论 和 工具 目录概述需求&#xff1a; 设计思路实现思路分析1.QA方法论2.Java QA工具 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result…