创建图像和生成随机特征点:
m_image_Left_BGR
和 m_image_Right_BGR
),并将它们转换为彩色图像。mvKeys
和 mvKeysRight
),分别对应于这两个图像。关联左右图特征点:
vRowIndices
假设存储与左图特征点在 Y 轴上对应的右图特征点索引。这里简单地假设左图中的每个特征点对应于右图中具有相同索引的特征点。合并图像并绘制特征点:
m_image_Left_BGR
),标记左图特征点的位置,并在右侧部分(对应于 m_image_Right_BGR
)标记对应的右图特征点的位置。保存和绘制特征点信息:
文件保存路径:
总的来说,这个程序用于可视化和分析两个图像之间特征点的对应关系。它在合并的图像上显示了左右图的特征点,以及相关的坐标信息,这在图像处理、立体视觉或特征点匹配分析中非常有用。
#include
#include
#include
#include // 确保包含这个头文件
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})