-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdetect.cpp
235 lines (191 loc) · 8.34 KB
/
detect.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "Marker.h"
#pragma comment(lib,"libzbar-0.lib")
using namespace std;
using namespace cv;
using namespace Eigen;
using namespace zbar;
int Corner3d = 0;
vector<cv::Point3f> m_markerCorners3d;
vector<cv::Point2f> m_markerCorners2d;
Mat camMatrix;//相机内参
Mat distCoeff;//相机畸变参数(需经过相机标定得到)
int main_detect(Mat &frame)
{
if (Corner3d == 0)
{
m_markerCorners3d.push_back(cv::Point3f(+70.0f, +70.0f, 0));//以二维码中心为世界坐标,二维码大小为200mm,x轴向右为正,y轴向下为正
m_markerCorners3d.push_back(cv::Point3f(-70.0f, +70.0f, 0));
m_markerCorners3d.push_back(cv::Point3f(-70.0f, -70.0f, 0));
m_markerCorners3d.push_back(cv::Point3f(+70.0f, -70.0f, 0));
Corner3d = 1;
}
camMatrix = (Mat_<double>(3, 3) << 2872.24, 0, 1905.33, 0, 2863.94, 1102.70, 0, 0, 1); //内参矩阵
distCoeff = (Mat_<double>(5, 1) << -0.41615, 0.34278, 0.00048529, 0.00056574, -0.31462); //畸变矩阵
int x[4], y[4]; //二维码坐标点
// 定义Zbar扫描的类
ImageScanner scanner;
// 初始化
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
// 加载二维码图像数据
Mat srcImage = frame;
if (!srcImage.data) {
cout << "Input image error!" << endl;
system("pause");
return 0;
}
Mat src_gray, result;
cvtColor(srcImage, src_gray, CV_BGR2GRAY);//获得灰度图
result = src_gray.clone();
threshold(src_gray, result, 70, 120, CV_THRESH_BINARY); //进行二值化处理,选择30,200.0为阈值
cvNamedWindow("灰度图", CV_WINDOW_NORMAL);
cv::imshow("灰度图", result);
int width = src_gray.cols;
int height = src_gray.rows;
// wrap the image
uchar*raw = (uchar*)result.data;
Image imageZbar(width, height, "Y800", raw, width*height);
// 开始扫描
scanner.scan(imageZbar);
// 扩展结果
Image::SymbolIterator symbol = imageZbar.symbol_begin();
if (imageZbar.symbol_begin() == imageZbar.symbol_end()) {
cout << "扫描失败,检查图片数据!" << endl;
}
else
{
for (; symbol != imageZbar.symbol_end(); ++symbol) {
//cout << "类型:" << endl << symbol->get_type_name() << endl;
//cout << "条码:" << endl << symbol->get_data() << endl;
x[0] = symbol->get_location_x(0);
x[1] = symbol->get_location_x(3);
x[2] = symbol->get_location_x(2);
x[3] = symbol->get_location_x(1);
y[0] = symbol->get_location_y(0);
y[1] = symbol->get_location_y(3);
y[2] = symbol->get_location_y(2);
y[3] = symbol->get_location_y(1);
//输出特征点(角点)在像素坐标系上的像素坐标
cout << "左上角点:" << "(" << symbol->get_location_x(0) << "," << symbol->get_location_y(0) << ")" << endl;
cout << "右上角点:" << "(" << symbol->get_location_x(3) << "," << symbol->get_location_y(3) << ")" << endl;
cout << "左下角点:" << "(" << symbol->get_location_x(1) << "," << symbol->get_location_y(1) << ")" << endl;
cout << "右下角点:" << "(" << symbol->get_location_x(2) << "," << symbol->get_location_y(2) << ")" << endl;
line(srcImage, Point(x[0], y[0]), Point(x[1], y[1]), Scalar(0, 0, 255), 8);
line(srcImage, Point(x[1], y[1]), Point(x[2], y[2]), Scalar(0, 0, 255), 8);
line(srcImage, Point(x[2], y[2]), Point(x[3], y[3]), Scalar(0, 0, 255), 8);
line(srcImage, Point(x[3], y[3]), Point(x[0], y[0]), Scalar(0, 0, 255), 8);
}
cv::Mat Rvec;
cv::Mat_<float> Tvec;
cv::Mat raux, taux;
vector<Point2f> points2d;
for (int i = 0; i < 4; i++) {
//cout << Point(x[i], y[i]) << endl;
points2d.push_back(Point(x[i], y[i]));
}
cv::solvePnP(m_markerCorners3d, points2d, camMatrix, distCoeff, raux, taux, false, CV_P3P); //PNP算法求位姿
raux.convertTo(Rvec, CV_32F); //旋转向量
taux.convertTo(Tvec, CV_32F); //平移向量
cv::Mat_<float> rotMat(3, 3);
cv::Rodrigues(Rvec, rotMat);
//float theta_z = atan2(rotMat[1][0], rotMat[0][0])*57.2958;
//float theta_y = atan2(-rotMat[2][0], sqrt(rotMat[2][0] * rotMat[2][0] + rotMat[2][2] * rotMat[2][2]))*57.2958;
//float theta_x = atan2(rotMat[2][1], rotMat[2][2])*57.2958;
//cout << "绕x轴转角:" << theta_x << endl;
//cout << "绕y轴转角:" << theta_y << endl;
//out << "绕z轴转角:" << theta_z << endl;
//void cv::cv2eigen(const Mat &rotMat, Eigen::Matrix< float, 1, Eigen::Dynamic > &R_n);
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> R_n;
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> T_n;
cv2eigen(rotMat, R_n);
cv2eigen(Tvec, T_n);
//cout << "R_n优化前的数值" << endl;
//cout << R_n << endl;
//cout << T_n << endl;
Eigen::Vector3f P_oc;
P_oc = -R_n.inverse()*T_n;
/*cout << endl << "PnP输出相机世界坐标" << endl;
cout << "camPositionX: " << ("%2f", P_oc[0]) << endl;
cout << "camPositionY: " << ("%2f", P_oc[1]) << endl;
cout << "camPositionZ: " << ("%2f", P_oc[2]) << endl;*/
/********************g2o实现相机位姿估计*********************/
// 初始化g2o
typedef g2o::BlockSolver< g2o::BlockSolverTraits<6, 3> > Block;
Block::LinearSolverType* linearSolver = new g2o::LinearSolverDense<Block::PoseMatrixType>(); //线性方程求解器
Block* solver_ptr = new Block(std::unique_ptr<Block::LinearSolverType>(linearSolver)); // 矩阵求解器
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg(std::unique_ptr<Block>(solver_ptr));
//g2o::OptimizationAlgorithmDogleg* solver = new g2o::OptimizationAlgorithmDogleg(std::unique_ptr<Block>(solver_ptr)); DogLeg优化方法
//g2o::OptimizationAlgorithmGaussNewton* solver = new g2o::OptimizationAlgorithmGaussNewton(std::unique_ptr<Block>(solver_ptr)); GN优化方法
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm(solver);
// 定义图优化顶点----> pose
g2o::VertexSE3Expmap* pose = new g2o::VertexSE3Expmap(); // camera pose
Eigen::Matrix3d R_mat;
/*R_mat <<
R_n(0, 0), R_n(0, 1), R_n(0, 2),
R_n(1, 0), R_n(1, 1), R_n(1, 2),
R_n(2, 0), R_n(2, 1), R_n(2, 2);*/
R_mat << 1, 0, 0, 0, 1, 0, 0, 0, 1;
pose->setId(0);
pose->setEstimate(g2o::SE3Quat(R_mat,Eigen::Vector3d(T_n(0, 0), T_n(1, 0), T_n(2, 0))));
optimizer.addVertex(pose);
// 定义图优化顶点----> points
int index = 1;
for (const Point3f p : m_markerCorners3d)
{
g2o::VertexSBAPointXYZ* point = new g2o::VertexSBAPointXYZ();
point->setId(index++);
point->setEstimate(Eigen::Vector3d(p.x, p.y, p.z));
point->setMarginalized(true);
//point->setInformation(Eigen::Matrix3d::Identity());
optimizer.addVertex(point);
}
// 设置相机内参
g2o::CameraParameters* camera = new g2o::CameraParameters(
camMatrix.at<double>(0, 0), Eigen::Vector2d(camMatrix.at<double>(0, 2), camMatrix.at<double>(1, 2)), 0);
camera->setId(0);
optimizer.addParameter(camera);
// 设置图优化边
index = 1;
for (const Point2f p : points2d)
{
g2o::EdgeProjectXYZ2UV* edge = new g2o::EdgeProjectXYZ2UV();
edge->setId(index);
edge->setVertex(0, dynamic_cast<g2o::VertexSBAPointXYZ*> (optimizer.vertex(index)));
edge->setVertex(1, pose);
edge->setMeasurement(Eigen::Vector2d(p.x, p.y)); //设置观测值
edge->setParameterId(0, 0);
edge->setInformation(Eigen::Matrix2d::Identity());
optimizer.addEdge(edge);
index++;
}
// 设置优化参数,开始执行优化
optimizer.setVerbose(false);
optimizer.initializeOptimization();
optimizer.optimize(100);
// 输出优化结果
cout << endl << "after optimization:" << endl;
//cout << "T=" << endl << Eigen::Isometry3d(pose->estimate()).matrix() << endl; //变换矩阵
Eigen::Matrix4d T_4d = Eigen::Isometry3d(pose->estimate()).matrix();
Eigen::Matrix3d R_mat_update; //优化后旋转矩阵
R_mat_update <<
T_4d(0, 0), T_4d(0, 1), T_4d(0, 2),
T_4d(1, 0), T_4d(1, 1), T_4d(1, 2),
T_4d(2, 0), T_4d(2, 1), T_4d(2, 2);
//cout << R_mat_update << endl;
Eigen::Vector3d T_n_update; // 优化后平移向量
T_n_update << T_4d(0, 3), T_4d(1, 3), T_4d(2, 3);
//cout << T_n_update << endl;
Eigen::Vector3d P_oc_update; // 优化后世界坐标
P_oc_update = -R_mat_update.inverse()*T_n_update;
cout << "优化后相机世界坐标" << endl;
cout << "camPositionX: " << ("%2f", P_oc_update[0]) << endl;
cout << "camPositionY: " << ("%2f", P_oc_update[1]) << endl;
cout << "camPositionZ: " << ("%2f", P_oc_update[2]) << endl;
cout << "--------------------------------" << endl;
}
cv::imshow("IPCamera", srcImage);
if (waitKey(1) == 27) {
system("pause");
}
return 0;
}