アプリ版:「スタンプのみでお礼する」機能のリリースについて

初歩的な質問なんですが、この下のプログラムは画像全体にモザイクをかけているものですが、画像上の範囲を指定して、その範囲内の領域だけモザイクをかけるにはどうしたらいいでしょうか?
void make_cmosaic_image()
{
int i,j,x,y,k;
int bsz; /*ブロックサイズ*/
int bx,by;
int bvaIR,bvaIG,bvaIB; /*ブロックの平均値*/
int pels;
int X,Y; /*ピクセルの位置*/

printf("カラー画像のモザイク化\n");

pXdim2=pXdim1;
pYdim2=pYdim1;

printf("ブロックサイズを入力してください(1より大きい値):");
scanf("%d",&bsz);
printf("ブロックサイズは%dである。",bsz);

if(pXdim1 % bsz ==0)
bx= pXdim1 / bsz;
else
bx=pXdim1 / bsz+1;

if(pYdim1 % bsz ==0)
by=pYdim1/bsz;
else
by=pYdim1/bsz+1;
/*モザイク化する*/
for(j=0;j<by;j++)
for(i=0;i<bx;i++){ /*ブロックごと に 計算する*/
/*各ブロックのピクセル平均値を計算する*/
bvaIR = bvaIG =bvaIB=0;
pels=0;
/*各ブロックのピクセル値の和を計算する*/
for(y=0;y<bsz;y++)
for(x=0;x<bsz;x++){
/*現在のピクセルの位置を計算する*/
X=i*bsz+x;
Y=j*bsz+y;
/*この位置が有効であれば、和を計算する*/
if(X>=0 && X<pXdim1 && Y>=0 && Y<pYdim1){
pels++;
/*和を計算する*/
bvaIR +=pimage1[0][Y][X];
bvaIG +=pimage1[1][Y][X];
bvaIB +=pimage1[2][Y][X];
}
}
bvaIR /=pels;
bvaIG /=pels;
bvaIB /=pels;
/*計算した平均値を目的画像へ代入する*/
for(y=0;y<bsz;y++)
for(x=0;x<bsz;x++){
X=i*bsz+x;
Y=j*bsz+y;
if(X>=0 && X<pXdim1 && Y>=0 && Y<pYdim1){
else
pimage2[0][Y][X]=bvaIR;
pimage2[1][Y][X]=bvaIG;
pimage2[2][Y][X]=bvaIB;
}  }  }  }

A 回答 (3件)

追記。



追加するif文の位置と、条件成立時の文の範囲、不成立時の文の範囲を工夫すれば「今から処理するモザイク1ブロック分が指定範囲外なら、ピクセルの平均や和を演算しなくて済むので演算させないで、元画像を目的画像に単にコピーするだけ」と言う最適化が行えます。

しかし「今から処理するモザイク1ブロック分が指定範囲外かどうかの判定」が複雑になるので、あまりお勧め出来ません。

今から処理するモザイク1ブロック分が、指定範囲と一部分だけ重なってたりした場合など、領域の重なりの判定が複雑になり、下手をすると「判定する処理の方が増えてしまい、逆に遅くなってしまう」と言う事が起きてしまいます。
    • good
    • 0
この回答へのお礼

ありがとうございました。
なんとか上手くできました

お礼日時:2009/06/02 21:22

pimage2[0][Y][X]=bvaIR;


pimage2[1][Y][X]=bvaIG;
pimage2[2][Y][X]=bvaIB;



if ((X >= 矩形範囲のX軸の小さいほう) && (X <= 矩形範囲のX軸の大きいほう) && (Y >= 矩形範囲のY軸の小さいほう) && (Y <= 矩形範囲のY軸の大きいほう)) {
 pimage2[0][Y][X]=bvaIR;
 pimage2[1][Y][X]=bvaIG;
 pimage2[2][Y][X]=bvaIB;
} else {
 pimage2[0][Y][X]=pimage1[0][Y][X];
 pimage2[1][Y][X]=pimage1[1][Y][X];
 pimage2[2][Y][X]=pimage1[2][Y][X];
}

にすればよい。例えば(100,150)-(199-249)の矩形の範囲だけにしたいなら

if ((X >= 100) && (X <= 199) && (Y >= 150) && (Y <= 249)) {
 pimage2[0][Y][X]=bvaIR;
 pimage2[1][Y][X]=bvaIG;
 pimage2[2][Y][X]=bvaIB;
} else {
 pimage2[0][Y][X]=pimage1[0][Y][X];
 pimage2[1][Y][X]=pimage1[1][Y][X];
 pimage2[2][Y][X]=pimage1[2][Y][X];
}

にする。

こうすると、モザイクの演算処理は「画像全体に行う」けども「指定範囲外は元画像をそのまま代入し、指定範囲内は画像平均値を代入してモザイクを掛ける」ので、目的通りになる。

なお、元のプログラムは「元画像pimage1から、目的画像pimage2を作る」と言う処理をしているので「必ず、処理は画像全体に対して行う必要がある」ので注意すること。

もし「上記以外の変更を行う」と、つまり「ループの開始値や終了値を変えてしまう」と、目的画像pimage2全体への処理が部分的に欠落し、目的画像pimageが正しく生成されない。

なので「forループの初期値や終了値、関数の冒頭の初期化処理は絶対に変更しない」ように注意する事。

つ~か「この回答で示した部分以外は絶対に変更しない事」です。

ANo.1の回答のような事をすると「目的画像pimage2の範囲外の部分の画素情報が不定になる」ので絶対にダメ。
    • good
    • 0

たぶん、二箇所ある


if(X>=0 && X<pXdim1 && Y>=0 && Y<pYdim1)
の0を開始位置 pXdim1とpYdim1を終了位置の変数に置き換えれば出来ると思います。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!