Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
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_contrib
Commits
f073c003
Commit
f073c003
authored
Mar 22, 2016
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #528 from lluisgomez:master
parents
6cd8e9f5
f07a00cf
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
189 additions
and
14 deletions
+189
-14
erfilter.hpp
modules/text/include/opencv2/text/erfilter.hpp
+21
-11
detect_er_chars.py
modules/text/samples/detect_er_chars.py
+39
-0
textdetection.py
modules/text/samples/textdetection.py
+60
-0
erfilter.cpp
modules/text/src/erfilter.cpp
+69
-3
No files found.
modules/text/include/opencv2/text/erfilter.hpp
View file @
f073c003
...
@@ -115,7 +115,7 @@ public:
...
@@ -115,7 +115,7 @@ public:
Extracts the component tree (if needed) and filter the extremal regions (ER's) by using a given classifier.
Extracts the component tree (if needed) and filter the extremal regions (ER's) by using a given classifier.
*/
*/
class
CV_EXPORTS
ERFilter
:
public
Algorithm
class
CV_EXPORTS
_W
ERFilter
:
public
Algorithm
{
{
public
:
public
:
...
@@ -124,7 +124,7 @@ public:
...
@@ -124,7 +124,7 @@ public:
By doing it we hide SVM, Boost etc. Developers can provide their own classifiers to the
By doing it we hide SVM, Boost etc. Developers can provide their own classifiers to the
ERFilter algorithm.
ERFilter algorithm.
*/
*/
class
CV_EXPORTS
Callback
class
CV_EXPORTS
_W
Callback
{
{
public
:
public
:
virtual
~
Callback
()
{
}
virtual
~
Callback
()
{
}
...
@@ -207,11 +207,11 @@ the probability P(er|character) are selected (if the local maximum of the probab
...
@@ -207,11 +207,11 @@ the probability P(er|character) are selected (if the local maximum of the probab
global limit pmin and the difference between local maximum and local minimum is greater than
global limit pmin and the difference between local maximum and local minimum is greater than
minProbabilityDiff).
minProbabilityDiff).
*/
*/
CV_EXPORTS
Ptr
<
ERFilter
>
createERFilterNM1
(
const
Ptr
<
ERFilter
::
Callback
>&
cb
,
CV_EXPORTS
_W
Ptr
<
ERFilter
>
createERFilterNM1
(
const
Ptr
<
ERFilter
::
Callback
>&
cb
,
int
thresholdDelta
=
1
,
float
minArea
=
0.00025
,
int
thresholdDelta
=
1
,
float
minArea
=
(
float
)
0.00025
,
float
maxArea
=
0.13
,
float
minProbability
=
0.4
,
float
maxArea
=
(
float
)
0.13
,
float
minProbability
=
(
float
)
0.4
,
bool
nonMaxSuppression
=
true
,
bool
nonMaxSuppression
=
true
,
float
minProbabilityDiff
=
0.1
);
float
minProbabilityDiff
=
(
float
)
0.1
);
/** @brief Create an Extremal Region Filter for the 2nd stage classifier of N&M algorithm [Neumann12].
/** @brief Create an Extremal Region Filter for the 2nd stage classifier of N&M algorithm [Neumann12].
...
@@ -224,8 +224,8 @@ non-character classes using more informative but also more computationally expen
...
@@ -224,8 +224,8 @@ non-character classes using more informative but also more computationally expen
classifier uses all the features calculated in the first stage and the following additional
classifier uses all the features calculated in the first stage and the following additional
features: hole area ratio, convex hull ratio, and number of outer inflexion points.
features: hole area ratio, convex hull ratio, and number of outer inflexion points.
*/
*/
CV_EXPORTS
Ptr
<
ERFilter
>
createERFilterNM2
(
const
Ptr
<
ERFilter
::
Callback
>&
cb
,
CV_EXPORTS
_W
Ptr
<
ERFilter
>
createERFilterNM2
(
const
Ptr
<
ERFilter
::
Callback
>&
cb
,
float
minProbability
=
0.3
);
float
minProbability
=
(
float
)
0.3
);
/** @brief Allow to implicitly load the default classifier when creating an ERFilter object.
/** @brief Allow to implicitly load the default classifier when creating an ERFilter object.
...
@@ -234,7 +234,7 @@ CV_EXPORTS Ptr<ERFilter> createERFilterNM2(const Ptr<ERFilter::Callback>& cb,
...
@@ -234,7 +234,7 @@ CV_EXPORTS Ptr<ERFilter> createERFilterNM2(const Ptr<ERFilter::Callback>& cb,
returns a pointer to ERFilter::Callback.
returns a pointer to ERFilter::Callback.
*/
*/
CV_EXPORTS
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM1
(
const
std
::
s
tring
&
filename
);
CV_EXPORTS
_W
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM1
(
const
S
tring
&
filename
);
/** @brief Allow to implicitly load the default classifier when creating an ERFilter object.
/** @brief Allow to implicitly load the default classifier when creating an ERFilter object.
...
@@ -242,7 +242,7 @@ CV_EXPORTS Ptr<ERFilter::Callback> loadClassifierNM1(const std::string& filename
...
@@ -242,7 +242,7 @@ CV_EXPORTS Ptr<ERFilter::Callback> loadClassifierNM1(const std::string& filename
returns a pointer to ERFilter::Callback.
returns a pointer to ERFilter::Callback.
*/
*/
CV_EXPORTS
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM2
(
const
std
::
s
tring
&
filename
);
CV_EXPORTS
_W
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM2
(
const
S
tring
&
filename
);
//! computeNMChannels operation modes
//! computeNMChannels operation modes
...
@@ -264,7 +264,7 @@ channels (Grad) are used in order to obtain high localization recall. This imple
...
@@ -264,7 +264,7 @@ channels (Grad) are used in order to obtain high localization recall. This imple
provides an alternative combination of red (R), green (G), blue (B), lightness (L), and gradient
provides an alternative combination of red (R), green (G), blue (B), lightness (L), and gradient
magnitude (Grad).
magnitude (Grad).
*/
*/
CV_EXPORTS
void
computeNMChannels
(
InputArray
_src
,
OutputArrayOfArrays
_channels
,
int
_mode
=
ERFILTER_NM_RGBLGrad
);
CV_EXPORTS
_W
void
computeNMChannels
(
InputArray
_src
,
CV_OUT
OutputArrayOfArrays
_channels
,
int
_mode
=
ERFILTER_NM_RGBLGrad
);
...
@@ -324,6 +324,13 @@ CV_EXPORTS void erGrouping(InputArray img, InputArrayOfArrays channels,
...
@@ -324,6 +324,13 @@ CV_EXPORTS void erGrouping(InputArray img, InputArrayOfArrays channels,
const
std
::
string
&
filename
=
std
::
string
(),
const
std
::
string
&
filename
=
std
::
string
(),
float
minProbablity
=
0.5
);
float
minProbablity
=
0.5
);
CV_EXPORTS_W
void
erGrouping
(
InputArray
image
,
InputArray
channel
,
std
::
vector
<
std
::
vector
<
Point
>
>
regions
,
CV_OUT
std
::
vector
<
Rect
>
&
groups_rects
,
int
method
=
ERGROUPING_ORIENTATION_HORIZ
,
const
String
&
filename
=
String
(),
float
minProbablity
=
(
float
)
0.5
);
/** @brief Converts MSER contours (vector\<Point\>) to ERStat regions.
/** @brief Converts MSER contours (vector\<Point\>) to ERStat regions.
@param image Source image CV_8UC1 from which the MSERs where extracted.
@param image Source image CV_8UC1 from which the MSERs where extracted.
...
@@ -343,6 +350,9 @@ An example of MSERsToERStats in use can be found in the text detection webcam_de
...
@@ -343,6 +350,9 @@ An example of MSERsToERStats in use can be found in the text detection webcam_de
CV_EXPORTS
void
MSERsToERStats
(
InputArray
image
,
std
::
vector
<
std
::
vector
<
Point
>
>
&
contours
,
CV_EXPORTS
void
MSERsToERStats
(
InputArray
image
,
std
::
vector
<
std
::
vector
<
Point
>
>
&
contours
,
std
::
vector
<
std
::
vector
<
ERStat
>
>
&
regions
);
std
::
vector
<
std
::
vector
<
ERStat
>
>
&
regions
);
// Utility funtion for scripting
CV_EXPORTS_W
void
detectRegions
(
InputArray
image
,
const
Ptr
<
ERFilter
>&
er_filter1
,
const
Ptr
<
ERFilter
>&
er_filter2
,
CV_OUT
std
::
vector
<
std
::
vector
<
Point
>
>&
regions
);
//! @}
//! @}
}
}
...
...
modules/text/samples/detect_er_chars.py
0 → 100644
View file @
f073c003
#!/usr/bin/python
import
sys
import
os
import
cv2
import
numpy
as
np
from
matplotlib
import
pyplot
as
plt
print
(
'
\n
detect_er_chars.py'
)
print
(
' A simple demo script using the Extremal Region Filter algorithm described in:'
)
print
(
' Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012
\n
'
)
if
(
len
(
sys
.
argv
)
<
2
):
print
(
' (ERROR) You must call this script with an argument (path_to_image_to_be_processed)
\n
'
)
quit
()
pathname
=
os
.
path
.
dirname
(
sys
.
argv
[
0
])
img
=
cv2
.
imread
(
str
(
sys
.
argv
[
1
]))
gray
=
cv2
.
imread
(
str
(
sys
.
argv
[
1
]),
0
)
erc1
=
cv2
.
text
.
loadClassifierNM1
(
pathname
+
'/trained_classifierNM1.xml'
)
er1
=
cv2
.
text
.
createERFilterNM1
(
erc1
)
erc2
=
cv2
.
text
.
loadClassifierNM2
(
pathname
+
'/trained_classifierNM2.xml'
)
er2
=
cv2
.
text
.
createERFilterNM2
(
erc2
)
regions
=
cv2
.
text
.
detectRegions
(
gray
,
er1
,
er2
)
#Visualization
rects
=
[
cv2
.
boundingRect
(
p
.
reshape
(
-
1
,
1
,
2
))
for
p
in
regions
]
for
rect
in
rects
:
cv2
.
rectangle
(
img
,
rect
[
0
:
2
],
(
rect
[
0
]
+
rect
[
2
],
rect
[
1
]
+
rect
[
3
]),
(
0
,
0
,
255
),
2
)
img
=
img
[:,:,::
-
1
]
#flip the colors dimension from BGR to RGB
plt
.
imshow
(
img
)
plt
.
xticks
([]),
plt
.
yticks
([])
# to hide tick values on X and Y axis
plt
.
show
()
modules/text/samples/textdetection.py
0 → 100644
View file @
f073c003
#!/usr/bin/python
import
sys
import
os
import
cv2
import
numpy
as
np
from
matplotlib
import
pyplot
as
plt
print
(
'
\n
textdetection.py'
)
print
(
' A demo script of the Extremal Region Filter algorithm described in:'
)
print
(
' Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012
\n
'
)
if
(
len
(
sys
.
argv
)
<
2
):
print
(
' (ERROR) You must call this script with an argument (path_to_image_to_be_processed)
\n
'
)
quit
()
pathname
=
os
.
path
.
dirname
(
sys
.
argv
[
0
])
img
=
cv2
.
imread
(
str
(
sys
.
argv
[
1
]))
# for visualization
vis
=
img
.
copy
()
# Extract channels to be processed individually
channels
=
cv2
.
text
.
computeNMChannels
(
img
)
# Append negative channels to detect ER- (bright regions over dark background)
cn
=
len
(
channels
)
-
1
for
c
in
range
(
0
,
cn
):
channels
.
append
((
255
-
channels
[
c
]))
# Apply the default cascade classifier to each independent channel (could be done in parallel)
print
(
"Extracting Class Specific Extremal Regions from "
+
str
(
len
(
channels
))
+
" channels ..."
)
print
(
" (...) this may take a while (...)"
)
for
channel
in
channels
:
erc1
=
cv2
.
text
.
loadClassifierNM1
(
pathname
+
'/trained_classifierNM1.xml'
)
er1
=
cv2
.
text
.
createERFilterNM1
(
erc1
,
16
,
0.00015
,
0.13
,
0.2
,
True
,
0.1
)
erc2
=
cv2
.
text
.
loadClassifierNM2
(
pathname
+
'/trained_classifierNM2.xml'
)
er2
=
cv2
.
text
.
createERFilterNM2
(
erc2
,
0.5
)
regions
=
cv2
.
text
.
detectRegions
(
channel
,
er1
,
er2
)
rects
=
cv2
.
text
.
erGrouping
(
img
,
channel
,[
r
.
tolist
()
for
r
in
regions
])
#rects = cv2.text.erGrouping(img,gray,[x.tolist() for x in regions], cv2.text.ERGROUPING_ORIENTATION_ANY,'../../GSoC2014/opencv_contrib/modules/text/samples/trained_classifier_erGrouping.xml',0.5)
#Visualization
for
r
in
range
(
0
,
np
.
shape
(
rects
)[
0
]):
rect
=
rects
[
r
]
cv2
.
rectangle
(
vis
,
(
rect
[
0
],
rect
[
1
]),
(
rect
[
0
]
+
rect
[
2
],
rect
[
1
]
+
rect
[
3
]),
(
0
,
255
,
255
),
2
)
#Visualization
vis
=
vis
[:,:,::
-
1
]
#flip the colors dimension from BGR to RGB
plt
.
imshow
(
vis
)
plt
.
xticks
([]),
plt
.
yticks
([])
# to hide tick values on X and Y axis
plt
.
show
()
modules/text/src/erfilter.cpp
View file @
f073c003
...
@@ -1161,7 +1161,7 @@ Ptr<ERFilter> createERFilterNM2(const Ptr<ERFilter::Callback>& cb, float minProb
...
@@ -1161,7 +1161,7 @@ Ptr<ERFilter> createERFilterNM2(const Ptr<ERFilter::Callback>& cb, float minProb
The function takes as parameter the XML or YAML file with the classifier model
The function takes as parameter the XML or YAML file with the classifier model
(e.g. trained_classifierNM1.xml) returns a pointer to ERFilter::Callback.
(e.g. trained_classifierNM1.xml) returns a pointer to ERFilter::Callback.
*/
*/
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM1
(
const
s
tring
&
filename
)
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM1
(
const
S
tring
&
filename
)
{
{
return
makePtr
<
ERClassifierNM1
>
(
filename
);
return
makePtr
<
ERClassifierNM1
>
(
filename
);
...
@@ -1172,7 +1172,7 @@ Ptr<ERFilter::Callback> loadClassifierNM1(const string& filename)
...
@@ -1172,7 +1172,7 @@ Ptr<ERFilter::Callback> loadClassifierNM1(const string& filename)
The function takes as parameter the XML or YAML file with the classifier model
The function takes as parameter the XML or YAML file with the classifier model
(e.g. trained_classifierNM2.xml) returns a pointer to ERFilter::Callback.
(e.g. trained_classifierNM2.xml) returns a pointer to ERFilter::Callback.
*/
*/
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM2
(
const
s
tring
&
filename
)
Ptr
<
ERFilter
::
Callback
>
loadClassifierNM2
(
const
S
tring
&
filename
)
{
{
return
makePtr
<
ERClassifierNM2
>
(
filename
);
return
makePtr
<
ERClassifierNM2
>
(
filename
);
}
}
...
@@ -1236,7 +1236,7 @@ void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude)
...
@@ -1236,7 +1236,7 @@ void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude)
ERFILTER_NM_RGBLGrad and ERFILTER_NM_IHSGrad.
ERFILTER_NM_RGBLGrad and ERFILTER_NM_IHSGrad.
*/
*/
void
computeNMChannels
(
InputArray
_src
,
OutputArrayOfArrays
_channels
,
int
_mode
)
void
computeNMChannels
(
InputArray
_src
,
CV_OUT
OutputArrayOfArrays
_channels
,
int
_mode
)
{
{
CV_Assert
(
(
_mode
==
ERFILTER_NM_RGBLGrad
)
||
(
_mode
==
ERFILTER_NM_IHSGrad
)
);
CV_Assert
(
(
_mode
==
ERFILTER_NM_RGBLGrad
)
||
(
_mode
==
ERFILTER_NM_IHSGrad
)
);
...
@@ -4094,6 +4094,22 @@ void erGrouping(InputArray image, InputArrayOfArrays channels, vector<vector<ERS
...
@@ -4094,6 +4094,22 @@ void erGrouping(InputArray image, InputArrayOfArrays channels, vector<vector<ERS
}
}
void
erGrouping
(
InputArray
image
,
InputArray
channel
,
vector
<
vector
<
Point
>
>
contours
,
CV_OUT
std
::
vector
<
Rect
>
&
groups_rects
,
int
method
,
const
String
&
filename
,
float
minProbability
)
{
CV_Assert
(
image
.
getMat
().
type
()
==
CV_8UC3
);
CV_Assert
(
channel
.
getMat
().
type
()
==
CV_8UC1
);
CV_Assert
(
!
((
method
==
ERGROUPING_ORIENTATION_ANY
)
&&
(
filename
.
empty
()))
);
vector
<
Mat
>
channels
;
channels
.
push_back
(
channel
.
getMat
());
vector
<
vector
<
ERStat
>
>
regions
;
MSERsToERStats
(
channel
,
contours
,
regions
);
regions
.
pop_back
();
std
::
vector
<
std
::
vector
<
Vec2i
>
>
groups
;
erGrouping
(
image
,
channels
,
regions
,
groups
,
groups_rects
,
method
,
filename
,
minProbability
);
}
/*!
/*!
* MSERsToERStats function converts MSER contours (vector<Point>) to ERStat regions.
* MSERsToERStats function converts MSER contours (vector<Point>) to ERStat regions.
* It takes as input the contours provided by the OpenCV MSER feature detector and returns as output two vectors
* It takes as input the contours provided by the OpenCV MSER feature detector and returns as output two vectors
...
@@ -4167,5 +4183,55 @@ void MSERsToERStats(InputArray image, vector<vector<Point> > &contours, vector<v
...
@@ -4167,5 +4183,55 @@ void MSERsToERStats(InputArray image, vector<vector<Point> > &contours, vector<v
}
}
}
}
// Utility funtion for scripting
void
detectRegions
(
InputArray
image
,
const
Ptr
<
ERFilter
>&
er_filter1
,
const
Ptr
<
ERFilter
>&
er_filter2
,
CV_OUT
vector
<
vector
<
Point
>
>&
regions
)
{
// assert correct image type
CV_Assert
(
image
.
getMat
().
type
()
==
CV_8UC1
);
// at least one ERFilter must be passed
CV_Assert
(
!
er_filter1
.
empty
()
);
vector
<
ERStat
>
ers
;
er_filter1
->
run
(
image
,
ers
);
if
(
!
er_filter2
.
empty
())
{
er_filter2
->
run
(
image
,
ers
);
}
//Convert each ER to vector<Point> and push it to output regions
Mat
src
=
image
.
getMat
();
Mat
region_mask
=
Mat
::
zeros
(
src
.
rows
+
2
,
src
.
cols
+
2
,
CV_8UC1
);
for
(
size_t
i
=
1
;
i
<
ers
.
size
();
i
++
)
//start from 1 to deprecate root region
{
ERStat
*
stat
=
&
ers
[
i
];
//Fill the region and calculate 2nd stage features
Mat
region
=
region_mask
(
Rect
(
Point
(
stat
->
rect
.
x
,
stat
->
rect
.
y
),
Point
(
stat
->
rect
.
br
().
x
+
2
,
stat
->
rect
.
br
().
y
+
2
)));
region
=
Scalar
(
0
);
int
newMaskVal
=
255
;
int
flags
=
4
+
(
newMaskVal
<<
8
)
+
FLOODFILL_FIXED_RANGE
+
FLOODFILL_MASK_ONLY
;
Rect
rect
;
floodFill
(
src
(
Rect
(
Point
(
stat
->
rect
.
x
,
stat
->
rect
.
y
),
Point
(
stat
->
rect
.
br
().
x
,
stat
->
rect
.
br
().
y
))),
region
,
Point
(
stat
->
pixel
%
src
.
cols
-
stat
->
rect
.
x
,
stat
->
pixel
/
src
.
cols
-
stat
->
rect
.
y
),
Scalar
(
255
),
&
rect
,
Scalar
(
stat
->
level
),
Scalar
(
0
),
flags
);
rect
.
width
+=
2
;
rect
.
height
+=
2
;
region
=
region
(
rect
);
vector
<
vector
<
Point
>
>
contours
;
vector
<
Vec4i
>
hierarchy
;
findContours
(
region
,
contours
,
hierarchy
,
RETR_TREE
,
CHAIN_APPROX_NONE
,
Point
(
0
,
0
)
);
for
(
size_t
j
=
0
;
j
<
contours
[
0
].
size
();
j
++
)
contours
[
0
][
j
]
+=
(
stat
->
rect
.
tl
()
-
Point
(
1
,
1
));
regions
.
push_back
(
contours
[
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