すこしふしぎ.

VR/HI系院生による技術ブログ.まったりいきましょ.(友人ズとブログリレー中.さぼったら焼肉おごらなきゃいけない)

プレモルCM画像を作る with openFrameworks

こんにちは,1000chです. 先週1週間,ギリシャクレタ島まで学会にいって参りました. リゾート地なだけはあり良い景色がいっぱいでした. 中でも近くのサントリーニ島がとてもよい感じです.

f:id:ism1000ch:20140702182045j:plain

f:id:ism1000ch:20140628140003j:plain

せっかく良さげな写真が撮れたので,プレモルCM的な色抽出画像を作ってみたいと思います.

さてじゃーどう作るかってはなしですが,時間も余り無いので(リレー的な意味で)さらっとつくれるoFを使います. 色抽出はHSV空間を使えばまぁ良いでしょう.

しきい値設定のUI部分としてはofxUIを使います. 依存アドオンとしてofxXmlsettingsも使ってるみたいなので,併せて取り込んでおきます.

testapp.h

#pragma once

#include "ofMain.h"
#include "ofxUI.h" // add

class testApp : 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 windowResized(int w, int h);
        void dragEvent(ofDragInfo dragInfo);
        void gotMessage(ofMessage msg);
    
    // add from here
    void exit();
    void setupGui();
    void process();
    void guiEvent(ofxUIEventArgs &e);
    
    ofxUISuperCanvas *gui0;
    
    ofImage src_img;
    ofImage dst_img;
    
    string filename;
    float min_hue;
    float max_hue;
};

testapp.cpp

//書き換えたとこだけ抜粋
void testApp::setup(){
    filename = "coke";
    src_img.loadImage(filename + ".jpg");
    dst_img.allocate(src_img.width, src_img.height, OF_IMAGE_COLOR);
    
    setupGui();
    process();
}

void testApp::setupGui(){
    ofEnableSmoothing();
    ofSetCircleResolution(60);
    
    min_hue = 100;
    max_hue = 200;
    
    gui0 = new ofxUISuperCanvas("SLIDER WIDGETS");
    
    gui0->addSpacer();
    gui0->addLabel("min_hue");
    gui0->addSlider("min", 0.0, 255.0, &min_hue);
    gui0->addLabel("max_hue");
    gui0->addSlider("max", 0.0, 255.0, &max_hue);
    
    gui0->autoSizeToFitWidgets();
    ofAddListener(gui0->newGUIEvent,this,&testApp::guiEvent);
}

void testApp::process(){
    ofColor src_col,dst_col;
    for(int i=0; i<dst_img.height; i++){
        for (int j=0; j<dst_img.width; j++) {
            src_col = src_img.getColor(j, i);
            
            if( min_hue < src_col.getHue() && src_col.getHue() < max_hue){
                dst_col = src_col;
            } else {
                dst_col = ofColor(src_col.g);
            }
            dst_img.setColor(j, i, dst_col);
        }
    }
    dst_img.update();
}
//--------------------------------------------------------------
void testApp::guiEvent(ofxUIEventArgs &e){
    process();
    cout << min_hue << ":" << max_hue << endl;
}


//--------------------------------------------------------------
void testApp::draw(){
    ofPushMatrix();
    float rate = ofGetWidth() / (float)src_img.width / 2;
    ofScale(rate,rate);
    src_img.draw(0, 0);
    dst_img.draw(src_img.width, 0);
    ofPopMatrix();
}

//--------------------------------------------------------------
void testApp::exit()
{
    delete gui0;
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    switch (key)
    {

        case 'g':
        {
            gui0->toggleVisible();
            break;
        }
        case 's':
        {
            string save_filename =  filename + ofGetTimestampString() + ".jpg";
            dst_img.saveImage(save_filename);
            cout << "save as " << save_filename << endl;
            break;
        }
        default:
            break;
    }
}

HSVと言いつつ色相しか使ってないですけどねw ofColorのグレースケール化手法がすぐにわからなかったので,とりあえずココ参考にgreen要素そのものを使ってます.

実行結果

では.先程の画像を変換してみます.

動作動画はこちら.

入力画像1

f:id:ism1000ch:20140702182045j:plain

出力画像1

f:id:ism1000ch:20140702183804j:plain

海と教会の色がほぼほぼ同じだった(´・ω・`) s,v要素も使えばよいのかね.

入力画像2

f:id:ism1000ch:20140628140003j:plain

出力画像2(青抜き)

f:id:ism1000ch:20140702184101j:plain

プールだけのこった!

出力画像2(赤抜き)

f:id:ism1000ch:20140702184123j:plain

いい感じに花が抜けています.

ほかにもいくつかやってみましょう.

入力画像3

f:id:ism1000ch:20140628141759j:plain

出力画像3(赤抜き)

f:id:ism1000ch:20140702185014j:plain

ちょっち手が残った(´・ω・`)

入力画像4

f:id:ism1000ch:20140629113210j:plain

出力画像4(赤抜き)

f:id:ism1000ch:20140702185416j:plain

ちょっとバランスが難しいかな?一応花は抜けた.

入力画像5

f:id:ism1000ch:20140629122419j:plain

出力画像5(青抜き)

f:id:ism1000ch:20140702185512j:plain

ちょっち空が残った(´・ω・`)

出力画像5(茶抜き)

f:id:ism1000ch:20140702185600j:plain

奇麗に要塞が抜けたw

まとめ

とまぁ色抽出するプログラムを作ってみました.画像処理を始めて勉強した頃を思い出しますね.コーラの画像とかは意外といい出来では無いでしょうか.

しかし,素材的に海と空がかぶってしまうのがちょっと残念ですね.色相だけでなく,彩度,明度も扱えば改善されるのかなぁ.あとはドラッグ範囲のみに処理を行うとか.いずれやってみるかな.

ま,とりあえず今日はこんなとこでー. リレービハインド状態なので明日もがんばって何か書かないと!