線形補完での画像処理

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
MEA
記事: 12
登録日時: 3年前

線形補完での画像処理

#1

投稿記事 by MEA » 3年前

線形補完の式を使って画像処理をしているのですが、Segmentation fault: 11が出て原因が全くわからないので原因になっているところを教えていただきたいです。(真ん中の方に線形補完の関数があります。)

コード:

#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);
/* 丸め込み関数*/
float f_round(float val);
/* 画像変数のメモリを開放する関数*/
void freeImage(ColorImage *ci);

// プログラムを自作する関数
/* 出力画像の変数を生成する関数*/
void createImage(ColorImage *ci);

/* 拡大1(アップサンプリング) */
void scale_up_US(ColorImage *outimage, const ColorImage *inimage ,int M ,int N);
/* 拡大2(最近傍法) */
void scale_up_NN(ColorImage *outimage, const ColorImage *inimage);
/* 拡大3(線形補間) */
void scale_up_IP(ColorImage *outimage, const ColorImage *inimage);
/* 縮小1(ダウンサンプリング) */
void scale_down_DS(ColorImage *outimage, const ColorImage *inimage);
/* 縮小2(平均値) */
void scale_down_Mean(ColorImage *outimage, const ColorImage *inimage);
/* トリミング */
void trimming(ColorImage *outimage, const ColorImage *inimage, int ypos, int xpos);

int main(void)
{
	// 変数宣言
	char *outputfile={"output_senkeihokan.ppm"};
	char *inputfile={"zoneplate256.ppm"};
	ColorImage inimage;
	ColorImage outimage;
	int pros=2; // 手法指定変数 0:拡大1, 1:拡大2, 2:拡大3, 3:縮小1, 4:縮小2, 5:トリミング
	float scaleH, scaleW; //倍率の指定
	int xpos, ypos; //トリミング用

	// ここから処理
	loadPPM(inputfile, &inimage);

	if(pros==0){ /* 拡大1(アップサンプリング) */
		scaleH=3; scaleW=3;
		outimage.width = scaleW*(inimage.width);
		outimage.height = scaleH*(inimage.height);
		createImage(&outimage);
		scale_up_US(&outimage, &inimage,scaleH, scaleW);
	}
	else if(pros==1){ /* 拡大2(最近傍法) */
		scaleH=2; scaleW=2;
		outimage.width = scaleW*(inimage.width);
		outimage.height = scaleH*(inimage.height);
		createImage(&outimage);
		scale_up_NN(&outimage, &inimage);
	}
	else if(pros==2){/* 拡大3(線形補間) */
		scaleH=2; scaleW=2;
		outimage.width = scaleW*(inimage.width);
		outimage.height = scaleH*(inimage.height);
		createImage(&outimage);
		scale_up_IP(&outimage, &inimage);
	}
	else if(pros==3){/* 縮小1(ダウンサンプリング) */
		scaleH=1.0/2; scaleW=1.0/2;
		outimage.width = scaleW*(inimage.width);
		outimage.height = scaleH*(inimage.height);
		createImage(&outimage);
		scale_down_DS(&outimage, &inimage);
	}
	else if(pros==4){/* 縮小2(平均値) */
		scaleH=1.0/2; scaleW=1.0/2;
		outimage.width = scaleW*(inimage.width);
		outimage.height = scaleH*(inimage.height);
		createImage(&outimage);
		scale_down_Mean(&outimage, &inimage);
	}
	else{/* トリミング */
		outimage.width = 64; outimage.height = 64;
		xpos = 32; ypos = 32;
		createImage(&outimage);
		trimming(&outimage, &inimage, ypos, xpos);
	}

	savePPM(outputfile, &outimage);
	freeImage(&inimage);
	freeImage(&outimage);
	return 0;
}

void createImage(ColorImage *ci)
{
	int i,j;


  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[i]==NULL||ci->b[i]==NULL) {
			printf("Error in malloc");
			exit(0);
		}
	}



	for(i=0;i<ci->height;i++){
		for(j=0;j<ci->width;j++){
			ci->r[i][j]=0;
			ci->g[i][j]=0;
			ci->b[i][j]=0;
		}
	}

}


/* 拡大1(アップサンプリング) */
void scale_up_US(ColorImage *outimage, const ColorImage *inimage, int M, int N)
{
  int i,j;
	for(i=0;i<outimage->height;i++){
    for(j=0;j<outimage->width;j++){
      if(fmod((float)i/M,1)==0 && fmod((float)j/N,1)==0){
      outimage->r[i][j]=inimage->r[i/M][j/N];
      outimage->g[i][j]=inimage->g[i/M][j/N];
      outimage->b[i][j]=inimage->b[i/M][j/N];
    }
    else{
      outimage->r[i][j]=0;
      outimage->g[i][j]=0;
      outimage->b[i][j]=0;
    }
    }
  }
}

/* 拡大2(最近傍法) */
void scale_up_NN(ColorImage *outimage, const ColorImage *inimage)
{
  int i,j;
	for(i=0;i<outimage->height;i++){
    for(j=0;j<outimage->width;j++){
      outimage->r[i][j]=round(inimage->r[i/2][j/2]);
      outimage->g[i][j]=round(inimage->g[i/2][j/2]);
      outimage->b[i][j]=round(inimage->b[i/2][j/2]);
    }
  }
}

/* 拡大3(線形補間) */
void scale_up_IP(ColorImage *outimage, const ColorImage *inimage)
{
	int i,j,I,J;
  float M=2,N=2,a,b;
  I=i/M;
  a=i/M-I;
  J=j/N;
  b=j/N-J;

  for(i=0;i<outimage->height;i++){
    for(j=0;j<outimage->width;j++){
      outimage->r[i][j]=(1-a)*(1-b)*inimage->r[I][J]
                        +a*(1-b)*inimage->r[I][J+1]
                        +(1-a)*b*inimage->r[I+1][J]
                        +a*b*inimage->r[I+1][J+1];
      outimage->g[i][j]=(1-a)*(1-b)*inimage->g[I][J]
                        +a*(1-b)*inimage->g[I][J+1]
                        +(1-a)*b*inimage->g[I+1][J]
                        +a*b*inimage->g[I+1][J+1];
      outimage->b[i][j]=(1-a)*(1-b)*inimage->b[I][J]
                        +a*(1-b)*inimage->b[I][J+1]
                        +(1-a)*b*inimage->b[I+1][J]
                        +a*b*inimage->b[I+1][J+1];
    }
  }
}

/* 縮小1(ダウンサンプリング) */
void scale_down_DS(ColorImage *outimage, const ColorImage *inimage)
{
  int i,j;
	for(i=0;i<outimage->height;i++){
    for(j=0;j<outimage->width;j++){
      outimage->r[i][j]=inimage->r[2*i][2*j];
      outimage->g[i][j]=inimage->g[2*i][2*j];
      outimage->b[i][j]=inimage->b[2*i][2*j];
    }
  }
}

/* 縮小2(平均値) */
void scale_down_Mean(ColorImage *outimage, const ColorImage *inimage)
{
	int i,j,k,l;
  int M=2,N=2; //縦M倍,横N倍に縮小
  for(i=0;i<outimage->height;i++){
    for(j=0;j<outimage->width;j++){
      for(k=0;k<M;k++){
        for(l=0;l<N;l++){
          outimage->r[i][j]+=(1/M/N)*inimage->r[M*i+k][N*j+l];
          outimage->g[i][j]+=(1/M/N)*inimage->g[M*i+k][N*j+l];
          outimage->b[i][j]+=(1/M/N)*inimage->b[M*i+k][N*j+l];
        }
      }
    }
  }
}

/* トリミング */
void trimming(ColorImage *outimage, const ColorImage *inimage, int ypos, int xpos)
{
	/* プログラムを書く.*/
}

/* ここから下は修正する必要はありません */
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);

	/* 画素値を書き出す */
	for(i=0;i<ci->height;i++){
		for(j=0;j<ci->width;j++){
            if(ci->r[i][j] > 255.0f) ci->r[i][j]=255.0f;
            if(ci->g[i][j] > 255.0f) ci->g[i][j]=255.0f;
            if(ci->b[i][j] > 255.0f) ci->b[i][j]=255.0f;
            if(ci->r[i][j] < 0.0f) ci->r[i][j]=0.0f;
            if(ci->g[i][j] < 0.0f) ci->g[i][j]=0.0f;
            if(ci->b[i][j] < 0.0f) ci->b[i][j]=0.0f;
		}
	}

	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[i]==NULL||ci->b[i]==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);
	}
}

void freeImage(ColorImage *ci)
{
	int i;

	for(i=0;i<ci->height;i++)
	{
		free(ci->r[i]);
		free(ci->g[i]);
		free(ci->b[i]);
	}
	free(ci->r);
	free(ci->g);
	free(ci->b);
}

float f_round(float val)
{
	float fval=0.0;
	fval = floor(val + 0.5);
	return fval;
}

参照魚
記事: 109
登録日時: 6年前

Re: 線形補完での画像処理

#2

投稿記事 by 参照魚 » 3年前

scale_up_IPでIやJが未初期化状態のi,jを使用して計算されています。for 文の中に入れて、ループの都度再計算する意図なのかなと思います。

MEA
記事: 12
登録日時: 3年前

Re: 線形補完での画像処理

#3

投稿記事 by MEA » 3年前

二重ループの中に初期化の文を入れたのですが、エラーは出なかったのですが、画像が真っ黒になりました。

参照魚
記事: 109
登録日時: 6年前

Re: 線形補完での画像処理

#4

投稿記事 by 参照魚 » 3年前

私自身は線形補完や画像処理に詳しくないので、
処理の計算式そのものについては、何も申し上げられないのですが、
気になるところとしては下記の計算式で、aとbは常に0になるのではないでしょうか?

コード:

  I=i/M;
  a=i/M-I;
  
  J=j/N;
  b=j/N-J;
  

アバター
usao
記事: 1887
登録日時: 11年前

Re: 線形補完での画像処理

#5

投稿記事 by usao » 3年前

> aとbは常に0になるのではないでしょうか?

I,J,a,b は全て(未初期化のi,jから算出しているのだから)不定値になるのでは.

返信

“C言語何でも質問掲示板” へ戻る