Commit d2bac5329e5a122d966687bcb08249c08eaab21e
1 parent
a80bf1d2
Updates to sliding window framework
Showing
2 changed files
with
98 additions
and
83 deletions
openbr/plugins/classification/cascade.cpp
| ... | ... | @@ -13,14 +13,14 @@ namespace br |
| 13 | 13 | |
| 14 | 14 | struct Miner |
| 15 | 15 | { |
| 16 | - Mat src; | |
| 17 | - Mat scaledSrc; | |
| 16 | + Template src; | |
| 17 | + Template scaledSrc; | |
| 18 | 18 | Size windowSize; |
| 19 | 19 | Point offset, point; |
| 20 | 20 | float scale, scaleFactor, stepFactor; |
| 21 | 21 | |
| 22 | - Miner(const Mat &m, const Size &windowSize, const Point &offset) : | |
| 23 | - src(m), | |
| 22 | + Miner(const Template &t, const Size &windowSize, const Point &offset) : | |
| 23 | + src(t), | |
| 24 | 24 | windowSize(windowSize), |
| 25 | 25 | offset(offset), |
| 26 | 26 | point(offset) |
| ... | ... | @@ -29,43 +29,57 @@ struct Miner |
| 29 | 29 | scaleFactor = 1.4142135623730950488016887242097F; |
| 30 | 30 | stepFactor = 0.5F; |
| 31 | 31 | |
| 32 | - scale = max(((float)windowSize.width + point.x) / ((float)src.cols), | |
| 33 | - ((float)windowSize.height + point.y) / ((float)src.rows)); | |
| 34 | - Size size((int)(scale*src.cols + 0.5F), (int)(scale*src.rows + 0.5F)); | |
| 35 | - resize(src, scaledSrc, size); | |
| 32 | + scale = max(((float)windowSize.width + point.x) / ((float)src.m().cols), | |
| 33 | + ((float)windowSize.height + point.y) / ((float)src.m().rows)); | |
| 34 | + Size size((int)(scale*src.m().cols + 0.5F), (int)(scale*src.m().rows + 0.5F)); | |
| 35 | + scaledSrc = resize(src, size); | |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | - Mat mine(bool *newImg) | |
| 38 | + Template resize(const Template &src, const Size &size) | |
| 39 | 39 | { |
| 40 | - // Copy region of winSize region of img into m | |
| 41 | - Mat window(windowSize.height, windowSize.width, CV_8U, | |
| 42 | - (void*)(scaledSrc.data + point.y * scaledSrc.step + point.x * scaledSrc.elemSize()), | |
| 43 | - scaledSrc.step); | |
| 40 | + Template dst(src.file); | |
| 41 | + for (int i=0; i<src.size(); i++) { | |
| 42 | + Mat buffer; | |
| 43 | + cv::resize(src[i], buffer, size); | |
| 44 | + dst.append(buffer); | |
| 45 | + } | |
| 46 | + return dst; | |
| 47 | + } | |
| 44 | 48 | |
| 45 | - Mat sample; | |
| 46 | - window.copyTo(sample); | |
| 49 | + Template mine(bool *newImg) | |
| 50 | + { | |
| 51 | + Template dst(src.file); | |
| 52 | + // Copy region of winSize region of img into m | |
| 53 | + for (int i=0; i<scaledSrc.size(); i++) { | |
| 54 | + Mat window(windowSize.height, windowSize.width, CV_8U, | |
| 55 | + (void*)(scaledSrc[i].data + point.y * scaledSrc[i].step + point.x * scaledSrc[i].elemSize()), | |
| 56 | + scaledSrc[i].step); | |
| 57 | + Mat sample; | |
| 58 | + window.copyTo(sample); | |
| 59 | + dst.append(sample); | |
| 60 | + } | |
| 47 | 61 | |
| 48 | - if ((int)(point.x + (1.0F + stepFactor) * windowSize.width) < scaledSrc.cols) | |
| 62 | + if ((int)(point.x + (1.0F + stepFactor) * windowSize.width) < scaledSrc.m().cols) | |
| 49 | 63 | point.x += (int)(stepFactor * windowSize.width); |
| 50 | 64 | else { |
| 51 | 65 | point.x = offset.x; |
| 52 | - if ((int)(point.y + (1.0F + stepFactor) * windowSize.height) < scaledSrc.rows) | |
| 66 | + if ((int)(point.y + (1.0F + stepFactor) * windowSize.height) < scaledSrc.m().rows) | |
| 53 | 67 | point.y += (int)(stepFactor * windowSize.height); |
| 54 | 68 | else { |
| 55 | 69 | point.y = offset.y; |
| 56 | 70 | scale *= scaleFactor; |
| 57 | 71 | if (scale <= 1.0F) { |
| 58 | - Size size((int)(scale*src.cols), (int)(scale*src.rows)); | |
| 59 | - resize(src, scaledSrc, size); | |
| 72 | + Size size((int)(scale*src.m().cols), (int)(scale*src.m().rows)); | |
| 73 | + scaledSrc = resize(src, size); | |
| 60 | 74 | } else { |
| 61 | 75 | *newImg = true; |
| 62 | - return sample; | |
| 76 | + return dst; | |
| 63 | 77 | } |
| 64 | 78 | } |
| 65 | 79 | } |
| 66 | 80 | |
| 67 | 81 | *newImg = false; |
| 68 | - return sample; | |
| 82 | + return dst; | |
| 69 | 83 | } |
| 70 | 84 | }; |
| 71 | 85 | |
| ... | ... | @@ -156,10 +170,10 @@ class CascadeClassifier : public Classifier |
| 156 | 170 | negative = getNegative(offset); |
| 157 | 171 | samplingLocker.unlock(); |
| 158 | 172 | |
| 159 | - Miner miner(negative.m(), windowSize(), offset); | |
| 173 | + Miner miner(negative, windowSize(), offset); | |
| 160 | 174 | forever { |
| 161 | 175 | bool newImg; |
| 162 | - Template sample(negative.file, miner.mine(&newImg)); | |
| 176 | + Template sample = miner.mine(&newImg); | |
| 163 | 177 | if (!newImg) { |
| 164 | 178 | if (negSamples.size() >= numNegs) |
| 165 | 179 | return passedNegatives; |
| ... | ... | @@ -169,7 +183,6 @@ class CascadeClassifier : public Classifier |
| 169 | 183 | QMutexLocker miningLocker(&miningMutex); |
| 170 | 184 | if (negSamples.size() >= numNegs) |
| 171 | 185 | return passedNegatives; |
| 172 | - | |
| 173 | 186 | negSamples.append(sample); |
| 174 | 187 | printf("Negative samples: %d\r", negSamples.size()); |
| 175 | 188 | } |
| ... | ... | @@ -198,7 +211,7 @@ class CascadeClassifier : public Classifier |
| 198 | 211 | stages.append(next_stage); |
| 199 | 212 | } |
| 200 | 213 | |
| 201 | - for (int i = 0; i < numStages; i++) { | |
| 214 | + for (int i = 0; i < stages.size(); i++) { | |
| 202 | 215 | qDebug() << "===== TRAINING" << i << "stage ====="; |
| 203 | 216 | qDebug() << "<BEGIN"; |
| 204 | 217 | ... | ... |
openbr/plugins/imgproc/slidingwindow.cpp
| ... | ... | @@ -95,75 +95,77 @@ class SlidingWindowTransform : public MetaTransform |
| 95 | 95 | Size minObjectSize(minSize, minSize); |
| 96 | 96 | Size maxObjectSize; |
| 97 | 97 | |
| 98 | - for (int i=0; i<t.size(); i++) { | |
| 99 | - Mat m; | |
| 100 | - OpenCVUtils::cvtUChar(t[i], m); | |
| 101 | - QList<Rect> rects; | |
| 102 | - QList<float> confidences; | |
| 103 | - | |
| 104 | - if (maxObjectSize.height == 0 || maxObjectSize.width == 0) | |
| 105 | - maxObjectSize = m.size(); | |
| 106 | - | |
| 107 | - Mat imageBuffer(m.rows + 1, m.cols + 1, CV_8U); | |
| 108 | - | |
| 109 | - for (double factor = 1; ; factor *= scaleFactor) { | |
| 110 | - int dx, dy; | |
| 111 | - Size originalWindowSize = classifier->windowSize(&dx, &dy); | |
| 112 | - | |
| 113 | - Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); | |
| 114 | - Size scaledImageSize(cvRound(m.cols/factor ), cvRound(m.rows/factor)); | |
| 115 | - Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height); | |
| 116 | - | |
| 117 | - if (processingRectSize.width <= 0 || processingRectSize.height <= 0) | |
| 118 | - break; | |
| 119 | - if (windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height) | |
| 120 | - break; | |
| 121 | - if (windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height) | |
| 122 | - continue; | |
| 123 | - | |
| 124 | - Mat scaledImage(scaledImageSize, CV_8U, imageBuffer.data); | |
| 125 | - resize(m, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); | |
| 98 | + Mat m = t.m(); | |
| 99 | + QList<Rect> rects; | |
| 100 | + QList<float> confidences; | |
| 101 | + | |
| 102 | + if (maxObjectSize.height == 0 || maxObjectSize.width == 0) | |
| 103 | + maxObjectSize = m.size(); | |
| 104 | + | |
| 105 | + for (double factor = 1; ; factor *= scaleFactor) { | |
| 106 | + int dx, dy; | |
| 107 | + Size originalWindowSize = classifier->windowSize(&dx, &dy); | |
| 108 | + | |
| 109 | + Size windowSize(cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); | |
| 110 | + Size scaledImageSize(cvRound(m.cols/factor ), cvRound(m.rows/factor)); | |
| 111 | + Size processingRectSize(scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height); | |
| 112 | + | |
| 113 | + if (processingRectSize.width <= 0 || processingRectSize.height <= 0) | |
| 114 | + break; | |
| 115 | + if (windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height) | |
| 116 | + break; | |
| 117 | + if (windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height) | |
| 118 | + continue; | |
| 119 | + | |
| 120 | + Template scaleBuffer(t.file); | |
| 121 | + for (int i=0; i<t.size(); i++) { | |
| 122 | + Mat scaledImage; | |
| 123 | + resize(t[i], scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR); | |
| 124 | + scaleBuffer.append(scaledImage); | |
| 125 | + } | |
| 126 | 126 | |
| 127 | - Template repImage(t.file, scaledImage); | |
| 128 | - repImage = classifier->preprocess(repImage); | |
| 127 | + Template rep(t.file); | |
| 128 | + rep = classifier->preprocess(scaleBuffer); | |
| 129 | 129 | |
| 130 | - int step = factor > 2. ? 1 : 2; | |
| 131 | - for (int y = 0; y < processingRectSize.height; y += step) { | |
| 132 | - for (int x = 0; x < processingRectSize.width; x += step) { | |
| 133 | - Mat window = repImage.m()(Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); | |
| 134 | - Template t(window); | |
| 130 | + int step = factor > 2. ? 1 : 2; | |
| 131 | + for (int y = 0; y < processingRectSize.height; y += step) { | |
| 132 | + for (int x = 0; x < processingRectSize.width; x += step) { | |
| 133 | + Template window(t.file); | |
| 134 | + for (int i=0; i<rep.size(); i++) { | |
| 135 | + Mat w = rep[i](Rect(Point(x, y), Size(originalWindowSize.width + dx, originalWindowSize.height + dy))).clone(); | |
| 136 | + window.append(w); | |
| 137 | + } | |
| 135 | 138 | |
| 136 | - float confidence = 0; | |
| 137 | - int result = classifier->classify(t, false, &confidence); | |
| 139 | + float confidence = 0; | |
| 140 | + int result = classifier->classify(window, false, &confidence); | |
| 138 | 141 | |
| 139 | - if (result == 1) { | |
| 140 | - rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); | |
| 141 | - confidences.append(confidence); | |
| 142 | - } | |
| 142 | + if (result == 1) { | |
| 143 | + rects.append(Rect(cvRound(x*factor), cvRound(y*factor), windowSize.width, windowSize.height)); | |
| 144 | + confidences.append(confidence); | |
| 145 | + } | |
| 143 | 146 | |
| 144 | - // TODO: Add non ROC mode | |
| 147 | + // TODO: Add non ROC mode | |
| 145 | 148 | |
| 146 | - if (result == 0) | |
| 147 | - x += step; | |
| 148 | - } | |
| 149 | + if (result == 0) | |
| 150 | + x += step; | |
| 149 | 151 | } |
| 150 | 152 | } |
| 153 | + } | |
| 151 | 154 | |
| 152 | - OpenCVUtils::group(rects, confidences, confidenceThreshold, minNeighbors, eps); | |
| 155 | + OpenCVUtils::group(rects, confidences, confidenceThreshold, minNeighbors, eps); | |
| 153 | 156 | |
| 154 | - if (!enrollAll && rects.empty()) { | |
| 155 | - rects.append(Rect(0, 0, m.cols, m.rows)); | |
| 156 | - confidences.append(-std::numeric_limits<float>::max()); | |
| 157 | - } | |
| 157 | + if (!enrollAll && rects.empty()) { | |
| 158 | + rects.append(Rect(0, 0, m.cols, m.rows)); | |
| 159 | + confidences.append(-std::numeric_limits<float>::max()); | |
| 160 | + } | |
| 158 | 161 | |
| 159 | - for (int j=0; j<rects.size(); j++) { | |
| 160 | - Template u(t.file, m); | |
| 161 | - u.file.set("Confidence", confidences[j]); | |
| 162 | - const QRectF rect = OpenCVUtils::fromRect(rects[j]); | |
| 163 | - u.file.appendRect(rect); | |
| 164 | - u.file.set("Face", rect); | |
| 165 | - dst.append(u); | |
| 166 | - } | |
| 162 | + for (int j=0; j<rects.size(); j++) { | |
| 163 | + Template u(t.file, m); | |
| 164 | + u.file.set("Confidence", confidences[j]); | |
| 165 | + const QRectF rect = OpenCVUtils::fromRect(rects[j]); | |
| 166 | + u.file.appendRect(rect); | |
| 167 | + u.file.set("Face", rect); | |
| 168 | + dst.append(u); | |
| 167 | 169 | } |
| 168 | 170 | } |
| 169 | 171 | } | ... | ... |