【问题标题】:How to show opencv projectedPoints on an image如何在图像上显示 opencv 投影点
【发布时间】:2023-03-03 03:13:01
【问题描述】:

以下代码的目标是将立方体的角顶点和中心点投影到相机图像平面上。但是,创建的图像包含背景屏幕的副本,并且不显示 9 个立方体点,或者至少我看不到任何 9 个点。如果这段代码有效,我想了解的是旋转和平移向量参数对立方体视图的影响。我想做的是在观察立方体的同时围绕立方体旋转相机。附:任何有关将 3D 点投影到 2D 相机图像平面上的数学信息也会有所帮助。聚苯乙烯。对顶点进行编号以使图像更清晰也很有帮助。

// baseline: https://www.programmersought.com/article/6279272931/
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/viz/types.hpp"

#include <iostream>
#include <string>
#include <math.h>

using namespace std;

vector<cv::Point3f> Generate3DPoints();

int main(int argc, char* argv[])
{
    // Generate 3D points
    vector<cv::Point3f> objectPoints = Generate3DPoints();
    vector<cv::Point2f> imagePoints;

    // Camera settings
    cv::Mat intrisicMat(3, 3, cv::DataType<float>::type); // Intrisic matrix
    intrisicMat.at<float>(0, 0) = 1.6415318549788924e+003;
    intrisicMat.at<float>(1, 0) = 0;
    intrisicMat.at<float>(2, 0) = 0;

    intrisicMat.at<float>(0, 1) = 0;
    intrisicMat.at<float>(1, 1) = 1.7067753507885654e+003;
    intrisicMat.at<float>(2, 1) = 0;

    intrisicMat.at<float>(0, 2) = 5.3262822453148601e+002;
    intrisicMat.at<float>(1, 2) = 3.8095355839052968e+002;
    intrisicMat.at<float>(2, 2) = 1;

    // Rotation vector
    cv::Mat rVec(3, 1, cv::DataType<float>::type); 
    rVec.at<float>(0) = -3.9277902400761393e-002;
    rVec.at<float>(1) = 3.7803824407602084e-002;
    rVec.at<float>(2) = 2.6445674487856268e-002;

    // Translation vector
    cv::Mat tVec(3, 1, cv::DataType<float>::type); 
    tVec.at<float>(0) = 2.1158489381208221e+000;
    tVec.at<float>(1) = -7.6847683212704716e+000;
    tVec.at<float>(2) = 2.6169795190294256e+001;

    // Distortion vector
    cv::Mat distCoeffs(5, 1, cv::DataType<float>::type);   
    distCoeffs.at<float>(0) = -7.9134632415085826e-001;
    distCoeffs.at<float>(1) = 1.5623584435644169e+000;
    distCoeffs.at<float>(2) = -3.3916502741726508e-002;
    distCoeffs.at<float>(3) = -1.3921577146136694e-002;
    distCoeffs.at<float>(4) = 1.1430734623697941e-002;

    cout << "Intrisic matrix: " << intrisicMat << endl << endl;
    cout << "Rotation vector: " << rVec << endl << endl;
    cout << "Translation vector: " << tVec << endl << endl;
    cout << "Distortion coef: " << distCoeffs << endl << endl;

    // Generate the points as viewed from the camera
    std::vector<cv::Point2f> projectedPoints;
    cv::projectPoints(objectPoints, rVec, tVec, intrisicMat, distCoeffs, projectedPoints);

    // Display the points in an image
    cv::Mat image(480, 640, CV_8UC3);
    const uint black_r(0), black_g(0), black_b(0);
    const uint silver_r(192), silver_g(192), silver_b(192);
    // image = cv::Scalar(redVal,greenVal,blueVal);
    image = cv::Scalar(black_b, black_g, black_r);
    // cv::viz::COLOR blk(cv::viz::Color::black());
    cv::Vec3b color(silver_b, silver_g, silver_r);
    for (unsigned int i = 0; i < projectedPoints.size(); ++i)
    {
        cout << "Project point " << objectPoints[i] << " to " << projectedPoints[i];
        cv::Point2f pt = projectedPoints[i];
        if (0<= (pt.x) && (pt.x) <= image.cols && 0<= (-pt.y) && (-pt.y) <= image.rows )
        {
            unsigned int ix(std::floor(pt.x)), iy(std::ceil(-pt.y));
            cout << ", and set image.at(" << ix << ", " << iy << ") = " << color;
            image.at<cv::Vec3b>(ix, iy) = color;
        }
        cout << endl;
    }

    cout << "calling imshow" << endl;
    cv::namedWindow("Projection", cv::WINDOW_AUTOSIZE);
    cv::imshow("Projection", image);
    cout << "return from imshow" << endl;

    cout << "Press any key to exit.";
    cin.ignore();
    cin.get();

    return 0;
}

vector<cv::Point3f> Generate3DPoints()
{
    vector<cv::Point3f> points;

    float x, y, z;

    // 8 corners of a cube

    // +0.5 z face
    z = .5;
    x = .5; y = .5;
    points.push_back(cv::Point3f(x, y, z));
    y = -.5;
    points.push_back(cv::Point3f(x, y, z));
    x = -.5; y = .5;
    points.push_back(cv::Point3f(x, y, z));
    y = -.5;
    points.push_back(cv::Point3f(x, y, z));

    // -0.5 z face
    z = -.5;
    x = .5; y = .5;
    points.push_back(cv::Point3f(x, y, z));
    y = -.5;
    points.push_back(cv::Point3f(x, y, z));
    x = -.5; y = .5;
    points.push_back(cv::Point3f(x, y, z));
    y = -.5;
    points.push_back(cv::Point3f(x, y, z));

    // mid point
    x = 0; y = 0; z = 0;
    points.push_back(cv::Point3f(x, y, z));

    return points;
}

【问题讨论】:

    标签: c++ opencv display point-clouds


    【解决方案1】:

    您的代码有几个问题:

    1。图像大小和相机固有参数不匹配

    intrisicMat可以看出原理点是(532.63, 380.95)。所以图片大小应该是1000*800左右,但是你使用的图片只有640*480。实际上,9 个点中有 5 个是投影到图像区域之外的 (x>640)。

    2。绘制位置错误

    cv::Mat::at() 的参数是(row, col),所以 image.at&lt;cv::Vec3b&gt;(ix, iy) 应改为image.at&lt;cv::Vec3b&gt;(iy, ix)

    3。 cv::waitKey()

    你应该在cv::imshow()之后调用cv::waitKey(0);,否则你看不到图片。

    解决这些问题后,您将看到预计的 9 点。

    【讨论】:

    • 谢谢!我是自学成才,仍然犯初学者错误......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 2016-10-24
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 2014-05-13
    相关资源
    最近更新 更多