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. 文件保存路径

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

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

源码文件

cpp 复制代码
#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;
}

编译文件

bash 复制代码
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})
相关推荐
Gyoku Mint4 分钟前
深度学习×第4卷:Pytorch实战——她第一次用张量去拟合你的轨迹
人工智能·pytorch·python·深度学习·神经网络·算法·聚类
zzywxc7877 分钟前
AI大模型的技术演进、流程重构、行业影响三个维度的系统性分析
人工智能·重构
点控云7 分钟前
智能私域运营中枢:从客户视角看 SCRM 的体验革新与价值重构
大数据·人工智能·科技·重构·外呼系统·呼叫中心
zhaoyi_he15 分钟前
多模态大模型的技术应用与未来展望:重构AI交互范式的新引擎
人工智能·重构
葫三生1 小时前
如何评价《论三生原理》在科技界的地位?
人工智能·算法·机器学习·数学建模·量子计算
pipip.1 小时前
UDP————套接字socket
linux·网络·c++·网络协议·udp
m0_751336392 小时前
突破性进展:超短等离子体脉冲实现单电子量子干涉,为飞行量子比特奠定基础
人工智能·深度学习·量子计算·材料科学·光子器件·光子学·无线电电子
美狐美颜sdk5 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
孞㐑¥6 小时前
Linux之Socket 编程 UDP
linux·服务器·c++·经验分享·笔记·网络协议·udp
DeepSeek-大模型系统教程6 小时前
推荐 7 个本周 yyds 的 GitHub 项目。
人工智能·ai·语言模型·大模型·github·ai大模型·大模型学习