Commit 9f89a05f088e6a5ff509b53929e081580b34d88e

Authored by Josh Klontz
1 parent bb446dfb

proposed implementation of #123

openbr/core/opencvutils.cpp
... ... @@ -300,6 +300,16 @@ QList<QRectF> OpenCVUtils::fromRects(const QList<Rect> &cvRects)
300 300 return qRects;
301 301 }
302 302  
  303 +bool OpenCVUtils::overlaps(const QList<Rect> &posRects, const Rect &negRect, double overlap)
  304 +{
  305 + foreach (const Rect &posRect, posRects) {
  306 + Rect intersect = negRect & posRect;
  307 + if (intersect.area() > overlap*posRect.area())
  308 + return true;
  309 + }
  310 + return false;
  311 +}
  312 +
303 313 QDataStream &operator<<(QDataStream &stream, const Mat &m)
304 314 {
305 315 // Write header
... ...
openbr/core/opencvutils.h
... ... @@ -87,6 +87,7 @@ namespace OpenCVUtils
87 87 QRectF fromRect(const cv::Rect &cvRect);
88 88 QList<cv::Rect> toRects(const QList<QRectF> &qRects);
89 89 QList<QRectF> fromRects(const QList<cv::Rect> &cvRects);
  90 + bool overlaps(const QList<cv::Rect> &posRects, const cv::Rect &negRect, double overlap);
90 91  
91 92 int getFourcc();
92 93 }
... ...
openbr/plugins/slidingwindow.cpp
... ... @@ -101,12 +101,73 @@ private:
101 101  
102 102 BR_REGISTER(Transform, SlidingWindowTransform)
103 103  
  104 +static TemplateList cropTrainingSamples(const TemplateList &data, const float aspectRatio, const int minSize, const float maxOverlap, const int negToPosRatio)
  105 +{
  106 + TemplateList result;
  107 + foreach (const Template &tmpl, data) {
  108 + QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
  109 + QList<Rect> negRects;
  110 + for (int i=0; i<posRects.size(); i++) {
  111 + Rect &posRect = posRects[i];
  112 +
  113 + // Adjust for training samples that have different aspect ratios
  114 + const int diff = posRect.width - int(posRect.height * aspectRatio);
  115 + posRect.x += diff / 2;
  116 + posRect.width += diff;
  117 +
  118 + // Ignore samples larger than the image
  119 + if ((posRect.x + posRect.width >= tmpl.m().cols) ||
  120 + (posRect.y + posRect.height >= tmpl.m().rows) ||
  121 + (posRect.x < 0) ||
  122 + (posRect.y < 0))
  123 + continue;
  124 +
  125 + result += Template(tmpl.file, Mat(tmpl, posRect));
  126 +
  127 + // Add random negative samples
  128 + Mat m = tmpl.m();
  129 + int sample = 0;
  130 + while (sample < negToPosRatio) {
  131 + const int x = rand() % m.cols;
  132 + const int y = rand() % m.rows;
  133 + const int maxWidth = m.cols - x;
  134 + const int maxHeight = m.rows - y;
  135 + if (maxWidth <= minSize || maxHeight <= minSize)
  136 + continue;
  137 +
  138 + int height;
  139 + int width;
  140 + if (aspectRatio > (float) maxWidth / (float) maxHeight) {
  141 + width = rand() % (maxWidth - minSize) + minSize;
  142 + height = qRound(width / aspectRatio);
  143 + } else {
  144 + height = rand() % (maxHeight - minSize) + minSize;
  145 + width = qRound(height * aspectRatio);
  146 + }
  147 + Rect negRect(x, y, width, height);
  148 +
  149 + // The negative samples cannot overlap the positive samples at
  150 + // all, but they may partially overlap with other negatives.
  151 + if (OpenCVUtils::overlaps(posRects, negRect, 0) ||
  152 + OpenCVUtils::overlaps(negRects, negRect, maxOverlap))
  153 + continue;
  154 +
  155 + result += Template(tmpl.file, Mat(tmpl, negRect));
  156 + result.last().file.set("Label", QString("neg"));
  157 + sample++;
  158 + }
  159 + }
  160 + }
  161 +
  162 + return result;
  163 +}
  164 +
104 165 /*!
105 166 * \ingroup transforms
106 167 * \brief .
107 168 * \author Austin Blanton \cite imaus10
108 169 */
109   -class BuildScalesTransform : public Transform
  170 +class BuildScalesTransform : public MetaTransform
110 171 {
111 172 Q_OBJECT
112 173 Q_PROPERTY(br::Transform *transform READ get_transform WRITE set_transform RESET reset_transform STORED false)
... ... @@ -117,7 +178,6 @@ class BuildScalesTransform : public Transform
117 178 Q_PROPERTY(int minSize READ get_minSize WRITE set_minSize RESET reset_minSize STORED false)
118 179 Q_PROPERTY(double maxOverlap READ get_maxOverlap WRITE set_maxOverlap RESET reset_maxOverlap STORED false)
119 180 Q_PROPERTY(float minScale READ get_minScale WRITE set_minScale RESET reset_minScale STORED false)
120   - Q_PROPERTY(bool negSamples READ get_negSamples WRITE set_negSamples RESET reset_negSamples STORED false)
121 181 BR_PROPERTY(br::Transform *, transform, NULL)
122 182 BR_PROPERTY(double, scaleFactor, 0.75)
123 183 BR_PROPERTY(bool, takeLargestScale, false)
... ... @@ -126,92 +186,27 @@ class BuildScalesTransform : public Transform
126 186 BR_PROPERTY(int, minSize, 8)
127 187 BR_PROPERTY(double, maxOverlap, 0)
128 188 BR_PROPERTY(float, minScale, 1.0)
129   - BR_PROPERTY(bool, negSamples, true)
130 189  
131   -public:
132   - BuildScalesTransform() : Transform(false, true) {}
133 190 private:
134   - int windowHeight;
135 191 float aspectRatio;
  192 + int windowHeight;
136 193  
137   - void train(const TemplateList &_data)
  194 + void train(const TemplateList &data)
138 195 {
139   - TemplateList data(_data); // have to make a copy b/c data is const
140 196 aspectRatio = getAspectRatio(data);
141   - data.first().file.set("aspectRatio", aspectRatio);
142   - windowHeight = (int) qRound((float) windowWidth / aspectRatio);
143   -
  197 + windowHeight = qRound(windowWidth / aspectRatio);
144 198 if (transform->trainable) {
145 199 TemplateList full;
146   - foreach (const Template &tmpl, data) {
147   - QList<Rect> posRects = OpenCVUtils::toRects(tmpl.file.rects());
148   - QList<Rect> negRects;
149   - foreach (Rect posRect, posRects) {
150   -
151   - //Adjust for training samples that have different aspect ratios
152   - int diff = posRect.width - (int)((float) posRect.height * aspectRatio);
153   - posRect.x += diff / 2;
154   - posRect.width += diff;
155   -
156   - if (posRect.x + posRect.width >= tmpl.m().cols || posRect.y + posRect.height >= tmpl.m().rows || posRect.x < 0 || posRect.y < 0) {
157   - continue;
158   - }
159   -
160   - Mat scaledImg;
161   - resize(Mat(tmpl, posRect), scaledImg, Size(windowWidth,qRound(windowWidth / aspectRatio)));
162   - Template pos(tmpl.file, scaledImg);
163   - full += pos;
164   -
165   - // add random negative samples
166   - if (negSamples) {
167   - Mat m = tmpl.m();
168   - int sample = 0;
169   - while (sample < negToPosRatio) {
170   - int x = Common::RandSample(1, m.cols)[0];
171   - int y = Common::RandSample(1, m.rows)[0];
172   - int maxWidth = m.cols - x;
173   - int maxHeight = m.rows - y;
174   - if (maxWidth <= minSize || maxHeight <= minSize)
175   - continue;
176   - int height;
177   - int width;
178   - if (aspectRatio > (float) maxWidth / (float) maxHeight) {
179   - width = Common::RandSample(1,maxWidth,minSize)[0];
180   - height = (int) qRound(width / aspectRatio);
181   - } else {
182   - height = Common::RandSample(1,maxHeight,minSize)[0];
183   - width = (int) qRound(height * aspectRatio);
184   - }
185   - Rect negRect(x, y, width, height);
186   - // the negative samples cannot overlap the positive at all
187   - // but they may overlap with other negatives
188   - if (overlaps(posRects, negRect, 0) || overlaps(negRects, negRect, maxOverlap))
189   - continue;
190   - negRects.append(negRect);
191   - Template neg(tmpl.file, Mat());
192   - resize(Mat(tmpl, negRect), neg, Size(windowWidth, windowHeight));
193   - neg.file.set("Label", QString("neg"));
194   - full += neg;
195   - sample++;
196   - }
197   - }
198   - }
  200 + foreach (const Template &roi, cropTrainingSamples(data, aspectRatio, minSize, maxOverlap, negToPosRatio)) {
  201 + Mat resized;
  202 + resize(roi, resized, Size(windowWidth, windowHeight));
  203 + full += Template(roi.file, resized);
199 204 }
  205 + full.first().file.set("aspectRatio", aspectRatio);
200 206 transform->train(full);
201 207 }
202 208 }
203 209  
204   - bool overlaps(QList<Rect> posRects, Rect negRect, double overlap)
205   - {
206   - foreach (const Rect posRect, posRects) {
207   - Rect intersect = negRect & posRect;
208   - if (intersect.area() > overlap*posRect.area())
209   - return true;
210   - }
211   - return false;
212   - }
213   -
214   -
215 210 void project(const Template &src, Template &dst) const
216 211 {
217 212 dst = src;
... ...
scripts/pedestrianBaselineLBP.sh
1 1 #!/bin/bash
2 2  
3   -#Right now this is just a simple proof of concept. No quanititative eval is performed
  3 +# Right now this is just a simple proof of concept. No quantitative eval is performed
4 4 # but instead the qualitative results are displayed.
5 5  
6   -#Make sure you set your data path. This will likely by your openbr/data directory.
7   -INRIA_PATH=$DATA/INRIAPerson
  6 +# Make sure you set your data path. This will likely by your openbr/data directory.
  7 +if [ -z "$DATA" ]; then
  8 + INRIA_PATH=../data/INRIAPerson
  9 +else
  10 + INRIA_PATH=$DATA/INRIAPerson
  11 +fi
8 12  
9 13 ALG="Open+Cvt(Gray)+Rename(neg,0)+BuildScales(Blur(2)+LBP(1,2)+SlidingWindow(Hist(59)+Cat+LDA(isBinary=true),windowWidth=10,takeLargestScale=false,threshold=2),windowWidth=10,takeLargestScale=false,minScale=4)+ConsolidateDetections+Discard"
10 14  
... ...