Skip to content

Instantly share code, notes, and snippets.

@vanderlin
Created August 5, 2019 18:19
Show Gist options
  • Save vanderlin/f34fac6369fd1e85a10e2920af4b5d05 to your computer and use it in GitHub Desktop.
Save vanderlin/f34fac6369fd1e85a10e2920af4b5d05 to your computer and use it in GitHub Desktop.
Color Palette from image (OpenCV KMeans)
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
video.setDeviceID(0);
video.setup(320, 240);
}
//--------------------------------------------------------------
void ofApp::update(){
video.update();
if (video.isFrameNew() && bCapture) {
// copy to src
cv::Mat src;
ofxCv::copy(video, src);
// reshape to 1d and convert to 32f
int total = src.rows * src.cols;
cv::Mat data = src.reshape(1, total);
data.convertTo(data, CV_32F);
// run kmeans
cv::Mat colors;
std::vector<int> labels;
cv::kmeans(data, k, labels, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 10, 1.0), 3, cv::KmeansFlags::KMEANS_PP_CENTERS, colors);
// remap color
for(int i=0; i<total; i++) {
data.at<float>(i, 0) = colors.at<float>(labels[i], 0);
data.at<float>(i, 1) = colors.at<float>(labels[i], 1);
data.at<float>(i, 2) = colors.at<float>(labels[i], 2);
}
// reshape back
cv::Mat output = data.reshape(3, src.rows);
output.convertTo(output, CV_8U);
// copy to ofImage
ofxCv::copy(output, image);
image.update();
// update color palette
palette.clear();
for(int i=0; i<k; i++) {
auto r = colors.at<float>(i, 0);
auto g = colors.at<float>(i, 1);
auto b = colors.at<float>(i, 2);
palette.push_back(ofColor(r, g, b));
}
// sort on brightness
ofSort(palette, [](ofColor &a, ofColor &b) -> bool {
return a.getBrightness() < b.getBrightness();
});
bCapture = false;
}
}
//--------------------------------------------------------------
void ofApp::draw(){
for(int i=0; i<palette.size(); i++) {
float x = video.getWidth();
float y = i * 30;
ofFill();
ofSetColor(palette[i]);
ofDrawRectangle(x, y, 100, 30);
}
ofSetColor(255);
video.draw(0, 0);
image.draw(0, video.getHeight());
ofDrawBitmapStringHighlight("press space to sample "+ofToString(ofGetFrameRate(), 0) + " fps "+ofToString(k)+" colors", 20, ofGetHeight()-20);
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
if (key == OF_KEY_UP) {
k ++;
}
if (key == OF_KEY_DOWN) {
k --;
if (k <= 0) k = 1;
}
if (key == ' ') {
bCapture = true;
}
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
}
#pragma once
#include "ofMain.h"
#include "ofxCv.h"
class ofApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void keyPressed(int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void mouseEntered(int x, int y);
void mouseExited(int x, int y);
void windowResized(int w, int h);
void dragEvent(ofDragInfo dragInfo);
void gotMessage(ofMessage msg);
ofVideoGrabber video;
ofImage image;
vector <ofColor> palette;
int k = 8;
bool bCapture = true;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment