Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hackassin
GitHub Repository: hackassin/learnopencv
Path: blob/master/AugmentedRealityWithArucoMarkers/augmented_reality_with_aruco.cpp
3092 views
1
// This code is written by Sunita Nayak at BigVision LLC. It is based on the OpenCV project. It is subject to the license terms in the LICENSE file found in this distribution and at http://opencv.org/license.html
2
3
// Usage example: ./augmented_reality_with_aruco.out --image=test.jpg
4
// ./augmented_reality_with_aruco.out --video=test.mp4
5
#include <fstream>
6
#include <sstream>
7
#include <iostream>
8
9
#include <opencv2/aruco.hpp>
10
#include <opencv2/imgproc.hpp>
11
#include <opencv2/highgui.hpp>
12
#include <opencv2/calib3d.hpp>
13
14
const char* keys =
15
"{help h usage ? | | Usage examples: \n\t\t./augmented_reality_with_aruco.out --image=test.jpg \n\t\t./augmented_reality_with_aruco.out --video=test.mp4}"
16
"{image i |<none>| input image }"
17
"{video v |<none>| input video }"
18
;
19
using namespace cv;
20
using namespace aruco;
21
using namespace std;
22
23
int main(int argc, char** argv)
24
{
25
CommandLineParser parser(argc, argv, keys);
26
parser.about("Use this script to do Augmented Reality using Aruco markers in OpenCV.");
27
if (parser.has("help"))
28
{
29
parser.printMessage();
30
return 0;
31
}
32
// Open a video file or an image file or a camera stream.
33
string str, outputFile;
34
VideoCapture cap;
35
VideoWriter video;
36
Mat frame, blob;
37
38
Mat im_src = imread("new_scenery.jpg");
39
40
try {
41
42
outputFile = "ar_out_cpp.avi";
43
if (parser.has("image"))
44
{
45
// Open the image file
46
str = parser.get<String>("image");
47
ifstream ifile(str);
48
if (!ifile) throw("error");
49
cap.open(str);
50
str.replace(str.end()-4, str.end(), "_ar_out_cpp.jpg");
51
outputFile = str;
52
}
53
else if (parser.has("video"))
54
{
55
// Open the video file
56
str = parser.get<String>("video");
57
ifstream ifile(str);
58
if (!ifile) throw("error");
59
cap.open(str);
60
str.replace(str.end()-4, str.end(), "_ar_out_cpp.avi");
61
outputFile = str;
62
}
63
// Open the webcaom
64
else cap.open(parser.get<int>("device"));
65
66
}
67
catch(...) {
68
cout << "Could not open the input image/video stream" << endl;
69
return 0;
70
}
71
72
// Get the video writer initialized to save the output video
73
if (!parser.has("image")) {
74
video.open(outputFile, VideoWriter::fourcc('M','J','P','G'), 28, Size(2*cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));
75
}
76
77
// Create a window
78
static const string kWinName = "Augmented Reality using Aruco markers in OpenCV";
79
namedWindow(kWinName, WINDOW_NORMAL);
80
81
// Process frames.
82
while (waitKey(1) < 0)
83
{
84
// get frame from the video
85
cap >> frame;
86
87
try {
88
// Stop the program if reached end of video
89
if (frame.empty()) {
90
cout << "Done processing !!!" << endl;
91
cout << "Output file is stored as " << outputFile << endl;
92
waitKey(3000);
93
break;
94
}
95
96
vector<int> markerIds;
97
98
// Load the dictionary that was used to generate the markers.
99
Ptr<Dictionary> dictionary = getPredefinedDictionary(DICT_6X6_250);
100
101
// Declare the vectors that would contain the detected marker corners and the rejected marker candidates
102
vector<vector<Point2f>> markerCorners, rejectedCandidates;
103
104
// Initialize the detector parameters using default values
105
Ptr<DetectorParameters> parameters = DetectorParameters::create();
106
107
// Detect the markers in the image
108
detectMarkers(frame, dictionary, markerCorners, markerIds, parameters, rejectedCandidates);
109
110
// Using the detected markers, locate the quadrilateral on the target frame where the new scene is going to be displayed.
111
vector<Point> pts_dst;
112
float scalingFac = 0.02;//0.015;
113
114
Point refPt1, refPt2, refPt3, refPt4;
115
116
// finding top left corner point of the target quadrilateral
117
std::vector<int>::iterator it = std::find(markerIds.begin(), markerIds.end(), 25);
118
int index = std::distance(markerIds.begin(), it);
119
refPt1 = markerCorners.at(index).at(1);
120
121
// finding top right corner point of the target quadrilateral
122
it = std::find(markerIds.begin(), markerIds.end(), 33);
123
index = std::distance(markerIds.begin(), it);
124
refPt2 = markerCorners.at(index).at(2);
125
126
float distance = norm(refPt1-refPt2);
127
pts_dst.push_back(Point(refPt1.x - round(scalingFac*distance), refPt1.y - round(scalingFac*distance)));
128
129
pts_dst.push_back(Point(refPt2.x + round(scalingFac*distance), refPt2.y - round(scalingFac*distance)));
130
131
// finding bottom right corner point of the target quadrilateral
132
it = std::find(markerIds.begin(), markerIds.end(), 30);
133
index = std::distance(markerIds.begin(), it);
134
refPt3 = markerCorners.at(index).at(0);
135
pts_dst.push_back(Point(refPt3.x + round(scalingFac*distance), refPt3.y + round(scalingFac*distance)));
136
137
// finding bottom left corner point of the target quadrilateral
138
it = std::find(markerIds.begin(), markerIds.end(), 23);
139
index = std::distance(markerIds.begin(), it);
140
refPt4 = markerCorners.at(index).at(0);
141
pts_dst.push_back(Point(refPt4.x - round(scalingFac*distance), refPt4.y + round(scalingFac*distance)));
142
143
// Get the corner points of the new scene image.
144
vector<Point> pts_src;
145
pts_src.push_back(Point(0,0));
146
pts_src.push_back(Point(im_src.cols, 0));
147
pts_src.push_back(Point(im_src.cols, im_src.rows));
148
pts_src.push_back(Point(0, im_src.rows));
149
150
// Compute homography from source and destination points
151
Mat h = cv::findHomography(pts_src, pts_dst);
152
153
// Warped image
154
Mat warpedImage;
155
156
// Warp source image to destination based on homography
157
warpPerspective(im_src, warpedImage, h, frame.size(), INTER_CUBIC);
158
159
// Prepare a mask representing region to copy from the warped image into the original frame.
160
Mat mask = Mat::zeros(frame.rows, frame.cols, CV_8UC1);
161
fillConvexPoly(mask, pts_dst, Scalar(255, 255, 255), LINE_AA);
162
163
// Erode the mask to not copy the boundary effects from the warping
164
Mat element = getStructuringElement( MORPH_RECT, Size(5,5));
165
// Mat element = getStructuringElement( MORPH_RECT, Size(3,3));
166
erode(mask, mask, element);
167
168
// Copy the warped image into the original frame in the mask region.
169
Mat imOut = frame.clone();
170
warpedImage.copyTo(imOut, mask);
171
172
// Showing the original image and the new output image side by side
173
Mat concatenatedOutput;
174
hconcat(frame, imOut, concatenatedOutput);
175
176
if (parser.has("image")) imwrite(outputFile, concatenatedOutput);
177
else video.write(concatenatedOutput);
178
179
imshow(kWinName, concatenatedOutput);
180
181
}
182
catch(const std::exception& e) {
183
cout << endl << " e : " << e.what() << endl;
184
cout << "Could not do homography !! " << endl;
185
// return 0;
186
}
187
188
}
189
190
cap.release();
191
if (!parser.has("image")) video.release();
192
193
return 0;
194
}
195
196