ERFilter python bindings

pull/528/head
lluisgomez 9 years ago
parent bd971fd78c
commit 9281cbfd2b
  1. 15
      modules/text/include/opencv2/text/erfilter.hpp
  2. 39
      modules/text/samples/detect_er_chars.py
  3. 54
      modules/text/src/erfilter.cpp

@ -115,7 +115,7 @@ public:
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:
@ -124,7 +124,7 @@ public:
By doing it we hide SVM, Boost etc. Developers can provide their own classifiers to the
ERFilter algorithm.
*/
class CV_EXPORTS Callback
class CV_EXPORTS_W Callback
{
public:
virtual ~Callback() { }
@ -207,7 +207,7 @@ 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
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,
float maxArea = 0.13, float minProbability = 0.4,
bool nonMaxSuppression = true,
@ -224,7 +224,7 @@ 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
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);
@ -234,7 +234,7 @@ CV_EXPORTS Ptr<ERFilter> createERFilterNM2(const Ptr<ERFilter::Callback>& cb,
returns a pointer to ERFilter::Callback.
*/
CV_EXPORTS Ptr<ERFilter::Callback> loadClassifierNM1(const std::string& filename);
CV_EXPORTS_W Ptr<ERFilter::Callback> loadClassifierNM1(const String& filename);
/** @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
returns a pointer to ERFilter::Callback.
*/
CV_EXPORTS Ptr<ERFilter::Callback> loadClassifierNM2(const std::string& filename);
CV_EXPORTS_W Ptr<ERFilter::Callback> loadClassifierNM2(const String& filename);
//! computeNMChannels operation modes
@ -343,6 +343,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,
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);
//! @}
}

@ -0,0 +1,39 @@
#!/usr/bin/python
import sys
import os
import cv2
import numpy as np
from matplotlib import pyplot as plt
print '\ndetect_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()

@ -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
(e.g. trained_classifierNM1.xml) returns a pointer to ERFilter::Callback.
*/
Ptr<ERFilter::Callback> loadClassifierNM1(const string& filename)
Ptr<ERFilter::Callback> loadClassifierNM1(const String& filename)
{
return makePtr<ERClassifierNM1>(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
(e.g. trained_classifierNM2.xml) returns a pointer to ERFilter::Callback.
*/
Ptr<ERFilter::Callback> loadClassifierNM2(const string& filename)
Ptr<ERFilter::Callback> loadClassifierNM2(const String& filename)
{
return makePtr<ERClassifierNM2>(filename);
}
@ -4167,5 +4167,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=0; i < ers.size(); i++)
{
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();
regions.push_back(contours[0]);
}
}
}
}

Loading…
Cancel
Save