音声認識エンジンJuliusの認識結果出力に関して

このQ&Aのポイント
  • 音声認識エンジンJuliusの認識結果をcsvファイルに出力し、ロボットの動きと連動させる開発を行っています。
  • Juliusの認識結果によって動きを変化させるため、認識した言葉に対応するファイルにのみ「1」を返す処理を行っています。
  • しかし、ポインタの型変換を行っても出力結果が「0」になってしまいます。エラーの原因と解決策を教えてください。
回答を見る
  • ベストアンサー

音声認識エンジンJuliusの認識結果出力に関して

現在、大学で音声認識とロボットとの連動における開発を行っています。 認識した言葉によってロボットの動きを変化させようと試みています。 具体的に、連動部分についてですが、以下の手順を理想としています。  Julius起動      ↓  認識結果をcsvもしくはtxtファイルに出力   (ex:file.csvに「おはよう」を認識したら「1」、「こんにちは」を認識したら「2」を出力させる)      ↓  認識した言葉によってそれぞれcsvファイルに0/1を返す   (ex:file.csvが「1」のときcsv1.csvに「1」・csv2.csv~csv10.csvに「0」を返す     同様にfile.csvが「2」のときcsv2.csvに「1」・csv1.csv,csv3.csv~csv.10.csvに「0」を返す)      ↓  Excelのマクロを使ってロボットのシーケンス制御と連動 連動の関係でcsvファイルへの出力が必要であり、 ロボットの動きと1対1対応をさせたいため、それぞれの単語用にcsvファイルを用意し それぞれ認識した単語に対応するファイルのみに「1」を返したいと思っています。 Juliusの認識結果を最初のfile.csvに「1」や「2」を出力することはできたのですが、 その後if文で場合分けをしようにもエラーがでてしまいます。 おそらく文字列の「1」や「2」だからC言語でエラーになるのかと推測します。 そこでポインタの型変換を試みたのですが、 最終的な出力結果はなぜか「0」になってしまいます。 csvの出力結果によって場合分けを行い指定の数字を出力させるには どうしたらよいでしょうか? ちなみに開発環境はWindowsXPです。 JuliusはMicrosoftVisualC++2008でビルドし、 コマンドプロンプトで認識エンジンを起動しています。 最後にJuliusに認識結果の出力に関するプログラムと 自身で追記したプログラムを載せるので参考にしていただければと思います。 C言語はまだ始めたばかりで初心者なので 何かご存知の方いらっしゃいましたらアドバイスお願いいたします。 julius/output_stdout.c static void //ttyout_pass2(NODE *hypo, int rank, Recog *recog) result_pass2(Recog *recog, void *dummy) { int i, j; int len; char ec[5] = {0x1b, '[', '1', 'm', 0}; WORD_INFO *winfo; WORD_ID *seq; int seqnum; int n, num; Sentence *s; RecogProcess *r; boolean multi; HMM_Logical *p; SentenceAlign *align; int c; int *csv; FILE *csv1; FILE *csv2;  <省略> /* output all confirmed words */ for(i=0;i<confwordnum;i++) { if (len + strlen(winfo->woutput[confword[i]]) > SPTEXTWIDTH) { for(j=len;j<writelen;j++) printf(" "); printf("\n"); for(j=i;j<confwordnum;j++) confword[j-i] = confword[j]; confwordnum -= i; len = 0; i = 0; writelen = 0; }  <省略> csv = fopen("file.csv", "w+"); csv1 = fopen("file1.csv", "w"); csv2 = fopen("file2.csv", "w"); if(csv1 == NULL){ printf("failed to open csv1 file\n"); }else { printf("succeed to open csv1 file\n"); } if(csv2 == NULL){ printf("failed to open csv2 file\n"); }else { printf("succeed to open csv2 file\n"); } for (i=0;i<seqnum;i++) { fprintf(csv, "%s\0", winfo->woutput[seq[i]]); /*文字列からint型(整数型)への変換と出力*/ c = atoi(csv); printf("%d\n", c); //出力結果:0\n0\n0\n0\n fprintf(csv1, "%d", c); //出力結果:0 } fclose(csv); fclose(csv1); fclose(csv2);  <省略>

質問者が選んだベストアンサー

  • ベストアンサー
  • myuki1232
  • ベストアンサー率57% (97/170)
回答No.3

比較が上手くいかないのは、文字列型と数値型の比較をしているからです。 直すならば、 if (atoi(winfo->woutput[seq[i]]) == 1) のようにするか、辞書の変更をやめて if (strcmp(winfo->woutput[seq[i]], "おはよう") != 0) のようにするといいでしょう。 しかし、このように単語と数値を対応させるプログラムを作るというのは、対応に追加や変更があったときに、変換プログラムと Excel のマクロの両方を変更しなければいけないので、あまり上手い方法ではないです。 シーケンス制御は Excel のマクロでやるのならば、単語と動作の対応付けはマクロの中だけでやってしまうべきです。それならばこんな余計なことで悩む必要はありません。

Klab-6E
質問者

お礼

丁寧なご回答ありがとうございます。 おかげで無事に課題をクリアできました。 マクロとの兼ね合いも考えましたが とりあえず今はこのプログラムでいこうと思います。 ありがとうございました。

その他の回答 (2)

  • myuki1232
  • ベストアンサー率57% (97/170)
回答No.2

Julius について軽く調べてきましたが、 winfo->woutput[seq[i]] には例で言うところの「おはよう」や「こんにちは」が入っているのではありませんか? だとすれば、それらの単語に対してどういう数値を割り当てるかを、自分で書かなくてはなりません。 あるいは、詳しく書かれていないので不明ですが、それらの処理は Excel のマクロ上でやってしまえば、いくつも csv ファイルを用意しなくても可能でしょう。

Klab-6E
質問者

補足

説明不足で申し訳ないです。 おっしゃるとおりです。 winfo->woutput[seq[i]] はJuliusの単語辞書とリンクしていて デフォルトだと「おはよう」や「こんにちは」と出力されるのですが、 if文で場合分けしたいので文字列のままだと扱えないと考え 単語辞書の該当箇所を数値に変更させました。 マクロをあまりよく理解していないので調べてみます。 よろしければ、if(winfo->woutput[seq[i]] == 1)のように 数値によって場合分けする処理がなぜうまくいかないか教えていただけますか。

  • myuki1232
  • ベストアンサー率57% (97/170)
回答No.1

数値と文字列とファイルの違いを憶えて下さい。 あなたのプログラムの、変数 csv はファイルポインタ型であるべきです。 プログラム中の file1.csv というファイル名は csv1.csv とは違うのでしょうか? 以下、同じものとして書きます。 動作的には、 file.csv への出力と csv*.csv への出力をひとつのプログラムでやるならば、ファイルの読み込みと文字列の変換は不要です。winfo->woutput[seq[i]] (か何か)をそのまま使って出力すればいいです。

Klab-6E
質問者

補足

ご指摘ありがとうございます。 file.csvとcsv1.csvは同一のものでした。 書き間違えていました。 すみません。 if(winfo->woutput[seq[i]] == 1){ fprintf(csv1, "1"); fprintf(csv2, "0"); … }else if(winfo->woutput[seq[i]] == 2){ … といったかんじで条件文をつくり winfo->woutput[seq[i]] の値によって場合分けしたいのですが、 if(winfo->woutput[seq[i]] = 1)の条件だとビルドはできても file1.csvやfile2.csvには何も出力されないです。 なので、一度file.csvファイルを読み込んで型変換が必要なのかなと思っていたのですが、 的外れなことをしていたのでしょうか?

関連するQ&A

  • cygwinを使ってcsvファイルを読み込み、出力させようとしています

    cygwinを使ってcsvファイルを読み込み、出力させようとしています。 とりあえず、読み込みのみのプログラムを作成し、 実行させてみたのですが(run ファイル名.csv と入力) 「Error: could not start C:\cygwin\home\ユーザー名ファイル名.csv」 と出力され、読み込みができず、困っています。 プログラム初心者です。 恐縮ですがご回答よろしくお願いします。 以下に、読み込みプログラムとcsvファイルを記載します。 (プログラムは拾い物です。) <プログラム> #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("comand error nyuuryoku keishiki\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("can not open file[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("data error[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("error(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("error(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("error(3)\n"); break; } if(*wp != '\0'){ printf("error(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); } <csvファイル> 1,2,3 11,12,13 21,22,23

  • アルファベットを入力するとすべてのアルファベットを小文字に変換して出力

    アルファベットを入力するとすべてのアルファベットを小文字に変換して出力するプログラムを作成しました。2度以上同じ処理を行う場合はその部分を関数としなければいけないのですが、実行結果のように出力できませんでした。。どこが間違っているのでしょうか? 実行結果↓ ************ AOmori ==>aomori iwate ==>iwate AKITA ==>akita ************ #include <stdio.h> #include <string.h> #include <ctype.h> int henkan(void); int main(void) { char str[100]; int j,len; for(j=0;j<6;j++){ gets(str); printf("==>"); } henkan(); return 0; } int henkan(void) { char str[100]; int i, chk,len; for(i=0;i<len;i++){ chk=isupper(str[i]); if(chk!=0)str[i]=tolower(str[i]); { printf("%c",str[i]); } } printf("\n"); return chk; }

  • c言語のファイル出力について

    現在C言語の課題に取り組んでおり、ファイルの中身通りに出力させたいのですが 「ファイルの中身」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 「出力結果」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 こういう形で改行されて出てきてしまいます。 どなたか修正点を教えて頂けないでしょうか? #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { int r,i,n; FILE* fp; char sin[9][1000]; fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } for (i = 0; i < 9; i++) { fscanf(fp, "%s", &(sin[i])); } fclose(fp); for (i = 0; i < 9; i++) { printf("%s\n", sin[i]); } return 0; }

  • ファイル出力について

    ファイルの出力について質問させてください。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #define NUM 50 /*構造体宣言*/ struct Students{ int N; /*学籍番号*/ int A; /*科目Aの点数*/ int B; /*科目Bの点数*/ int C; /*科目Cの点数*/ int sum; /*3科目の合計*/ double ave; double dev; }; /*平均の関数*/ double Average(struct Students tmp) { return(double)(tmp.A+tmp.B+tmp.C)/3.0; } /*偏差値の関数*/ double Deviation(struct Students k,double l,double m) { return(double)(NUM+10*(k.ave-l)/m); } int main(void){ struct Students std[NUM]; /*構造型配列*/ int j=0,i,N,A,B,scannum; double csum=0,sdev=0,cave; /*csum:クラスの総合点、sdev:標準偏差値、cave:クラスの一科目あたりの平均*/ FILE*file; /*ファイルのポインタを用意*/ srand((unsigned)time(NULL)); /*乱数の初期化*/ file=fopen("Data.txt","r"); /*Dataファイルのオープン*/ /*ファイルのオープンチェック*/ if(file==NULL){ fprintf(stderr,"cannnot open file 'Data.txt'\n"); exit(1); } /*Studentsにデータを格納*/ for(i=0;i<NUM;i++){ scannum=fscanf(file,"%d%d%d",&N,&A,&B); /*ファイルが読み込めたかチェック if(scannum!=1){ fprintf(stderr,"cannnot read file 'Data.txt'\n"); exit(1); } */ std[i].N=N; std[i].A=A; std[i].B=B; std[i].C=70+(int)(rand()/(RAND_MAX+1.0)*31); std[i].sum=std[i].A+std[i].B+std[i].C; std[i].ave=Average(std[i]); csum=csum+std[i].sum; }fclose(file); /*標準偏差計算*/ cave=csum/150.0; for(i=0;i<NUM;i++){ sdev=sdev+(std[i].sum-cave)*(std[i].sum-cave); } sdev=sqrt(sdev/NUM); /*偏差値の計算,最高偏差値の出力*/ for(i=0;i<NUM;i++){ std[i].dev=Deviation(std[i],cave,sdev); if(std[i].dev > std[j].dev){ std[j]=std[i]; } printf("学籍番号:%d.\n",std[i].N); printf("科目A:%d.\n",std[i].A); printf("科目B:%d.\n",std[i].B); printf("科目C:%d.\n",std[i].C); printf("平均点:%lf.\n",std[i].ave); printf("偏差値は:%lf.\n",std[i].dev); } /*results.txtに書き込み if((file=fopen("results.txt","w"))==NULL){ printf("cannnot open\n"); return 1; } fprintf(file,"%d,%d,%d,%d,%lf,%lf",std[j].N,std[j].A,std[j].B,std[j].C,std[j].ave,std[j].dev); fclose(file); */ return 0; } このプログラムを実行させてみるとdata.txtの一番最初の学生番号のみ 表示されません。そのためファイルの読み込みのエラー確認を入れると ストップしてしまう状態です。学生番号は101~150なんですが実行結果 が102~150で表示されます。学生番号は変数Nに対応してるのでそこを 考えてみたのですがどこが悪いのか 発見できません。アドバイスを お願いします。

  • 平均値を関数を用いて出力したいのですが。。

    平均値を関数を用いて出力したいのですが一箇所でつまずいてしまい ました。ソースは #include <stdio.h> #include <stdlib.h> #include <time.h> /*構造体宣言*/ struct Students{ int N; int A; int B; int C; double ave; }; /*平均値を計算する関数*/ struct Students Average(struct Students std[i]){ std[i].ave=(double)(std[i].A+std[i].B+std[i].C)/3; return std[i]; } int main(void){ struct Students std[49]; /*構造型配列*/ int i,N,A,B,C,num,scannum; FILE*file; /*ファイルのポインタを用意*/ srand((unsigned)time(NULL)); /*乱数の初期化/ file=fopen("Data.txt","r"); /*Dataファイルの読み込み*/ /*ファイルのオープンチェック*/ if(file==NULL){ fprintf(stderr,"cannnot open file 'Data.txt'\n"); exit(1); } /*Studentsにデータを格納*/ for(i=0;i<=49;i++){ fscanf(file,"%d%d%d",&N,&A,&B); std[i].N=N; std[i].A=A; std[i].B=B; std[i].C=70+(rand()/(RAND_MAX+1.0)*31); std[i].ave=Average(std[i]); /*表示*/ printf("学籍番号:%d.",std[i].N); printf("科目A:%d.\n",std[i].A); printf("科目B:%d.\n",std[i].B); printf("科目C:%d.\n",std[i].C); printf("平均点:%d.\n",std[i].ave); fclose(file); return 0; } 目標はA,B,Cの平均を出したいのですが関数宣言の際にstd[i]を 用いると未定義扱いになってしまい実行が出来ない状態です。 自分としては↑のソースでi番目の配列の平均値を導出し、表示 させようとしてるのですが。。。。アドバイスをお願いします。 m(__)m

  • CSVファイルの内容を構造体に格納したい(Unix使用)。

    こんにちは。私は30代の男性です。 「名前」「身長」「体重」が記載されたCSVファイルの内容を読み取って、構造体の「name」「height」「weight」に格納するプログラムを作っています。CSVの内容は A,175,80 B,167,89 C,155,45 ・ ・ ・ Z,188,70 だと仮定します。数値が読み取れているか、下記のように「tp = strtok(file_image, ",\n" );」の前後に「printf("%s\n", file_image);」を置いてみたら、strtok前では全て表示されるのに、strtok後では「ABC」しか表示されません。これでは全てのデータを構造体に格納できないので、困っています。 1.どのようにすれば、数字も取り出せる(読み取れる)でしょうか? 2.効率よく構造体に格納するには、どのようにしたらよいでしょうか? アドバイスを頂ければ幸いです。宜しくお願いいたします。 #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> int main(int argc, char *argv[]) { FILE *fp = NULL; int rtn = 0; if ((fp = fopen(argv[1], "r")) == NULL) { printf("ファイルオープンに失敗しました。\n"); return 1; } if (argc != 2) { printf("ERROR: オプションの数に過不足があります。\n"); return 1; } rtn = change_csv(fp); return 0; } int change_csv(FILE *fp) { int i; int j; char file_image[256]; /* 読み込んだ先のメモリの領域 */ char *tp; for (i = 0; i <= 256; i++) { if (fgets(file_image, 256, fp) == NULL) { if (ferror(fp) != 0) { printf("ERROR: 読み込みに失敗しました。\n"); return 1; } } if (feof(fp) != 0) { break; } printf("%s\n", file_image); tp = strtok(file_image, ",\n" ); printf("%s\n", file_image); } fclose(fp); return 0; }

  • 【C言語】if文内の演算子の優先順位について

    【C言語】if文内の演算子の優先順位について こんにちわ。初めて質問を投稿させて頂きます。 宜しくお願い致します。 【環境】 OS:Windows XP(SP3) コンパイラ:Visual C++ 6.0 CPU:AMD Athlon X2 4200+ 【質問】 私は下記のプログラムを実行しました --------------------------------- 【プログラム】 #include <stdio.h> int main( void ) { int i = 1; int j = 2; printf( "i = %d\n",i ); printf( "j = %d\n",j ); if( (i = 0) && (j = 200) == 200 ){ printf( "\n(1)-----------------------------\n" ); printf( "i = %d\n",i ); printf( "j = %d\n",j ); } printf( "\n(2)-----------------------------\n" ); printf( "i = %d\n",i ); printf( "j = %d\n",j ); return 0; } 【出力結果】 i = 1 j = 2 (2)----------------------------- i = 0 j = 2 //(※) --------------------------------- 私は【出力結果】(2)のj = 2という出力結果(上記(※)の行)は j = 200にならないとおかしいと思っております。 なぜなら、私は【プログラム】内のif文「if( (i = 0) && (j = 200) == 200 )」 の判定手順が下記の様になると考えているからです。  (1)i = 0を実行  (2)j = 200を実行  (3)(i = 0)の判定実行   →判定の結果「0」なので&&の右側の判定「(j = 200) == 200」    を行うまでも無くif文全体の判定がFALSE。 しかし、実際は「j = 200」が実行されてないので、上記(2)と(3)の 判定手順が逆転している様に見えます。 C言語の優先順位を見ると「&&」や「==」よりも「()」の方が高いと 記憶してるので、(2)→(3)の順に実行されないとおかしいと思ってます。 しかし、私の予想した結果と実際の出力結果が異なるので私の演算子の優先順位 やif文内での判定手順の理解に間違いがあると考えています。 出来ましたらどの点が間違っているのかご教授願えませんでしょうか? 宜しくお願い申し上げます。

  • ポインタと出力について

    現在C言語を勉強している者ですが、参考書をもとに自分でソースコードを書いて少し疑問に思った所がありました。以下がそのソースコードです。 #include <stdio.h> int main(void) { int dt = 0x41424344; int *ip; char *cp; ip = &dt; cp = (char *)ip; printf("%x\n", *ip); printf("%x\n", *cp); printf("%x\n", *cp++); printf("%x\n", *cp++); printf("%x\n", *cp++); return 0; } 出力結果は 41424344 44 44 43 42 となります。 私の予想していた結果は 41424344 44 43 42 41 でしたが、結果はなぜか44が二回出力されています。 2番目のprintf("%x\n", *cp); と 3番目のprintf("%x\n", *cp++);は明らかに3番目のprintfが *cp++ で番地が1つ進んでいると思うのですが結果を見る限りでは同じ数字44が出力されています。なぜこうなってしまうのでしょうか? 説明不足でしたらまた追加しますのでどうかよろしくおねがいします。  

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • 0と1のファイルへの書き込み、出力

    c言語で0と1の乱数を生成し、ファイルに出力したいのですが、出力がおかしくなってしまいます。 正しく0と1をファイルに書き込み、出力するにはどうしたらいいでしょうか。 わかる方いらっしゃいましたら教えてください。 お願い致します。 #include<stdio.h> #include <stdlib.h> #include <time.h> #define max 3000000 #define nrand(n) (int)((double)n*rand()/RAND_MAX) /* 0以上n未満の整数を返す */ int main() {   FILE *Wf;   char W_filename[20];   int *W=(int *)malloc(sizeof(int) * max);   printf("入力ファイル名 : "); scanf("%s",W_filename);   if( ( Wf=fopen(W_filename,"w") ) == NULL ) printf("ファイルを開けません\n");   else   {     for(i=0;i<max;i++)     {     W[i]=nrand(2);     fprintf(Wf,"%d ",W[i]);    }   }   fclose(Wf);   free(W); } 出力が ‰‱‱‰‱‱‰‱‱‰‰‰‰‱‰‱‰‱‰‰ のようになってしまいます。 Wにはちゃんと0か1が入っているみたいなのですが・・・