-
Notifications
You must be signed in to change notification settings - Fork 0
/
BBoxSelector.cpp
138 lines (125 loc) · 4.5 KB
/
BBoxSelector.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
#include <iostream>
#include <fstream>
#include "Utils.hpp"
#include <opencv2/core/utils/filesystem.hpp>
int main(int argc, char** argv)
{
// Expects at least one argument which is the path to a directory containing the images on which the user
// needs to select bounding boxes. It exects jpg images and it will write one txt file for each image in the same
// folder, with the same name as the image it refers to.
std::vector<cv::String> filenames;
std::vector<cv::String> done;
cv::utils::fs::glob(cv::String(argv[1]), cv::String("*.jpg"), filenames);
cv::utils::fs::glob(cv::String(argv[1]), cv::String("*.txt"), done);
cv::namedWindow("BBoxSelector");
std::cout<<filenames.size()<<" images found\n";
// -S option: allows the user to see the bounding boxes they selected
// over the original images. Images will be shown one at a time and
// any input will make the program go to the next image. No interaction with
// the images is possible.
if(argc == 3 and strcmp(argv[2],"-S")==0)
{
// for all images found in the directory
for(const auto& fn: filenames)
{
std::vector<cv::Rect> ROIs;
bool show = false;
// check the txt files found to see if there is one for this image
for(const auto& dn: done)
{
// if there is then load the ROIs from the txt and setup the image to
// be dispalyed
if(filenamesMatch(fn,dn))
{
show = true;
loadROIs(dn,ROIs);
break;
}
}
// if the corresponding txt file was found, then
// draw the loaded ROIs over the image and wait for user input before going to the next image.
if(show)
{
cv::Mat img = cv::imread(fn);
drawROIs(img, ROIs);
cv::imshow("BBoxSelector", img);
cv::waitKey(0);
}
// otherwise just go to the next image in the folder
else
{
std::cout<<"ROIs not found: "<<fn<<"\n";
}
}
}
// -R option: allows the user to see the bounding boxes they selected
// over the original images and draw additional boxes. Images will be shown one at a time,
// and navigation is performed as in the general case. The difference with the general case is that
// it will also show images for which the bounding boxes were already selected.
else if(argc == 3 and strcmp(argv[2],"-R")==0)
{
// for all images found in the directory
for(const auto& fn: filenames)
{
std::vector<cv::Rect> ROIs;
cv::Mat img = cv::imread(fn);
// check the txt files found to see if there is one for this image
for(const auto& dn: done)
{
// if there is then load the ROIs from the txt and draw them over the image.
if(filenamesMatch(fn,dn))
{
loadROIs(dn, ROIs);
drawROIs(img, ROIs);
break;
}
}
// Regardless of whether any previous bounding boxes were found, allow the user to
// draw more bounding boxes over the image
selectROIs("BBoxSelector", img, ROIs);
std::cout<<"\n"<<ROIs.size()<<" ROIs selected\n\n\n";
// After the user is done save the ROIs (old and new)
// to a txt file with the same name as the image
saveROIs(fn.substr(0,fn.size()-4), ROIs);
}
}
// General case: Images are shown one at a time and the user is allowed to draw bounding boxes over them.
// Once the user is satisfied with the drawn bounding box, they can press enter or space to confirm it. When
// the user is done selecting bounding boxes for the current image, they can press enter or space without drawing
// any box to go to the next image. Images for which bounding boxes already exist will be skipped, prompting the user
// with the first image they haven't seen yet.
else
{
// for all images found in the directory
for(const auto& fn: filenames)
{
bool skip = false;
// check the txt files found to see if there is one for this image
for(const auto& dn: done)
{
// if there is then the ROIs were already selected and this image can be skipped.
if(filenamesMatch(fn,dn))
{
skip = true;
break;
}
}
if(skip)
{
std::cout<<"skipping "<<fn<<"\n";
}
else
{
cv::Mat img = cv::imread(fn);
std::vector<cv::Rect> ROIs;
// allow the user to draw bounding boxes over the image
selectROIs("BBoxSelector", img, ROIs);
std::cout<<"\n"<<ROIs.size()<<" ROIs selected\n\n\n";
// After the user is done save the new ROIs
// to a txt file with the same name as the image
saveROIs(fn.substr(0,fn.size()-4), ROIs);
}
}
}
return 0;
}