K-meansについて教えてください。
OpenCVを利用し、肌色部分をHSV値の範囲により緑色に変えています。(while文)ここから顔、右手、左手の3つにK-meansを使って三色に分けたいのですが、どのように変えればいいですか?クラスタの中心の座標を使うので座標でクラスタリングしたいです。
#include "stdafx.h"
#include <cv.h>
#include <highgui.h>
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")
#include <math.h>
#define LINE_THICKNESS -1
#define LINE_TYPE 8
#define SHIFT 0
#define MAX_CLUSTERS (3)
int _tmain(int argc, _TCHAR* argv[])
{
CvSeq *objects;
CvRect *r;
char *cascade_name;
int key;
int i = 1;
//////////////////////////////////////////////////////////////////
int x, y, W, H;
int ofs, idx;
unsigned char *pix;
int pixCnt;
int pixCnt2;
int h, s, v;
double n, m;
double aveH, aveS, aveV;
double divh, divs, divv;
double divH, divS, divV;
double aveH2, aveS2, aveV2;
double sigmaH, sigmaS, sigmaV;
///////////////////////////////////////////////////////////////////////////
CvCapture* src;
IplImage *frame1;
IplImage *frame2;
IplImage *frame3;
CvHaarClassifierCascade *cascade;
CvMemStorage *storage;
cvNamedWindow ("原画像");
cvNamedWindow ("HSV画像");
cvNamedWindow ("処理結果");
// カスケード・ファイルの読み込み
cascade_name = "haarcascade_frontalface_default.xml";
cascade = (CvHaarClassifierCascade *) cvLoad(cascade_name, 0, 0, 0);
storage = cvCreateMemStorage (0);
cvClearMemStorage(storage);
src = cvCaptureFromCAM(0);
if(src == NULL){printf("映像が取得できません。\n");
cvWaitKey(0);
return -1;
}
frame1 = cvQueryFrame(src);
frame2 = cvCreateImage(cvGetSize(frame1), IPL_DEPTH_8U, 3);
frame3 = cvCreateImage(cvGetSize(frame1), IPL_DEPTH_8U, 3);
//顔領域の検出
objects = cvHaarDetectObjects(frame1, cascade, storage, 1.1, 3, 0, cvSize(0, 0));
r = (CvRect *) cvGetSeqElem(objects, i);
cvRectangle(frame1, cvPoint(r->x, r->y)
, cvPoint(r->x + r->width, r->y + r->height), CV_RGB(0, 255, 0), 4);
cvCvtColor(frame1, frame2, CV_BGR2HSV);
/////////////////////////////////////////////////////////////////////////
pix = (unsigned char*)frame2->imageData;
pixCnt = frame2->width*frame2->height;
pixCnt2 = r->width/6*r->height/6;
printf( "%d\n", pixCnt );
printf("pixCnt2: %d\n", pixCnt2);
aveV = aveS = aveH = 0;
for( y=r->y+r->height/2; y<r->y+r->height/2+r->height/6; y++ ) {
ofs = y*frame2->widthStep;
for( x=r->x+r->width*2/3; x<r->x+r->width*2/3+r->width/6; x++ ) {
idx = ofs + x*3;
aveS += pix[idx+1];
if (pix[idx+1] >= 0) {
aveH += pix[idx];
} else {
pixCnt2--;
}
}
}
aveS /= pixCnt2;
aveH /= pixCnt2;
printf("H%f,S%f,V%f\n", aveH, aveS, aveV);
aveH2 = 0;
divh = 0;
for( y=r->y; y<r->y+r->height; y++ ) {
ofs = y*frame2->widthStep;
for( x=r->x; x<r->x+r->width; x++ ) {
idx = ofs + x*3;
aveH2 += (pix[idx]-aveH)*(pix[idx]-aveH);
}
}
aveH2 /= pixCnt2;
divH = aveH2;
sigmaH = sqrt(aveH2);
while(1){
frame1 = cvQueryFrame(src); if(frame1 == NULL) break; // 1フレーム取得
cvRectangle(frame1, cvPoint(r->x, r->y) // 検出部に四角枠描画
, cvPoint(r->x + r->width, r->y + r->height), CV_RGB(0, 255, 0), 4);
cvCvtColor(frame1, frame2, CV_BGR2HSV);
cvShowImage ("原画像", frame1); // 検出結果表示
cvShowImage ("HSV画像", frame2); // 検出結果表示
for( y=0; y<frame2->height; y++ ) {
ofs = y*frame2->widthStep;
for( x=0; x<frame2->width; x++ ) {
idx = ofs + x*3;
v = pix[idx+2];
s = pix[idx+1];
h = pix[idx];
if ((h > aveH-sigmaH && h < aveH+sigmaH)&& (s > aveS-10 && s < aveS+10)) {
pix[idx+2] = 230;
pix[idx+1] = 230;
pix[idx] = 60;
}
else {
pix[idx+2] = 0;
pix[idx+1] = 0;
pix[idx] = 0;
}
}
}
cvCvtColor(frame2, frame3, CV_HSV2BGR);
cvShowImage ("処理結果", frame3); // 検出結果表示
if(cvWaitKey(33) == 27) break; // ESCキーを押した時終了
}
// ウィンドウ・キャプチャ・メモリの解放
cvReleaseImage(&frame1);
cvReleaseImage(&frame2);
cvReleaseImage(&frame3);
cvDestroyWindow("原画像");
cvDestroyWindow("HSV画像");
cvDestroyWindow("処理結果");
cvReleaseCapture(&src);
cvReleaseMemStorage(&storage);
return 0;
}
お礼
回答有難うございます. プログラミングについて理解不足でした. 以上のご指導頂いた点を試してみて, もし理解できない場合は再度質問してみようと思います. 有難うございました.