Created
August 19, 2016 11:09
-
-
Save berak/8cd27cb8219d7c58bd24e99ea9361ac8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "opencv2/opencv.hpp" | |
| using namespace cv; | |
| #include <iostream> | |
| using namespace std; | |
| // | |
| // b g r y cr cb h s v like pearls ona string. | |
| // | |
| Mat feature(const Vec3b &pixel) { | |
| // normalized bgr; | |
| float b = float(pixel[0]) / 255; | |
| float g = float(pixel[1]) / 255; | |
| float r = float(pixel[2]) / 255; | |
| // ycrcb | |
| float y = 0.299f * r + 0.587f * g + 0.114f * b; | |
| float cr = 0.713f * (r - y) + 0.5f; | |
| float cb = 0.564f * (b - y) + 0.5f; | |
| // hsv | |
| float M(max(max(b,g),r)); | |
| float m(min(min(b,g),r)); | |
| float md = M - m; | |
| float A = 1.0f / 6; | |
| float v = M; | |
| float s = (M>0) ? (md/M) : 0; | |
| float h = (md==0) ? 0 : | |
| (M==r) ? ( A*(g-b)/md) : | |
| (M==g) ? (2*A+A*(b-r)/md) : | |
| (3*A+A*(r-g)/md); | |
| return Mat_<float>(1,9) << b,g,r, y,cr,cb, h,s,v; // 9x1 | |
| } | |
| // | |
| // txt file with 3 numbers on a row, b g r | |
| // (made a little colorpicker, that samples 8nb per click) | |
| int getPos(Mat &features, int off, int n) | |
| { | |
| ifstream in("skin_bgr.txt"); | |
| int b=0,g=0,r=0, i=0; | |
| while ((in >> b) && (in >> g) && (in >> b)) | |
| { | |
| i++; | |
| if (i<=off) continue; | |
| if (i>off+n) break; | |
| Mat row = feature(Vec3b(b,g,r)); | |
| features.push_back(row); | |
| } | |
| return features.rows; | |
| } | |
| // | |
| // negative images from browser cache, no humans allowed ! | |
| // (a whole hardcoded folder) | |
| int getNeg(Mat &features, int off, int n) | |
| { | |
| int k=0, of=features.rows; | |
| vector<String> fn; | |
| glob("c:/data/img/noskin", fn); | |
| for (size_t i=0; i<fn.size(); i++) | |
| { | |
| Mat img = imread(fn[i]); | |
| if (img.empty()) | |
| continue; | |
| for (int i=0; i<200; i++) // N random pixel samples per image | |
| { | |
| k++; | |
| if (k<=off) continue; | |
| if (k>off+n) break; | |
| int x = theRNG().uniform(5,img.cols-5); | |
| int y = theRNG().uniform(5,img.rows-5); | |
| Vec3b p = img.at<Vec3b>(y,x); | |
| Mat row = feature(p); | |
| features.push_back(row); | |
| } | |
| } | |
| return features.rows - of; | |
| } | |
| int main() | |
| { | |
| int ntest = 1000; | |
| //print_colors(); | |
| Mat features; | |
| int p = getPos(features, ntest, 0xffff); // save N for testing later | |
| cout << p << " positive, "; | |
| int n = getNeg(features, ntest, 0xffff); | |
| cout << n << " negative probes, "; | |
| cout << features.size() << " feature elems." << endl; | |
| Mat labels(features.rows, 1, CV_32S, Scalar(1)); | |
| labels(Range(p,labels.rows),Range::all()) = 0; | |
| Ptr<ml::SVM> svm = ml::SVM::create(); | |
| svm->setType(ml::SVM::NU_SVC); | |
| svm->setKernel(ml::SVM::LINEAR); | |
| svm->setNu(0.55f); | |
| svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 1000, 1e-6)); | |
| svm->setC(60); | |
| bool ok = svm->train(features , ml::ROW_SAMPLE , labels); | |
| cout << "training done: " << ok << "." << endl; | |
| svm->save("colors_svm.xml"); | |
| Mat query; | |
| p = getPos(query, 0, ntest); // first N are for testing | |
| cout << p << " positive, "; | |
| n = getNeg(query, 0, ntest); | |
| cout << n << " negative probes, "; | |
| cout << query.size() << " query elems." << endl; | |
| Mat truth(query.rows, 1, CV_32F, Scalar(1)); | |
| truth(Range(p,truth.rows),Range::all()) = 0; | |
| Ptr<ml::SVM> svm2 = ml::SVM::load("colors_svm.xml"); | |
| Mat pred; | |
| svm2->predict(query, pred); | |
| Mat_<int> confusion(2,2, 0); | |
| for (size_t i=0; i<pred.total(); i++) | |
| { | |
| int r = int(pred.at<float>(i)); | |
| int c = int(truth.at<float>(i)); | |
| confusion(r, c) ++; | |
| } | |
| cout << confusion << endl; | |
| /* Mat eq(pred == truth); | |
| int nz = countNonZero(eq); | |
| int nelm = (ntest*2); */ | |
| int nz = sum(confusion.diag())[0]; | |
| int nelm = sum(confusion)[0]; | |
| float acc = (float(nz) / nelm); | |
| cout << nz << "/" << nelm << " : " << acc << endl; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment