#include <vector>
#include <string>
#include <iostream>
+#include <string>
+#include <cstdio>
namespace {
+char *itoa(long i, char* s, int /*dummy_radix*/)
+{
+ sprintf(s, "%ld", i);
+ return s;
+}
+
+// used for noisy printfs
+// #define WITH_DEBUG_OUT
+
struct Octave
{
+ int index;
float scale;
int stages;
cv::Size size;
static const char *const SC_OCT_STAGES;
static const char *const SC_OCT_SHRINKAGE;
- Octave() : scale(0), stages(0), size(cv::Size()), shrinkage(0) {}
- Octave(cv::Size origObjSize, const cv::FileNode& fn)
- : scale((float)fn[SC_OCT_SCALE]), stages((int)fn[SC_OCT_STAGES]),
+ Octave(const int i, cv::Size origObjSize, const cv::FileNode& fn)
+ : index(i), scale((float)fn[SC_OCT_SCALE]), stages((int)fn[SC_OCT_STAGES]),
size(cvRound(origObjSize.width * scale), cvRound(origObjSize.height * scale)),
shrinkage((int)fn[SC_OCT_SHRINKAGE])
{}
-
- int index() const {return (int)log(scale);}
};
const char *const Octave::SC_OCT_SCALE = "scale";
const char *const Octave::SC_OCT_STAGES = "stageNum";
const char *const Octave::SC_OCT_SHRINKAGE = "shrinkingFactor";
-
struct Stage
{
float threshold;
float threshold;
Node(){}
- Node(cv::FileNodeIterator& fIt) : feature((int)(*(fIt +=2)++)), threshold((float)(*(fIt++))){}
+ Node(const int offset, cv::FileNodeIterator& fIt)
+ : feature((int)(*(fIt +=2)++) + offset), threshold((float)(*(fIt++))){}
};
-
struct Feature
{
int channel;
cv::FileNode rn = fn[SC_F_RECT];
cv::FileNodeIterator r_it = rn.end();
rect = cv::Rect(*(--r_it), *(--r_it), *(--r_it), *(--r_it));
- // std::cout << "feature: " << rect.x << " " << rect.y << " " << rect.width
- //<< " " << rect.height << " " << channel << std::endl;
}
};
const char * const Feature::SC_F_CHANNEL = "channel";
const char * const Feature::SC_F_RECT = "rect";
+struct Object
+{
+ enum Class{PEDESTRIAN};
+ cv::Rect rect;
+ float confidence;
+ Class detType;
+
+ Object(const cv::Rect& r, const float c, Class dt = PEDESTRIAN) : rect(r), confidence(c), detType(dt) {}
+};
+
struct Level
{
const Octave* octave;
float origScale;
float relScale;
- float shrScale;
+ float shrScale; // used for marking detection
cv::Size workRect;
cv::Size objSize;
-
- // TiDo not reounding
Level(const Octave& oct, const float scale, const int shrinkage, const int w, const int h)
- : octave(&oct), origScale(scale), relScale(scale / oct.scale), shrScale (relScale / shrinkage),
+ : octave(&oct), origScale(scale), relScale(scale / oct.scale), shrScale (relScale / (float)shrinkage),
workRect(cv::Size(cvRound(w / (float)shrinkage),cvRound(h / (float)shrinkage))),
objSize(cv::Size(cvRound(oct.size.width * relScale), cvRound(oct.size.height * relScale)))
{}
- void markDetection(const int x, const int dx, std::vector<cv::Rect>& detections) const
+ void markDetection(const int x, const int y, float confidence, std::vector<Object>& detections) const
{
+ int shrinkage = (*octave).shrinkage;
+ cv::Rect rect(cvRound(x * shrinkage), cvRound(y * shrinkage), objSize.width, objSize.height);
+ detections.push_back(Object(rect, confidence));
}
};
-
struct CascadeIntrinsics
{
static const float lambda = 1.099f, a = 0.89f;
if ((scaling - 1.f) < FLT_EPSILON)
return 1.f;
- // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool paper
+ // according to R. Benenson, M. Mathias, R. Timofte and L. Van Gool's and Dallal's papers
static const float A[2][2] =
{ //channel <= 6, otherwise
{ 0.89f, 1.f}, // down
static const float B[2][2] =
{ //channel <= 6, otherwise
{ 1.099f / log(2), 2.f}, // down
- { 2.f, 2.f} // up
+ { 0.f, 2.f} // up
};
- float a = A[(int)(scaling >= 1)][(int)(channel >= 6)];
- float b = B[(int)(scaling >= 1)][(int)(channel >= 6)];
+ float a = A[(int)(scaling >= 1)][(int)(channel > 6)];
+ float b = B[(int)(scaling >= 1)][(int)(channel > 6)];
+#if defined WITH_DEBUG_OUT
+ printf("scaling: %f %f %f %f\n", scaling, a, b, a * pow(scaling, b));
+#endif
return a * pow(scaling, b);
}
};
-// Feature rescale(float relScale)
-// {
-// Feature res(*this);
-// res.rect = cv::Rect (cvRound(rect.x * relScale), cvRound(rect.y * relScale),
-// cvRound(rect.width * relScale), cvRound(rect.height * relScale));
-// res.threshold = threshold * CascadeIntrinsics::getFor(channel, relScale);
-// return res;
-// }
+int qangle6(float dfdx, float dfdy)
+{
+ static const float vectors[6][2] =
+ {
+ {std::cos(0), std::sin(0) },
+ {std::cos(M_PI / 6.f), std::sin(M_PI / 6.f) },
+ {std::cos(M_PI / 3.f), std::sin(M_PI / 3.f) },
+
+ {std::cos(M_PI / 2.f), std::sin(M_PI / 2.f) },
+ {std::cos(2.f * M_PI / 3.f), std::sin(2.f * M_PI / 3.f)},
+ {std::cos(5.f * M_PI / 6.f), std::sin(5.f * M_PI / 6.f)}
+ };
+
+ int index = 0;
+
+ float dot = fabs(dfdx * vectors[0][0] + dfdy * vectors[0][1]);
+
+ for(int i = 1; i < 6; ++i)
+ {
+ const float curr = fabs(dfdx * vectors[i][0] + dfdy * vectors[i][1]);
+
+ if(curr > dot)
+ {
+ dot = curr;
+ index = i;
+ }
+ }
+
+ return index;
+}
+//ToDo
void calcHistBins(const cv::Mat& grey, cv::Mat& magIntegral, std::vector<cv::Mat>& histInts,
const int bins, int shrinkage)
{
+ static const float magnitudeScaling = 1.f / sqrt(2);
+
CV_Assert( grey.type() == CV_8U);
float scale = 1.f / shrinkage;
const int rows = grey.rows + 1;
const int cols = grey.cols + 1;
- cv::Size intSumSize(cols, rows);
- histInts.clear();
- std::vector<cv::Mat> hist;
- for (int bin = 0; bin < bins; ++bin)
+ cv::Mat df_dx(grey.rows, grey.cols, CV_32F),
+ df_dy(grey.rows, grey.cols, CV_32F), mag, angle;
+ // cv::Sobel(grey, df_dx, CV_32F, 1, 0);
+ // cv::Sobel(grey, df_dy, CV_32F, 0, 1);
+
+ for (int y = 1; y < grey.rows -1; ++y)
{
- hist.push_back(cv::Mat(rows, cols, CV_32FC1));
- }
+ float* dx = df_dx.ptr<float>(y);
+ float* dy = df_dy.ptr<float>(y);
+
+ const uchar* gr = grey.ptr<uchar>(y);
+ const uchar* gr_down = grey.ptr<uchar>(y - 1);
+ const uchar* gr_up = grey.ptr<uchar>(y + 1);
+ for (int x = 1; x < grey.cols - 1; ++x)
+ {
+ float dx_a = gr[x + 1];
+ float dx_b = gr[x - 1];
+ dx[x] = dx_a - dx_b;
- cv::Mat df_dx, df_dy, mag, angle;
- cv::Sobel(grey, df_dx, CV_32F, 1, 0);
- cv::Sobel(grey, df_dy, CV_32F, 0, 1);
+ float dy_a = gr_up[x];
+ float dy_b = gr_down[x];
+ dy[x] = dy_a - dy_b;
+ }
+ }
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
- const float magnitudeScaling = 1.0 / sqrt(2);
mag *= magnitudeScaling;
- angle /= 60;
- for (int h = 0; h < mag.rows; ++h)
+ cv::Mat saturatedMag(grey.rows, grey.cols, CV_8UC1);
+ for (int y = 0; y < grey.rows; ++y)
+ {
+ float* rm = mag.ptr<float>(y);
+ uchar* mg = saturatedMag.ptr<uchar>(y);
+ for (int x = 0; x < grey.cols; ++x)
+ {
+ mg[x] = cv::saturate_cast<uchar>(rm[x]);
+ }
+ }
+
+ mag = saturatedMag;
+
+ histInts.clear();
+ std::vector<cv::Mat> hist;
+ for (int bin = 0; bin < bins; ++bin)
+ {
+ hist.push_back(cv::Mat(rows, cols, CV_8UC1));
+ }
+
+ for (int h = 0; h < saturatedMag.rows; ++h)
{
- float* magnitude = mag.ptr<float>(h);
- float* ang = angle.ptr<float>(h);
+ uchar* magnitude = saturatedMag.ptr<uchar>(h);
+ float* dfdx = df_dx.ptr<float>(h);
+ float* dfdy = df_dy.ptr<float>(h);
- for (int w = 0; w < mag.cols; ++w)
+ for (int w = 0; w < saturatedMag.cols; ++w)
{
- hist[(int)ang[w]].ptr<float>(h)[w] = magnitude[w];
+ hist[ qangle6(dfdx[w], dfdy[w]) ].ptr<uchar>(h)[w] = magnitude[w];
}
}
+ angle /= 60;
+
+
+ // for (int h = 0; h < saturatedMag.rows; ++h)
+ // {
+ // uchar* magnitude = saturatedMag.ptr<uchar>(h);
+ // float* ang = angle.ptr<float>(h);
+
+ // for (int w = 0; w < saturatedMag.cols; ++w)
+ // {
+ // hist[ (int)ang[w] ].ptr<uchar>(h)[w] = magnitude[w];
+ // }
+ // }
+ char buffer[33];
+
for (int bin = 0; bin < bins; ++bin)
{
cv::Mat shrunk, sum;
+ cv::imshow(std::string("hist[bin]") + itoa(bin, buffer, 10), hist[bin]);
cv::resize(hist[bin], shrunk, cv::Size(), scale, scale, cv::INTER_AREA);
+ cv::imshow(std::string("shrunk") + itoa(bin, buffer, 10), shrunk);
cv::integral(shrunk, sum);
+ cv::imshow(std::string("sum") + itoa(bin, buffer, 10), sum);
histInts.push_back(sum);
+
+ // std::cout << shrunk << std::endl << std::endl;
}
cv::Mat shrMag;
+ cv::imshow("mag", mag);
cv::resize(mag, shrMag, cv::Size(), scale, scale, cv::INTER_AREA);
+ cv::FileStorage fs("/home/kellan/actualChannels.xml", cv::FileStorage::WRITE);
+ cv::imshow("shrunk_channel", shrMag);
+ fs << "shrunk_channel6" << shrMag;
+
+ // cv::imshow("shrMag", shrMag);
cv::integral(shrMag, magIntegral, mag.depth());
+ // cv::imshow("magIntegral", magIntegral);
histInts.push_back(magIntegral);
}
enum {HOG_BINS = 6, HOG_LUV_BINS = 10};
ChannelStorage() {}
- ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr)
+ ChannelStorage(cv::Mat& colored, int shr) : shrinkage(shr)
{
- cv::Mat _luv, shrLuv;
- cv::cvtColor(colored, _luv, CV_BGR2Luv);
- cv::resize(_luv, shrLuv, cv::Size(), 1.f / shr, 1.f / shr, cv::INTER_AREA);
+ hog.clear();
+ cv::FileStorage fs("/home/kellan/testInts.xml", cv::FileStorage::READ);
+ char buff[33];
+ float scale = 1.f / shrinkage;
+ for(int i = 0; i < 10; ++i)
+ {
+ cv::Mat channel;
+ fs[std::string("channel") + itoa(i, buff, 10)] >> channel;
+
+ cv::Mat shrunk, sum;
+ // cv::resize(channel, shrunk, cv::Size(), scale, scale, cv::INTER_AREA);
+ // cv::imshow(std::string("channel") + itoa(i, buff, 10), shrunk);
+ // cv::waitKey(0);
+ // cv::integral(channel, sum);
+ // if (i == 1)
+ // std::cout << channel << std::endl;
+ hog.push_back(channel);
+ }
+ // exit(1);
+ }
+ // {
+ // // add gauss
+ // cv::Mat gauss;
+ // cv::GaussianBlur(colored, gauss, cv::Size(3,3), 0 ,0);
- cv::integral(shrLuv, luv);
+ // colored = gauss;
+ // // cv::imshow("colored", colored);
- std::vector<cv::Mat> splited;
- split(luv, splited);
+ // cv::Mat _luv, shrLuv;
+ // cv::cvtColor(colored, _luv, CV_BGR2Luv);
- cv::Mat grey;
- cv::cvtColor(colored, grey, CV_RGB2GRAY);
+ // // cv::imshow("_luv", _luv);
- calcHistBins(grey, magnitude, hog, HOG_BINS, shrinkage);
+ // cv::resize(_luv, shrLuv, cv::Size(), 1.f / shr, 1.f / shr, cv::INTER_AREA);
- hog.insert(hog.end(), splited.begin(), splited.end());
- }
+ // // cv::imshow("shrLuv", shrLuv);
+
+ // cv::integral(shrLuv, luv);
+
+ // // cv::imshow("luv", luv);
+
+ // std::vector<cv::Mat> splited;
+ // split(luv, splited);
+
+ // char buffer[33];
+
+ // for (int i = 0; i < (int)splited.size(); i++)
+ // {
+ // // cv::imshow(itoa(i,buffer,10), splited[i]);
+ // }
+
+ // cv::Mat grey;
+ // cv::cvtColor(colored, grey, CV_RGB2GRAY);
+
+ // // cv::imshow("grey", grey);
+
+ // calcHistBins(grey, magnitude, hog, HOG_BINS, shrinkage);
+
+ // hog.insert(hog.end(), splited.begin(), splited.end());
+ // }
float get(const int x, const int y, const int channel, const cv::Rect& area) const
{
CV_Assert(channel < HOG_LUV_BINS);
-
const cv::Mat m = hog[channel];
- float a = m.ptr(y + area.y)[x + area.x];
- float b = m.ptr(y + area.y)[x + area.width];
- float c = m.ptr(y + area.height)[x + area.width];
- float d = m.ptr(y + area.height)[x + area.x];
+#if defined WITH_DEBUG_OUT
+ printf("feature box %d %d %d %d ", area.x, area.y, area.width, area.height);
+ printf("get for channel %d\n", channel);
+ printf("!! %d\n", m.depth());
+#endif
+ int a = m.ptr<int>(y + area.y)[x + area.x];
+ int b = m.ptr<int>(y + area.y)[x + area.width];
+ int c = m.ptr<int>(y + area.height)[x + area.width];
+ int d = m.ptr<int>(y + area.height)[x + area.x];
+
+#if defined WITH_DEBUG_OUT
+ printf(" retruved integral values: %d %d %d %d\n", a, b, c, d);
+#endif
return (a - b + c - d);
}
};
+
}
struct cv::SoftCascade::Filds
std::vector<Octave> octaves;
std::vector<Stage> stages;
- std::vector<Node> nodes;
- std::vector<float> leaves;
-
+ std::vector<Node> nodes;
+ std::vector<float> leaves;
std::vector<Feature> features;
std::vector<Level> levels;
typedef std::vector<Octave>::iterator octIt_t;
+ float rescale(const Feature& feature, const float relScale, cv::Rect& scaledRect, const float threshold) const
+ {
+ float scaling = CascadeIntrinsics::getFor(feature.channel, relScale);
+ scaledRect = feature.rect;
+
+#if defined WITH_DEBUG_OUT
+ printf("feature %d box %d %d %d %d\n", feature.channel, scaledRect.x, scaledRect.y,
+ scaledRect.width, scaledRect.height);
+
+ std::cout << "rescale: " << feature.channel << " " << relScale << " " << scaling << std::endl;
+#endif
+
+ float farea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
+ // rescale
+ scaledRect.x = cvRound(relScale * scaledRect.x);
+ scaledRect.y = cvRound(relScale * scaledRect.y);
+ scaledRect.width = cvRound(relScale * scaledRect.width);
+ scaledRect.height = cvRound(relScale * scaledRect.height);
+
+#if defined WITH_DEBUG_OUT
+ printf("feature %d box %d %d %d %d\n", feature.channel, scaledRect.x, scaledRect.y,
+ scaledRect.width, scaledRect.height);
+
+ std::cout << " new rect: " << scaledRect.x << " " << scaledRect.y
+ << " " << scaledRect.width << " " << scaledRect.height << " ";
+#endif
+
+ float sarea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
+
+ float approx = 1.f;
+ if ((farea - 0.f) > FLT_EPSILON && (farea - 0.f) > FLT_EPSILON)
+ {
+ const float expected_new_area = farea * relScale * relScale;
+ approx = expected_new_area / sarea;
+
+#if defined WITH_DEBUG_OUT
+ std::cout << " rel areas " << expected_new_area << " " << sarea << std::endl;
+#endif
+
+ }
+
+ // compensation areas rounding
+ float rootThreshold = threshold / approx;/
+ rootThreshold *= scaling;
+
+#if defined WITH_DEBUG_OUT
+ std::cout << "approximation " << approx << " " << threshold << " -> " << rootThreshold
+ << " " << scaling << std::endl;
+#endif
+
+ return rootThreshold;
+ }
+
void detectAt(const Level& level, const int dx, const int dy, const ChannelStorage& storage,
- std::vector<cv::Rect>& detections) const
+ std::vector<Object>& detections) const
{
+#if defined WITH_DEBUG_OUT
+ std::cout << "detect at: " << dx << " " << dy << std::endl;
+#endif
float detectionScore = 0.f;
const Octave& octave = *(level.octave);
- int stBegin = octave.index() * octave.stages, stEnd = stBegin + octave.stages;
+ int stBegin = octave.index * octave.stages, stEnd = stBegin + octave.stages;
+
+#if defined WITH_DEBUG_OUT
+ std::cout << " octave stages: " << stBegin << " to " << stEnd << " index " << octave.index << " "
+ << octave.scale << " level " << level.origScale << std::endl;
+#endif
+
int st = stBegin;
for(; st < stEnd; ++st)
{
+
+#if defined WITH_DEBUG_OUT
+ printf("index: %d\n", st);
+#endif
+
const Stage& stage = stages[st];
{
int nId = st * 3;
// work with root node
const Node& node = nodes[nId];
const Feature& feature = features[node.feature];
+ cv::Rect scaledRect;
+ float threshold = rescale(feature, level.relScale, scaledRect, node.threshold);
- // rescaling
- float scaling = CascadeIntrinsics::getFor(feature.channel, level.relScale);
- cv::Rect scaledRect = feature.rect;
- float farea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
- // rescale
- scaledRect.x = cvRound(scaling * scaledRect.x);
- scaledRect.y = cvRound(scaling * scaledRect.y);
- scaledRect.width = cvRound(scaling * scaledRect.width);
- scaledRect.height = cvRound(scaling * scaledRect.height);
- float sarea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
+ float sum = storage.get(dx, dy, feature.channel, scaledRect);
- float approx = 1.f;
- if ((farea - 0.f) > FLT_EPSILON && (farea - 0.f) > FLT_EPSILON)
- {
- const float expected_new_area = farea*level.relScale*level.relScale;
- approx = expected_new_area / sarea;
- }
+#if defined WITH_DEBUG_OUT
+ printf("root feature %d %f\n",feature.channel, sum);
+#endif
- float rootThreshold = node.threshold / approx; // ToDo check
- rootThreshold *= scaling;
+ int next = (sum >= threshold)? 2 : 1;
- // use rescaled
- float sum = storage.get(dx, dy, feature.channel, scaledRect);
- int next = (sum >= rootThreshold)? 2 : 1;
+#if defined WITH_DEBUG_OUT
+ printf("go: %d (%f >= %f)\n\n" ,next, sum, threshold);
+#endif
- // leaces
+ // leaves
const Node& leaf = nodes[nId + next];
- const Feature& fLeaf = features[node.feature];
-
- // rescaling
- scaling = CascadeIntrinsics::getFor(fLeaf.channel, level.relScale);
- scaledRect = fLeaf.rect;
- farea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
- // rescale
- scaledRect.x = cvRound(scaling * scaledRect.x);
- scaledRect.y = cvRound(scaling * scaledRect.y);
- scaledRect.width = cvRound(scaling * scaledRect.width);
- scaledRect.height = cvRound(scaling * scaledRect.height);
-
- sarea = (scaledRect.width - scaledRect.x) * (scaledRect.height - scaledRect.y);
-
- approx = 1.f;
- if ((farea - 0.f) > FLT_EPSILON && (farea - 0.f) > FLT_EPSILON)
- {
- const float expected_new_area = farea*level.relScale*level.relScale;
- approx = expected_new_area / sarea;
- }
+ const Feature& fLeaf = features[leaf.feature];
- rootThreshold = leaf.threshold / approx; // ToDo check
- rootThreshold *= scaling;
+ threshold = rescale(fLeaf, level.relScale, scaledRect, leaf.threshold);
+ sum = storage.get(dx, dy, fLeaf.channel, scaledRect);
- sum = storage.get(dx, dy, feature.channel, scaledRect);
- int lShift = (next - 1) * 2 + (sum >= rootThreshold) ? 1 : 0;
- float impact = leaves[nId + lShift];
+ int lShift = (next - 1) * 2 + ((sum >= threshold) ? 1 : 0);
+ float impact = leaves[(st * 4) + lShift];
+#if defined WITH_DEBUG_OUT
+ printf("decided: %d (%f >= %f) %d %f\n\n" ,next, sum, threshold, lShift, impact);
+#endif
detectionScore += impact;
}
+#if defined WITH_DEBUG_OUT
+ printf("extracted stage:\n");
+ printf("ct %f\n", stage.threshold);
+ printf("computed score %f\n\n", detectionScore);
+ // if (st - stBegin > 100) break;
+#endif
+
if (detectionScore <= stage.threshold) break;
}
- if (st == octave.stages - 1)
- level.markDetection(dx, dy, detections);
+ printf("x %d y %d: %d\n", dx, dy, st - stBegin);
+
+ if (st == stEnd)
+ {
+ std::cout << " got " << st << std::endl;
+ level.markDetection(dx, dy, detectionScore, detections);
+ }
}
octIt_t fitOctave(const float& logFactor)
if (fabs(scale - maxScale) < FLT_EPSILON) break;
scale = std::min(maxScale, expf(log(scale) + logFactor));
- // std::cout << "level scale "
- // << levels[sc].origScale
- // << " octeve "
- // << levels[sc].octave->scale
- // << " "
- // << levels[sc].relScale
- // << " " << levels[sc].shrScale
- // << " [" << levels[sc].objSize.width
- // << " " << levels[sc].objSize.height << "] ["
- // << levels[sc].workRect.width << " " << levels[sc].workRect.height << std::endl;
+ std::cout << "level " << sc << " scale "
+ << levels[sc].origScale
+ << " octeve "
+ << levels[sc].octave->scale
+ << " "
+ << levels[sc].relScale
+ << " " << levels[sc].shrScale
+ << " [" << levels[sc].objSize.width
+ << " " << levels[sc].objSize.height << "] ["
+ << levels[sc].workRect.width << " " << levels[sc].workRect.height << "]" << std::endl;
}
-
- return;
-
-
- std::cout << std::endl << std::endl << std::endl;
}
bool fill(const FileNode &root, const float mins, const float maxs)
// octaves.reserve(noctaves);
FileNodeIterator it = fn.begin(), it_end = fn.end();
+ int feature_offset = 0;
+ int octIndex = 0;
for (; it != it_end; ++it)
{
FileNode fns = *it;
- Octave octave(cv::Size(SoftCascade::ORIG_OBJECT_WIDTH, SoftCascade::ORIG_OBJECT_HEIGHT), fns);
+ Octave octave(octIndex, cv::Size(SoftCascade::ORIG_OBJECT_WIDTH, SoftCascade::ORIG_OBJECT_HEIGHT), fns);
CV_Assert(octave.stages > 0);
octaves.push_back(octave);
fns = (*ftr)[SC_INTERNAL];
FileNodeIterator inIt = fns.begin(), inIt_end = fns.end();
for (; inIt != inIt_end;)
- nodes.push_back(Node(inIt));
+ nodes.push_back(Node(feature_offset, inIt));
fns = (*ftr)[SC_LEAF];
inIt = fns.begin(), inIt_end = fns.end();
st = ffs.begin(), st_end = ffs.end();
for (; st != st_end; ++st )
features.push_back(Feature(*st));
+
+ feature_offset += octave.stages * 3;
+ ++octIndex;
}
shrinkage = octaves[0].shrinkage;
+
+ //debug print
+ // std::cout << "collected " << stages.size() << " stages" << std::endl;
+ // for (int i = 0; i < (int)stages.size(); ++i)
+ // {
+ // std::cout << "stage " << i << ": " << stages[i].threshold << std::endl;
+ // }
+
+ // std::cout << "collected " << nodes.size() << " nodes" << std::endl;
+ // for (int i = 0; i < (int)nodes.size(); ++i)
+ // {
+ // std::cout << "node " << i << ": " << nodes[i].threshold << " " << nodes[i].feature << std::endl;
+ // }
+
+ // std::cout << "collected " << leaves.size() << " leaves" << std::endl;
+ // for (int i = 0; i < (int)leaves.size(); ++i)
+ // {
+ // std::cout << "leaf " << i << ": " << leaves[i] << std::endl;
+ // }
return true;
}
};
return true;
}
-void cv::SoftCascade::detectMultiScale(const Mat& image, const std::vector<cv::Rect>& rois,
- std::vector<cv::Rect>& objects,
- const int step, const int rejectfactor)
+#define DEBUG_STORE_IMAGES
+#define DEBUG_SHOW_RESULT
+
+void cv::SoftCascade::detectMultiScale(const Mat& image, const std::vector<cv::Rect>& /*rois*/,
+ std::vector<cv::Rect>& objects, const int /*rejectfactor*/)
{
typedef std::vector<cv::Rect>::const_iterator RIter_t;
// only color images are supperted
const Filds& fld = *filds;
+ cv::Mat image1;
+ cv::cvtColor(image, image1, CV_RGB2RGBA);
+
+#if defined DEBUG_STORE_IMAGES
+ cv::FileStorage fs("/home/kellan/opencvInputImage.xml", cv::FileStorage::WRITE);
+ cv::imwrite("/home/kellan/opencvInputImage.jpg", image1);
+ fs << "opencvInputImage" << image1;
+
+ cv::Mat doppia;
+ cv::FileStorage fsr("/home/kellan/befireGause.xml", cv::FileStorage::READ);
+ fsr["input_gpu_mat"] >> doppia;
+
+ cv::Mat diff;
+ cv::absdiff(image1, doppia, diff);
+
+ fs << "absdiff" << diff;
+ fs.release();
+#if defined DEBUG_STORE_IMAGES
+
// create integrals
- ChannelStorage storage(image, fld.shrinkage);
+ ChannelStorage storage(image1, fld.shrinkage);
// object candidates
- std::vector<cv::Rect> detections;
+ std::vector<Object> detections;
typedef std::vector<Level>::const_iterator lIt;
- for (lIt it = fld.levels.begin(); it != fld.levels.end(); ++it)
+ int total = 0, l = 0;
+ for (lIt it = fld.levels.begin() + 26; it != fld.levels.end(); ++it)
{
const Level& level = *it;
+
+#if defined WITH_DEBUG_OUT
+ std::cout << "================================ " << l++ << std::endl;
+#endif
for (int dy = 0; dy < level.workRect.height; ++dy)
+ {
for (int dx = 0; dx < level.workRect.width; ++dx)
+ {
fld.detectAt(level, dx, dy, storage, detections);
+ total++;
+ // break;
+ }
+ // break;
+ }
+ break;
+ }
+
+ cv::Mat out = image.clone();
+
+#if defined DEBUG_SHOW_RESULT
+
+ printf("TOTAL: %d from %d\n", (int)detections.size(),total) ;
+
+ for(int i = 0; i < (int)detections.size(); ++i)
+ {
+ cv::rectangle(out, detections[i].rect, cv::Scalar(255, 0, 0, 255), 2);
}
- std::swap(detections, objects);
+ cv::imshow("out", out);
+ cv::waitKey(0);
+#endif
+ // std::swap(detections, objects);
}
\ No newline at end of file