以下のコードでforeground.ppmを前景画像,background.ppmを背景画像として 前景画像の各画素値において赤の値がα以下, かつ緑の値がβ以上, かつ青の値がγ以下の時, その画素を背景画像の同じ場所の画素に置き換え, その結果を画像output.ppmに出力したいのですが、Segmentation fault: 11とエラーが出ました。chroma_key関数を書き終えてからエラーが出始めたのでそこが原因だとは思うのですが、原因がわからないので教えて欲しいです。
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <ctype.h> /* 画像の構造体 */ typedef struct{ int width; int height; float **r; float **g; float **b; }ColorImage; /* 1ワード読み込む関数 */ void getword(FILE *fp, char *word); /* PPMフォーマットの画像を読み込む関数 */ void loadPPM(char* filename, ColorImage *ci); /* 画像をPPMフォーマットで書き出す関数 */ void savePPM(char* filename, ColorImage *ci); /* ネガポジ変換 */ void nega_posi(ColorImage *cimage); /* コントラスト強調 */ void contrast(ColorImage *cimage); /* ガンマ補正 */ void gamma_ps(ColorImage *cimage); /* 量子化 */ void quantize(ColorImage *cimage); /* クロマキー */ void chroma_key(ColorImage *fg, ColorImage *bg); int main(void) { char *outputfile={"output.ppm"}; char *inputfile={"peppers.ppm"}; ColorImage cimage[2]; int pros=4; /*0:ネガポジ、1:コントラスト強調、2:ガンマ補正、 3:量子化、4:クロマキー*/ if(pros==0){ //ネガポジ loadPPM(inputfile, cimage); nega_posi(cimage); savePPM(outputfile, cimage); } else if(pros==1){ loadPPM(inputfile, cimage); contrast(cimage); savePPM(outputfile, cimage); } else if(pros==2){ loadPPM(inputfile, cimage); gamma_ps(cimage); savePPM(outputfile, cimage); } else if(pros==3){ loadPPM(inputfile, cimage); quantize(cimage); savePPM(outputfile, cimage); } //Chroma Key else { loadPPM("foreground.ppm", cimage); loadPPM("background.ppm", &cimage[1]); chroma_key(cimage, &cimage[1]); savePPM(outputfile, cimage); } return 0; } void nega_posi(ColorImage *cimage) { /*y(i, j) = 255 − x(i, j) に基づいてネガポジ変換する*/ int i,j; for(i=0;i<cimage->height;i++){ for(j=0;j<cimage->width;j++){ cimage->r[i][j]=255-cimage->r[i][j]; cimage->g[i][j]=255-cimage->g[i][j]; cimage->b[i][j]=255-cimage->b[i][j]; } } } void contrast(ColorImage *cimage) { int i,j; for(i=0;i<cimage->height;i++){ for(j=0;j<cimage->width;j++){ cimage->r[i][j]=1.5*cimage->r[i][j]-10; cimage->g[i][j]=1.5*cimage->g[i][j]-10; cimage->b[i][j]=1.5*cimage->b[i][j]-10; } } } void gamma_ps(ColorImage *cimage) { int i,j; for(i=0;i<cimage->height;i++){ for(j=0;j<cimage->width;j++){ cimage->r[i][j]=powf(cimage->r[i][j],1.4); cimage->g[i][j]=powf(cimage->g[i][j],1.4); cimage->b[i][j]=powf(cimage->b[i][j],1.4); } } } void quantize(ColorImage *cimage) { int i,j; for(i=0;i<cimage->height;i++){ for(j=0;j<cimage->width;j++){ /*この場合は7ビットにビットシフトを用いて量子化する*/ cimage->r[i][j]=((int)cimage->r[i][j]>>(8-1))<<(8-1); cimage->g[i][j]=((int)cimage->g[i][j]>>(8-1))<<(8-1); cimage->b[i][j]=((int)cimage->b[i][j]>>(8-1))<<(8-1); } } } // insert forground image into background. void chroma_key(ColorImage *fg, ColorImage *bg) { int i,j; int a,b,c; a=150; b=150; c=150; for(i=0;i<fg->height;i++){ for(j=0;j<fg->width;j++){ if(fg->r[i][j]<a && fg->g[i][j]>b && fg->g[i][j]<c) { fg->r[i][j]=bg->r[i][j]; fg->g[i][j]=bg->g[i][j]; fg->b[i][j]=bg->b[i][j]; } else { fg->r[i][j]=fg->r[i][j]; fg->g[i][j]=fg->g[i][j]; fg->b[i][j]=fg->b[i][j]; } } } } void savePPM(char* filename, ColorImage *ci) { /* save file in PGM P3 format */ int i, j; FILE *out; /* ファイルをオープン */ out=fopen(filename, "w"); /* ファイルが存在しなければエラー */ if (out==NULL){ printf("Cannot open file\n"); exit(0); } /* ファイルのヘッダ情報を書き出す */ fprintf(out, "P3\n%d %d\n255\n", ci->width, ci->height); /* 画素値を書き出す */ /* 画素値を0~255に制限するプログラム */ for(i=0;i<ci->height;i++){ for(j=0;j<ci->width;j++){ if(ci->r[i][j]<0){ ci->r[i][j]=0; } if(ci->r[i][j]>=255){ ci->r[i][j]=255; } if(ci->g[i][j]<0){ ci->g[i][j]=0; } if(ci->g[i][j]>=255){ ci->g[i][j]=255; } if(ci->b[i][j]<0){ ci->b[i][j]=0; } if(ci->b[i][j]>=255){ ci->b[i][j]=255; } } } for(i=0;i<ci->height;i++){ for(j=0;j<ci->width;j++){ fprintf(out, "%d ", (int)ci->r[i][j]); fprintf(out, "%d ", (int)ci->g[i][j]); fprintf(out, "%d ", (int)ci->b[i][j]); } } fclose(out); } void loadPPM(char* filename, ColorImage *ci) { char word[1000]; int i,j; FILE *in; in=fopen(filename, "rb"); if(in==NULL){ printf("Cannot open file\n"); exit(0); } getword(in, word); getword(in, word); sscanf(word,"%d",&(ci->width)); getword(in, word); sscanf(word,"%d",&(ci->height)); getword(in, word); ci->r=(float **)malloc(ci->height*sizeof(float *)); ci->g=(float **)malloc(ci->height*sizeof(float *)); ci->b=(float **)malloc(ci->height*sizeof(float *)); if(ci->r==NULL||ci->g==NULL||ci->b==NULL) { printf("Error in malloc"); exit(0); } for(i=0;i<ci->height;i++){ ci->r[i]=(float *)malloc(ci->width*sizeof(float)); ci->g[i]=(float *)malloc(ci->width*sizeof(float)); ci->b[i]=(float *)malloc(ci->width*sizeof(float)); if(ci->r[i]==NULL||ci->g==NULL||ci->b==NULL) { printf("Error in malloc"); exit(0); } } /*discard one CR*/ fgetc(in); for(i=0;i<ci->height;i++){ for(j=0;j<ci->width;j++){ int tmpr, tmpg, tmpb; fscanf(in, "%s", word); sscanf(word,"%d",&(tmpr)); fscanf(in, "%s", word); sscanf(word,"%d",&(tmpg)); fscanf(in, "%s", word); sscanf(word,"%d",&(tmpb)); ci->r[i][j]=(float)tmpr; ci->g[i][j]=(float)tmpg; ci->b[i][j]=(float)tmpb; } } fclose(in); } void getword(FILE *fp, char *word) { fscanf(fp, "%s", word); /* while(word[0]=='#'){ fscanf(fp, "%s", word); }*/ if(word[0]=='#'){ while(word[0]!=10){ word[0]=(int)fgetc(fp); } fscanf(fp, "%s", word); } } コード
chroma_key()関数をコメントアウトして、エラーが出なければ、可能性は高いですね。fg と bgのサイズが同じ前提となっていますが、それも問題ないでしょうか?
丁寧にみる気合がないので、ざっと気が付いたところで。
foreground.ppmとbackground.ppmの先頭部分(画像の情報)はそれぞれどうなっていますか。
一応どちらもサイズ、階調は同じです
書き換える苗のchroma_key関数とコード比較しては?
添え字の範囲とか変わってないですか?
66,67行目の画像を他のものにしたらコンパイル自体はとおりました、、、
こちら https://dixq.net/forum/viewtopic.php?f=3&t=21013&sid=8d6fc76696924b9002f94317e78a0b28 に回答しましたが、height と width が逆になっていませんか?
height と width を入れ替えたら、実行はできるが特に変化のない画像が出力されました。
回答1件
あなたの回答
tips
プレビュー