Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    Mat im = imread("logo_2.png");
    resize(im,im,Size(8,8)); // keep small for demo output below

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    Mat im = imread("logo_2.png");
    resize(im,im,Size(8,8)); // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

// if you squint really hard, you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

// if you squint really hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

image description

// squint hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }

int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << im << endl;
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

image description

[  0,   0,   0,   0,   0,   0,   3,   2,  21,  36,  18, 247,  36,  18, 247,  26,  13, 179,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,  22,  11, 152,   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0;
  45, 190, 100,  48, 204, 108,  48, 204, 108,   0,   0,   0,   0,   0,   0,  22,   8,   0,   0,   0,   0, 212,  77,   0;
  48, 204, 108,   0,   0,   0,   0,   0,   0,   9,  38,  20, 212,  77,   0,   0,   0,   0,   0,   0,   0, 212,  77,   0;
  48, 204, 108,  48, 204, 108,  48, 204, 108,   0,   0,   0,   0,   0,   0, 212,  77,   0, 212,  77,   0, 167,  61,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0]

// squint hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   }
} // this is the "exact match"
// {   return norm(a,b) < 32;   } // if you want something more tolerant


int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << im << endl;
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

image description

[  0,   0,   0,   0,   0,   0,   3,   2,  21,  36,  18, 247,  36,  18, 247,  26,  13, 179,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,  22,  11, 152,   0,   0,   0,   0,   0,   0,  36,  18, 247,   0,   0,   0,   0,   0,   0;
  45, 190, 100,  48, 204, 108,  48, 204, 108,   0,   0,   0,   0,   0,   0,  22,   8,   0,   0,   0,   0, 212,  77,   0;
  48, 204, 108,   0,   0,   0,   0,   0,   0,   9,  38,  20, 212,  77,   0,   0,   0,   0,   0,   0,   0, 212,  77,   0;
  48, 204, 108,  48, 204, 108,  48, 204, 108,   0,   0,   0,   0,   0,   0, 212,  77,   0, 212,  77,   0, 167,  61,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0]

// squint hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

[edit]

if you don't want an exact match, but more some epsilon region, you could change the predicate to:

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return norm(a,b) < 90;   } // some heuristic value

then, ofc. you get less, but more "general" clusters:

[0, 0, 0, 1, 1, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 2, 2, 2, 0, 0, 0, 0, 3;
 2, 0, 0, 0, 3, 0, 0, 3;
 2, 2, 2, 0, 0, 3, 3, 3;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
4 unique colors
click to hide/show revision 9
No.9 Revision

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   } // this is the "exact match"
// {   return norm(a,b) < 32;   } // if you want something more tolerant


int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << im << endl;
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

image description

// squint hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

[edit]

if you don't want an exact match, but more some epsilon region, you could change the predicate to:

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return norm(a,b) < 90;   } // some heuristic value

then, ofc. you get less, but more "general" clusters:

[0, 0, 0, 1, 1, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 2, 2, 2, 0, 0, 0, 0, 3;
 2, 0, 0, 0, 3, 0, 0, 3;
 2, 2, 2, 0, 0, 3, 3, 3;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
4 unique colors
click to hide/show revision 10
No.10 Revision

if you meant: "all pixels with exact same values should go into the same cluster", - you could try with partition :

#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return a == b;   } // this is the "exact match"
// {   return norm(a,b) < 32;   } // if you want something more tolerant


int main( int argc, char** argv )
{
    // opencv logo from webpage
    Mat im = imread("logo_2.png");
    // keep small for demo output below
    resize(im,im,Size(8,8)); 

    // partition wants a vector, so we need a copy ;(
    Vec3b *p = im.ptr<Vec3b>();
    vector<Vec3b> pix(p, p+im.total());

    // now cluster:
    vector<int> labels;
    int unique = cv::partition(pix, labels, pixel_equal);

    // debug output
    Mat lm = Mat(labels).reshape(1,im.rows);
    cerr << im << endl;
    cerr << lm << endl;
    cerr << unique << " unique colors" << endl;
    return 0;
}

image description ===> image description

// squint hard, and you can still see the opencv logo. (0..3:red, 4--6:green, 7..10:blue)
[0, 0, 1, 2, 2, 3, 0, 0;
 0, 0, 2, 0, 0, 2, 0, 0;
 0, 0, 4, 0, 0, 2, 0, 0;
 5, 6, 6, 0, 0, 7, 0, 8;
 6, 0, 0, 9, 8, 0, 0, 8;
 6, 6, 6, 0, 0, 8, 8, 10;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
11 unique colors

[edit]

if you don't want an exact match, but more some epsilon region, you could change the predicate to:

static bool pixel_equal(const Vec3b &a, const Vec3b &b)
{   return norm(a,b) < 90;   } // some heuristic value

then, ofc. you get less, but more "general" clusters:

[0, 0, 0, 1, 1, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 0, 0, 1, 0, 0, 1, 0, 0;
 2, 2, 2, 0, 0, 0, 0, 3;
 2, 0, 0, 0, 3, 0, 0, 3;
 2, 2, 2, 0, 0, 3, 3, 3;
 0, 0, 0, 0, 0, 0, 0, 0;
 0, 0, 0, 0, 0, 0, 0, 0]
4 unique colors