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})
相关推荐
别NULL14 分钟前
机试题——疯长的草
数据结构·c++·算法
Jeremy_lf16 分钟前
【生成模型之三】ControlNet & Latent Diffusion Models论文详解
人工智能·深度学习·stable diffusion·aigc·扩散模型
桃花键神1 小时前
AI可信论坛亮点:合合信息分享视觉内容安全技术前沿
人工智能
野蛮的大西瓜1 小时前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
CYBEREXP20081 小时前
MacOS M3源代码编译Qt6.8.1
c++·qt·macos
yuanbenshidiaos2 小时前
c++------------------函数
开发语言·c++
CountingStars6192 小时前
目标检测常用评估指标(metrics)
人工智能·目标检测·目标跟踪
yuanbenshidiaos2 小时前
C++----------函数的调用机制
java·c++·算法
tangjunjun-owen2 小时前
第四节:GLM-4v-9b模型的tokenizer源码解读
人工智能·glm-4v-9b·多模态大模型教程
冰蓝蓝2 小时前
深度学习中的注意力机制:解锁智能模型的新视角
人工智能·深度学习