ページ 11

続・opencvによるアルファブレンドについて

Posted: 2013年4月16日(火) 15:37
by 禊太郎
先日ここで阿呆な質問をした禊太郎です。
なぜかopencvでアルファブレンドをしようとした時に奇妙な挙動になったので質問させて頂きます。
今まではiplImageのImageDataにある各画素に、アルファブレンド後の数値を直接char型にキャストして代入していたのですが、これでは整数レベルでしか変動させられないため、一旦double型の変数に格納して変数に手を加えた後にImageDataに格納しようと考えました。
しかし、その結果できたアルファブレンド画像は酷いノイズが入っており、とても望んでいたブレンド画像では有りませんでした。
恐らく格納する間に何かあることは検討がつくのですがそれが何なのかは全くわかりません。
どうか検証をお願いします。

コード:

  
#define BLUE 0
#define GREEN 1
#define RED 2

IplImage *IplAlphaBlend(IplImage *ImageA,IplImage *ImageB,int framecount)//doubleに格納
{
	IplImage *BlendImage = cvCloneImage(ImageA);
	double alpha=0;
	double colorstk[3]={0};
	#pragma omp parallel for
	for(int y = 0 ; y < ImageA->height ; y++)
	{
		for(int x = 0 ; x < ImageA->width ; x++)
		{	
			alpha = ((double)ImageRGBMax(ImageA,x,y))/255;//座標(x,y)において一番明るい色の数値をunsigned charで返し、255で割ることで0<=alpha<=1となるalphaを取得する。
			//alpha = 0.1;
			if(alpha>1)alpha=1;
			else if(alpha<0.05)alpha=0.0001;
			/*ここから
			BlendImage->imageData[y*BlendImage->widthStep + x*3+BLUE] = (char)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+BLUE]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+BLUE]));
			BlendImage->imageData[y*BlendImage->widthStep + x*3+GREEN] = (char)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+GREEN]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+GREEN]));
			BlendImage->imageData[y*BlendImage->widthStep + x*3+RED] = (char)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+RED]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+RED]));
			ここまでがアルファブレンド画像の画素値を直接代入する。現在はコメントアウト中*/
			//ここから
			colorstk[BLUE] = (double)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+BLUE]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+BLUE]));
			colorstk[GREEN] = (double)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+GREEN]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+GREEN]));
			colorstk[RED] = (double)(alpha * (unsigned char)(ImageA->imageData[y*ImageA->widthStep + x*3+RED]) + (1.0-alpha) * (unsigned char)(ImageB->imageData[y*ImageB->widthStep + x*3+RED]));
			BlendImage->imageData[y*BlendImage->widthStep + x*3+BLUE] = (char)(colorstk[BLUE]);
			BlendImage->imageData[y*BlendImage->widthStep + x*3+GREEN] = (char)(colorstk[GREEN]);
			BlendImage->imageData[y*BlendImage->widthStep + x*3+RED] = (char)(colorstk[RED]);
			//ここまでがdoubleに代入後charにキャストする
		}
	}

	return BlendImage;
}

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月16日(火) 17:46
by h2so5
doubleをcharにキャストしてしまっているのが問題です。
colorstkの取り得る数値は0.0〜255.0の間ですが、charでは-128〜127ですから情報が欠落します。

あとコードが冗長で読みにくく感じます。
画素値へのアドレスをポインタに代入しておけば簡潔になるでしょう。

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月17日(水) 14:54
by 禊太郎
>doubleをcharにキャストしてしまっているのが問題です。
>colorstkの取り得る数値は0.0〜255.0の間ですが、charでは-128〜127ですから情報が欠落します。

なるほど、そういうことだったのですか。教えてくれてありがとうございます。
冗長なのは……いずれ直しますがとりあえずこのままにします。

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月18日(木) 11:32
by usao
OpenCVならcvAddWeighted()という関数がありますが,それではダメなのでしょうか

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月18日(木) 12:58
by 禊太郎
usao さんが書きました:OpenCVならcvAddWeighted()という関数がありますが,それではダメなのでしょうか
自分がその関数を見た限り、全画素を一定のアルファ値でブレンディングするときには使えるけれど、各画素ごとにアルファ値を設定してのブレンドには向かないと判断しました。
もしcvAddWeighted()関数で各画素ごとにアルファ値を設定しアルファブレンドする方法があるなら教えていただければ幸いです。

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月18日(木) 14:03
by usao
alpha固定なのだと勘違いしていました 大変失礼しました.


ところで,各画素の計算は double ではなく整数計算で

コード:

const unsigned char Alpha = ImageRGBMax(ImageA,x,y);
const unsigned char Beta = unsigned char(255) - Alpha;
unsigned char BlendedResult = (unsigned char)(   ( unsigned int(ImgAの画素値)*Alpha + unsigned int(ImgBの画素値)*Beta ) >> 8   );
でどうでしょうか.

Re: 続・opencvによるアルファブレンドについて

Posted: 2013年4月18日(木) 16:16
by 禊太郎
整数計算をやってみましたが、今までと大差なかったので使用するかどうかは保留にします。
手法について考えてくださりありがとうございます。