/* segment using HMM and then histogram clustering */ void cluster_segment(int* q, double** features, int frames_read, int feature_length, int nHMM_states, int histogram_length, int nclusters, int neighbour_limit) { int i, j; /*****************************/ if (0) { /* try just using the predominant bin number as a 'decoded state' */ nHMM_states = feature_length + 1; /* allow a 'zero' state */ double chroma_thresh = 0.05; double maxval; int maxbin; for (i = 0; i < frames_read; i++) { maxval = 0; for (j = 0; j < feature_length; j++) { if (features[i][j] > maxval) { maxval = features[i][j]; maxbin = j; } } if (maxval > chroma_thresh) q[i] = maxbin; else q[i] = feature_length; } } if (1) { /*****************************/ /* scale all the features to 'balance covariances' during HMM training */ double scale = 10; for (i = 0; i < frames_read; i++) for (j = 0; j < feature_length; j++) features[i][j] *= scale; /* train an HMM on the features */ /* create a model */ model_t* model = hmm_init(features, frames_read, feature_length, nHMM_states); /* train the model */ hmm_train(features, frames_read, model); /* printf("\n\nafter training:\n"); hmm_print(model); */ /* decode the hidden state sequence */ viterbi_decode(features, frames_read, model, q); hmm_close(model); /*****************************/ } /*****************************/ /* fprintf(stderr, "HMM state sequence:\n"); for (i = 0; i < frames_read; i++) fprintf(stderr, "%d ", q[i]); fprintf(stderr, "\n\n"); */ /* create histograms of states */ double* h = (double*) malloc(frames_read*nHMM_states*sizeof(double)); /* vector in row major order */ create_histograms(q, frames_read, nHMM_states, histogram_length, h); /* cluster the histograms */ int nbsched = 20; /* length of inverse temperature schedule */ double* bsched = (double*) malloc(nbsched*sizeof(double)); /* inverse temperature schedule */ double b0 = 100; double alpha = 0.7; bsched[0] = b0; for (i = 1; i < nbsched; i++) bsched[i] = alpha * bsched[i-1]; cluster_melt(h, nHMM_states, frames_read, bsched, nbsched, nclusters, neighbour_limit, q); /* now q holds a sequence of cluster assignments */ free(h); free(bsched); }
/* cwiid_mesg_callback_t has undergone a few changes lately, hopefully this * will be the last. Some programs need to know which messages were received * simultaneously (e.g. for correlating accelerometer and IR data), and the * sequence number mechanism used previously proved cumbersome, so we just * pass an array of messages, all of which were received at the same time. * The id is to distinguish between multiple wiimotes using the same callback. * */ void cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], struct timespec *timestamp) { int i; //int valid_source; for (i=0; i < mesg_count; i++) { switch (mesg[i].type) { case CWIID_MESG_STATUS: printf("Status Report: battery=%d extension=", mesg[i].status_mesg.battery); switch (mesg[i].status_mesg.ext_type) { case CWIID_EXT_NONE: printf("none"); break; case CWIID_EXT_NUNCHUK: printf("Nunchuk"); break; case CWIID_EXT_CLASSIC: printf("Classic Controller"); break; default: printf("Unknown Extension"); break; } printf("\n"); break; case CWIID_MESG_BTN: printf("Button Report: %.4X\n", mesg[i].btn_mesg.buttons); button_state = mesg[i].btn_mesg.buttons; if (button_state == 0 && accs.next) { dump_acc_stream(&accs); printf("\n\nDOWNSAMPLED\n"); struct acc_report *ds = downsample_acc_stream(&accs); dump_acc_stream(ds); printf("\n\nQUANTIZED\n"); struct observation *obs = run_quantizer(ds); StateSequenceRef sequence = createStateSequence(obs->sequence, obs->sequence_len); observation_free(obs); // gets copied int n_trained_index = n_trained / 3; if (n_trained == -1) { printf("GOOD, YOU'VE SYNCED. PROCEEDING TO TRAIN 0."); n_trained++; } else if (n_trained_index < n_gestures) { hmm_train(hmms[n_trained_index], &sequence, 1); printf("TRAINED %d\n", n_trained_index); n_trained++; n_trained_index = n_trained / 3; if (n_trained_index < n_gestures) printf("PROCEEDING TO TRAIN %d\n", n_trained_index); else printf("DONE TRAINING, WOO. On to classifying.\n"); } else { printf("\nCLASSIFYING\n"); double max_p = 0.0; int max_i = 0; for(int i = 0; i < n_gestures; i++) { double p = getProbability(hmms[i], sequence); printf(" P(%d) = %f\n", i, p); if (p > max_p) { max_p = p; max_i = i; } } printf("\n CLASSIFICATION RESULTS: %d with P=%f\n", max_i, max_p); } reset_acc_stream(ds); free(ds); acc_cursor = reset_acc_stream(&accs); } break; case CWIID_MESG_ACC: if (button_state & 0x0004) { struct timeval now; gettimeofday(&now, NULL); /* printf("Acc Report: x=%d, y=%d, z=%d %ld %ld\n", mesg[i].acc_mesg.acc[CWIID_X], mesg[i].acc_mesg.acc[CWIID_Y], mesg[i].acc_mesg.acc[CWIID_Z], now.tv_sec, now.tv_usec); */ acc_cursor = add_acc_report( acc_cursor, (signed char)mesg[i].acc_mesg.acc[CWIID_X], (signed char)mesg[i].acc_mesg.acc[CWIID_Y], (signed char)mesg[i].acc_mesg.acc[CWIID_Z], now.tv_sec, now.tv_usec); } break; case CWIID_MESG_IR: printf("IR Report: elided"); printf("\n"); break; case CWIID_MESG_NUNCHUK: printf("Nunchuk Report elided\n"); break; case CWIID_MESG_CLASSIC: printf("Classic Report: btns=%.4X l_stick=(%d,%d) r_stick=(%d,%d) " "l=%d r=%d\n", mesg[i].classic_mesg.buttons, mesg[i].classic_mesg.l_stick[CWIID_X], mesg[i].classic_mesg.l_stick[CWIID_Y], mesg[i].classic_mesg.r_stick[CWIID_X], mesg[i].classic_mesg.r_stick[CWIID_Y], mesg[i].classic_mesg.l, mesg[i].classic_mesg.r); break; case CWIID_MESG_ERROR: if (cwiid_close(wiimote)) { fprintf(stderr, "Error on wiimote disconnect\n"); exit(-1); } exit(0); break; default: printf("Unknown Report"); break; } } }