Commit 9281cbfd authored by lluisgomez's avatar lluisgomez

ERFilter python bindings

parent bd971fd7
...@@ -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,7 +207,7 @@ the probability P(er|character) are selected (if the local maximum of the probab ...@@ -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 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 = 0.00025,
float maxArea = 0.13, float minProbability = 0.4, float maxArea = 0.13, float minProbability = 0.4,
bool nonMaxSuppression = true, bool nonMaxSuppression = true,
...@@ -224,7 +224,7 @@ non-character classes using more informative but also more computationally expen ...@@ -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 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 = 0.3);
...@@ -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::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. /** @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::string& filename); CV_EXPORTS_W Ptr<ERFilter::Callback> loadClassifierNM2(const String& filename);
//! computeNMChannels operation modes //! computeNMChannels operation modes
...@@ -343,6 +343,9 @@ An example of MSERsToERStats in use can be found in the text detection webcam_de ...@@ -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, 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);
//! @} //! @}
} }
......
#!/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()
\ No newline at end of file
...@@ -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 string& filename) Ptr<ERFilter::Callback> loadClassifierNM1(const String& 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 string& filename) Ptr<ERFilter::Callback> loadClassifierNM2(const String& filename)
{ {
return makePtr<ERClassifierNM2>(filename); return makePtr<ERClassifierNM2>(filename);
} }
...@@ -4167,5 +4167,55 @@ void MSERsToERStats(InputArray image, vector<vector<Point> > &contours, vector<v ...@@ -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]);
}
}
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment