Skip to content

Instantly share code, notes, and snippets.

@berak
Created August 19, 2016 11:09
Show Gist options
  • Select an option

  • Save berak/8cd27cb8219d7c58bd24e99ea9361ac8 to your computer and use it in GitHub Desktop.

Select an option

Save berak/8cd27cb8219d7c58bd24e99ea9361ac8 to your computer and use it in GitHub Desktop.
#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