forked from MasteringOpenCV/code
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
executable file
·190 lines (160 loc) · 6.35 KB
/
main.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
/*****************************************************************************
* Markerless AR desktop application.
******************************************************************************
* by Khvedchenia Ievgen, 5th Dec 2012
* http://computer-vision-talks.com
******************************************************************************
* Ch3 of the book "Mastering OpenCV with Practical Computer Vision Projects"
* Copyright Packt Publishing 2012.
* http://www.packtpub.com/cool-projects-with-opencv/book
*****************************************************************************/
////////////////////////////////////////////////////////////////////
// File includes:
#include "ARDrawingContext.hpp"
#include "ARPipeline.hpp"
#include "DebugHelpers.hpp"
////////////////////////////////////////////////////////////////////
// Standard includes:
#include <opencv2/opencv.hpp>
#include <gl/gl.h>
#include <gl/glu.h>
/**
* Processes a recorded video or live view from web-camera and allows you to adjust homography refinement and
* reprojection threshold in runtime.
*/
void processVideo(const cv::Mat& patternImage, CameraCalibration& calibration, cv::VideoCapture& capture);
/**
* Processes single image. The processing goes in a loop.
* It allows you to control the detection process by adjusting homography refinement switch and
* reprojection threshold in runtime.
*/
void processSingleImage(const cv::Mat& patternImage, CameraCalibration& calibration, const cv::Mat& image);
/**
* Performs full detection routine on camera frame and draws the scene using drawing context.
* In addition, this function draw overlay with debug information on top of the AR window.
* Returns true if processing loop should be stopped; otherwise - false.
*/
bool processFrame(const cv::Mat& cameraFrame, ARPipeline& pipeline, ARDrawingContext& drawingCtx);
int main(int argc, const char * argv[])
{
// Change this calibration to yours:
CameraCalibration calibration(526.58037684199849f, 524.65577209994706f, 318.41744018680112f, 202.96659047014398f);
if (argc < 2)
{
std::cout << "Input image not specified" << std::endl;
std::cout << "Usage: markerless_ar_demo <pattern image> [filepath to recorded video or image]" << std::endl;
return 1;
}
// Try to read the pattern:
cv::Mat patternImage = cv::imread(argv[1]);
if (patternImage.empty())
{
std::cout << "Input image cannot be read" << std::endl;
return 2;
}
if (argc == 2)
{
processVideo(patternImage, calibration, cv::VideoCapture());
}
else if (argc == 3)
{
std::string input = argv[2];
cv::Mat testImage = cv::imread(input);
if (!testImage.empty())
{
processSingleImage(patternImage, calibration, testImage);
}
else
{
cv::VideoCapture cap;
if (cap.open(input))
{
processVideo(patternImage, calibration, cap);
}
}
}
else
{
std::cerr << "Invalid number of arguments passed" << std::endl;
return 1;
}
return 0;
}
void processVideo(const cv::Mat& patternImage, CameraCalibration& calibration, cv::VideoCapture& capture)
{
// Grab first frame to get the frame dimensions
cv::Mat currentFrame;
capture >> currentFrame;
// Check the capture succeeded:
if (currentFrame.empty())
{
std::cout << "Cannot open video capture device" << std::endl;
return;
}
cv::Size frameSize(currentFrame.cols, currentFrame.rows);
ARPipeline pipeline(patternImage, calibration);
ARDrawingContext drawingCtx("Markerless AR", frameSize, calibration);
bool shouldQuit = false;
do
{
capture >> currentFrame;
if (currentFrame.empty())
{
shouldQuit = true;
continue;
}
shouldQuit = processFrame(currentFrame, pipeline, drawingCtx);
} while (!shouldQuit);
}
void processSingleImage(const cv::Mat& patternImage, CameraCalibration& calibration, const cv::Mat& image)
{
cv::Size frameSize(image.cols, image.rows);
ARPipeline pipeline(patternImage, calibration);
ARDrawingContext drawingCtx("Markerless AR", frameSize, calibration);
bool shouldQuit = false;
do
{
shouldQuit = processFrame(image, pipeline, drawingCtx);
} while (!shouldQuit);
}
bool processFrame(const cv::Mat& cameraFrame, ARPipeline& pipeline, ARDrawingContext& drawingCtx)
{
// Clone image used for background (we will draw overlay on it)
cv::Mat img = cameraFrame.clone();
// Draw information:
if (pipeline.m_patternDetector.enableHomographyRefinement)
cv::putText(img, "Pose refinement: On ('h' to switch off)", cv::Point(10,15), CV_FONT_HERSHEY_PLAIN, 1, CV_RGB(0,200,0));
else
cv::putText(img, "Pose refinement: Off ('h' to switch on)", cv::Point(10,15), CV_FONT_HERSHEY_PLAIN, 1, CV_RGB(0,200,0));
cv::putText(img, "RANSAC threshold: " + ToString(pipeline.m_patternDetector.homographyReprojectionThreshold) + "( Use'-'/'+' to adjust)", cv::Point(10, 30), CV_FONT_HERSHEY_PLAIN, 1, CV_RGB(0,200,0));
// Set a new camera frame:
drawingCtx.updateBackground(img);
// Find a pattern and update it's detection status:
drawingCtx.isPatternPresent = pipeline.processFrame(cameraFrame);
// Update a pattern pose:
drawingCtx.patternPose = pipeline.getPatternLocation();
// Request redraw of the window:
drawingCtx.updateWindow();
// Read the keyboard input:
int keyCode = cv::waitKey(5);
bool shouldQuit = false;
if (keyCode == '+' || keyCode == '=')
{
pipeline.m_patternDetector.homographyReprojectionThreshold += 0.2f;
pipeline.m_patternDetector.homographyReprojectionThreshold = std::min(10.0f, pipeline.m_patternDetector.homographyReprojectionThreshold);
}
else if (keyCode == '-')
{
pipeline.m_patternDetector.homographyReprojectionThreshold -= 0.2f;
pipeline.m_patternDetector.homographyReprojectionThreshold = std::max(0.0f, pipeline.m_patternDetector.homographyReprojectionThreshold);
}
else if (keyCode == 'h')
{
pipeline.m_patternDetector.enableHomographyRefinement = !pipeline.m_patternDetector.enableHomographyRefinement;
}
else if (keyCode == 27 || keyCode == 'q')
{
shouldQuit = true;
}
return shouldQuit;
}