如何在图像上显示opencv投影点



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

// 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;
}

您的代码有几个问题:

1.图像大小与相机固有参数不匹配

intrisicMat可以看出,原理点是(532.63, 380.95)。所以图像大小应该是1000*800左右,但您使用的图像只有640*480。事实上,九分之五的点被投影到图像区域之外(x>640(。

2.图纸位置错误

cv::Mat::at()的自变量是(row, col),因此image.at<cv::Vec3b>(ix, iy)应改为image.at<cv::Vec3b>(iy, ix)

3.cv::waitKey()

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

解决这些问题后,您将看到投影的9个点。

最新更新