Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
b922d49a
Commit
b922d49a
authored
Apr 11, 2016
by
StevenPuttemans
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vectorize process + enable early quitting/storage + enable delete annotion option
parent
06ea0aa0
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
88 additions
and
55 deletions
+88
-55
opencv_annotation.cpp
apps/annotation/opencv_annotation.cpp
+88
-55
No files found.
apps/annotation/opencv_annotation.cpp
View file @
b922d49a
...
@@ -46,6 +46,9 @@ USAGE:
...
@@ -46,6 +46,9 @@ USAGE:
./opencv_annotation -images <folder location> -annotations <ouput file>
./opencv_annotation -images <folder location> -annotations <ouput file>
Created by: Puttemans Steven - February 2015
Created by: Puttemans Steven - February 2015
Adapted by: Puttemans Steven - April 2016 - Vectorize the process to enable better processing
+ early leave and store by pressing an ESC key
+ enable delete `d` button, to remove last annotation
*****************************************************************************************************/
*****************************************************************************************************/
#include <opencv2/core.hpp>
#include <opencv2/core.hpp>
...
@@ -68,16 +71,15 @@ using namespace cv;
...
@@ -68,16 +71,15 @@ using namespace cv;
// Function prototypes
// Function prototypes
void
on_mouse
(
int
,
int
,
int
,
int
,
void
*
);
void
on_mouse
(
int
,
int
,
int
,
int
,
void
*
);
string
int2string
(
int
);
vector
<
Rect
>
get_annotations
(
Mat
);
void
get_annotations
(
Mat
,
stringstream
*
);
// Public parameters
// Public parameters
Mat
image
;
Mat
image
;
int
roi_x0
=
0
,
roi_y0
=
0
,
roi_x1
=
0
,
roi_y1
=
0
,
num_of_rec
=
0
;
int
roi_x0
=
0
,
roi_y0
=
0
,
roi_x1
=
0
,
roi_y1
=
0
,
num_of_rec
=
0
;
bool
start_draw
=
false
;
bool
start_draw
=
false
,
stop
=
false
;
// Window name for visualisation purposes
// Window name for visualisation purposes
const
string
window_name
=
"OpenCV Based Annotation Tool"
;
const
string
window_name
=
"OpenCV Based Annotation Tool"
;
// FUNCTION : Mouse response for selecting objects in images
// FUNCTION : Mouse response for selecting objects in images
// If left button is clicked, start drawing a rectangle as long as mouse moves
// If left button is clicked, start drawing a rectangle as long as mouse moves
...
@@ -98,7 +100,8 @@ void on_mouse(int event, int x, int y, int , void * )
...
@@ -98,7 +100,8 @@ void on_mouse(int event, int x, int y, int , void * )
start_draw
=
false
;
start_draw
=
false
;
}
}
}
}
// Action when mouse is moving
// Action when mouse is moving and drawing is enabled
if
((
event
==
EVENT_MOUSEMOVE
)
&&
start_draw
)
if
((
event
==
EVENT_MOUSEMOVE
)
&&
start_draw
)
{
{
// Redraw bounding box for annotation
// Redraw bounding box for annotation
...
@@ -109,42 +112,34 @@ void on_mouse(int event, int x, int y, int , void * )
...
@@ -109,42 +112,34 @@ void on_mouse(int event, int x, int y, int , void * )
}
}
}
}
// FUNCTION : snippet to convert an integer value to a string using a clean function
// FUNCTION : returns a vector of Rect objects given an image containing positive object instances
// instead of creating a stringstream each time inside the main code
vector
<
Rect
>
get_annotations
(
Mat
input_image
)
string
int2string
(
int
num
)
{
{
stringstream
temp_stream
;
vector
<
Rect
>
current_annotations
;
temp_stream
<<
num
;
return
temp_stream
.
str
();
}
// FUNCTION : given an image containing positive object instances, add all the object
// Make it possible to exit the annotation process
// annotations to a known stringstream
stop
=
false
;
void
get_annotations
(
Mat
input_image
,
stringstream
*
output_stream
)
{
// Make it possible to exit the annotation
bool
stop
=
false
;
// Reset the num_of_rec element at each iteration
// Make sure the global image is set to the current image
num_of_rec
=
0
;
image
=
input_image
;
// Init window interface and couple mouse actions
// Init window interface and couple mouse actions
namedWindow
(
window_name
,
WINDOW_AUTOSIZE
);
namedWindow
(
window_name
,
WINDOW_AUTOSIZE
);
setMouseCallback
(
window_name
,
on_mouse
);
setMouseCallback
(
window_name
,
on_mouse
);
image
=
input_image
;
imshow
(
window_name
,
image
);
imshow
(
window_name
,
image
);
stringstream
temp_stream
;
int
key_pressed
=
0
;
int
key_pressed
=
0
;
do
do
{
{
// Get a temporary image clone
Mat
temp_image
=
input_image
.
clone
();
Rect
currentRect
(
0
,
0
,
0
,
0
);
// Keys for processing
// Keys for processing
// You need to select one for confirming a selection and one to continue to the next image
// You need to select one for confirming a selection and one to continue to the next image
// Based on the universal ASCII code of the keystroke: http://www.asciitable.com/
// Based on the universal ASCII code of the keystroke: http://www.asciitable.com/
// c = 99 add rectangle to current image
// c = 99 add rectangle to current image
// n = 110 save added rectangles and show next image
// n = 110 save added rectangles and show next image
// d = 100 delete the last annotation made
// <ESC> = 27 exit program
// <ESC> = 27 exit program
key_pressed
=
0xFF
&
waitKey
(
0
);
key_pressed
=
0xFF
&
waitKey
(
0
);
switch
(
key_pressed
)
switch
(
key_pressed
)
...
@@ -154,31 +149,51 @@ void get_annotations(Mat input_image, stringstream* output_stream)
...
@@ -154,31 +149,51 @@ void get_annotations(Mat input_image, stringstream* output_stream)
stop
=
true
;
stop
=
true
;
break
;
break
;
case
99
:
case
99
:
// Add a rectangle to the list
num_of_rec
++
;
// Draw initiated from top left corner
// Draw initiated from top left corner
if
(
roi_x0
<
roi_x1
&&
roi_y0
<
roi_y1
)
if
(
roi_x0
<
roi_x1
&&
roi_y0
<
roi_y1
)
{
{
temp_stream
<<
" "
<<
int2string
(
roi_x0
)
<<
" "
<<
int2string
(
roi_y0
)
<<
" "
<<
int2string
(
roi_x1
-
roi_x0
)
<<
" "
<<
int2string
(
roi_y1
-
roi_y0
);
currentRect
.
x
=
roi_x0
;
currentRect
.
y
=
roi_y0
;
currentRect
.
width
=
roi_x1
-
roi_x0
;
currentRect
.
height
=
roi_y1
-
roi_y0
;
}
}
// Draw initiated from bottom right corner
// Draw initiated from bottom right corner
if
(
roi_x0
>
roi_x1
&&
roi_y0
>
roi_y1
)
if
(
roi_x0
>
roi_x1
&&
roi_y0
>
roi_y1
)
{
{
temp_stream
<<
" "
<<
int2string
(
roi_x1
)
<<
" "
<<
int2string
(
roi_y1
)
<<
" "
<<
int2string
(
roi_x0
-
roi_x1
)
<<
" "
<<
int2string
(
roi_y0
-
roi_y1
);
currentRect
.
x
=
roi_x1
;
currentRect
.
y
=
roi_y1
;
currentRect
.
width
=
roi_x0
-
roi_x1
;
currentRect
.
height
=
roi_y0
-
roi_y1
;
}
}
// Draw initiated from top right corner
// Draw initiated from top right corner
if
(
roi_x0
>
roi_x1
&&
roi_y0
<
roi_y1
)
if
(
roi_x0
>
roi_x1
&&
roi_y0
<
roi_y1
)
{
{
temp_stream
<<
" "
<<
int2string
(
roi_x1
)
<<
" "
<<
int2string
(
roi_y0
)
<<
" "
<<
int2string
(
roi_x0
-
roi_x1
)
<<
" "
<<
int2string
(
roi_y1
-
roi_y0
);
currentRect
.
x
=
roi_x1
;
currentRect
.
y
=
roi_y0
;
currentRect
.
width
=
roi_x0
-
roi_x1
;
currentRect
.
height
=
roi_y1
-
roi_y0
;
}
}
// Draw initiated from bottom left corner
// Draw initiated from bottom left corner
if
(
roi_x0
<
roi_x1
&&
roi_y0
>
roi_y1
)
if
(
roi_x0
<
roi_x1
&&
roi_y0
>
roi_y1
)
{
{
temp_stream
<<
" "
<<
int2string
(
roi_x0
)
<<
" "
<<
int2string
(
roi_y1
)
<<
" "
<<
int2string
(
roi_x1
-
roi_x0
)
<<
" "
<<
int2string
(
roi_y0
-
roi_y1
);
currentRect
.
x
=
roi_x0
;
currentRect
.
y
=
roi_y1
;
currentRect
.
width
=
roi_x1
-
roi_x0
;
currentRect
.
height
=
roi_y0
-
roi_y1
;
}
}
// Draw the rectangle on the canvas
rectangle
(
input_image
,
Point
(
roi_x0
,
roi_y0
),
Point
(
roi_x1
,
roi_y1
),
Scalar
(
0
,
255
,
0
),
1
);
// Add the rectangle to the vector of annotations
current_annotations
.
push_back
(
currentRect
);
break
;
case
100
:
// Remove the last annotation
if
(
current_annotations
.
size
()
>
0
){
current_annotations
.
pop_back
();
}
break
;
default
:
// Default case --> do nothing at all
// Other keystrokes can simply be ignored
break
;
break
;
}
}
...
@@ -187,19 +202,24 @@ void get_annotations(Mat input_image, stringstream* output_stream)
...
@@ -187,19 +202,24 @@ void get_annotations(Mat input_image, stringstream* output_stream)
{
{
break
;
break
;
}
}
// Draw all the current rectangles onto the top image and make sure that the global image is linked
for
(
int
i
=
0
;
i
<
(
int
)
current_annotations
.
size
();
i
++
){
rectangle
(
temp_image
,
current_annotations
[
i
],
Scalar
(
0
,
255
,
0
),
1
);
}
}
// Continue as long as the next image key has not been pressed
image
=
temp_image
;
while
(
key_pressed
!=
110
);
// If there are annotations AND the next image key is pressed
// Force an explicit redraw of the canvas --> necessary to visualize delete correctly
// Write the image annotations to the file
imshow
(
window_name
,
image
);
if
(
num_of_rec
>
0
&&
key_pressed
==
110
)
{
*
output_stream
<<
" "
<<
num_of_rec
<<
temp_stream
.
str
()
<<
endl
;
}
}
// Continue as long as the next image key has not been pressed
while
(
key_pressed
!=
110
);
// Close down the window
// Close down the window
destroyWindow
(
window_name
);
destroyWindow
(
window_name
);
// Return the data
return
current_annotations
;
}
}
int
main
(
int
argc
,
const
char
**
argv
)
int
main
(
int
argc
,
const
char
**
argv
)
...
@@ -209,13 +229,13 @@ int main( int argc, const char** argv )
...
@@ -209,13 +229,13 @@ int main( int argc, const char** argv )
cout
<<
"Usage: "
<<
argv
[
0
]
<<
endl
;
cout
<<
"Usage: "
<<
argv
[
0
]
<<
endl
;
cout
<<
" -images <folder_location> [example - /data/testimages/]"
<<
endl
;
cout
<<
" -images <folder_location> [example - /data/testimages/]"
<<
endl
;
cout
<<
" -annotations <ouput_file> [example - /data/annotations.txt]"
<<
endl
;
cout
<<
" -annotations <ouput_file> [example - /data/annotations.txt]"
<<
endl
;
cout
<<
"TIP: Use absolute paths to avoid any problems with the software!"
<<
endl
;
return
-
1
;
return
-
1
;
}
}
// Read in the input arguments
// Read in the input arguments
string
image_folder
;
string
image_folder
;
string
annotations
;
string
annotations
_file
;
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
{
if
(
!
strcmp
(
argv
[
i
],
"-images"
)
)
if
(
!
strcmp
(
argv
[
i
],
"-images"
)
)
...
@@ -224,7 +244,7 @@ int main( int argc, const char** argv )
...
@@ -224,7 +244,7 @@ int main( int argc, const char** argv )
}
}
else
if
(
!
strcmp
(
argv
[
i
],
"-annotations"
)
)
else
if
(
!
strcmp
(
argv
[
i
],
"-annotations"
)
)
{
{
annotations
=
argv
[
++
i
];
annotations
_file
=
argv
[
++
i
];
}
}
}
}
...
@@ -249,14 +269,9 @@ int main( int argc, const char** argv )
...
@@ -249,14 +269,9 @@ int main( int argc, const char** argv )
}
}
#endif
#endif
// Create the outputfilestream
// Start by processing the data
ofstream
output
(
annotations
.
c_str
());
if
(
!
output
.
is_open
()
){
cerr
<<
"The path for the output file contains an error and could not be opened. Please check again!"
<<
endl
;
return
0
;
}
// Return the image filenames inside the image folder
// Return the image filenames inside the image folder
vector
<
vector
<
Rect
>
>
annotations
;
vector
<
String
>
filenames
;
vector
<
String
>
filenames
;
String
folder
(
image_folder
);
String
folder
(
image_folder
);
glob
(
folder
,
filenames
);
glob
(
folder
,
filenames
);
...
@@ -274,14 +289,32 @@ int main( int argc, const char** argv )
...
@@ -274,14 +289,32 @@ int main( int argc, const char** argv )
continue
;
continue
;
}
}
// Perform annotations & generate corresponding output
// Perform annotations & store the result inside the vectorized structure
stringstream
output_stream
;
vector
<
Rect
>
current_annotations
=
get_annotations
(
current_image
);
get_annotations
(
current_image
,
&
output_stream
);
annotations
.
push_back
(
current_annotations
);
// Check if the ESC key was hit, then exit earlier then expected
if
(
stop
){
break
;
}
}
// When all data is processed, store the data gathered inside the proper file
// This now even gets called when the ESC button was hit to store preliminary results
ofstream
output
(
annotations_file
.
c_str
());
if
(
!
output
.
is_open
()
){
cerr
<<
"The path for the output file contains an error and could not be opened. Please check again!"
<<
endl
;
return
0
;
}
// Store the annotations, write to the output file
// Store the annotations, write to the output file
if
(
output_stream
.
str
()
!=
""
){
for
(
int
i
=
0
;
i
<
(
int
)
annotations
.
size
();
i
++
){
output
<<
filenames
[
i
]
<<
output_stream
.
str
();
output
<<
filenames
[
i
]
<<
" "
<<
annotations
[
i
].
size
();
for
(
int
j
=
0
;
j
<
(
int
)
annotations
[
i
].
size
();
j
++
){
Rect
temp
=
annotations
[
i
][
j
];
output
<<
" "
<<
temp
.
x
<<
" "
<<
temp
.
y
<<
" "
<<
temp
.
width
<<
" "
<<
temp
.
height
;
}
}
output
<<
endl
;
}
}
return
0
;
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment