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

どなたか以下のヒストグラム均等化処理プログラムを解説して頂けないでしょうか。特にgetMinMax関数とgetHistEqu関数で、何がしたいのか訳がわかりません。
以下のプログラムは、ヒストグラム均等化処理部分のみですが、分かる範囲でいいので、解説お願いします。
-------------------------------------------------------
// ヒストグラム均等化による画素値の割り当てを決定する
// hist:入力画像のヒストグラム
// min:割り当てられる画素値の最小
// max:割り当てられる画素値の最大
// たとえば,min[5]=4 max[5]=6の場合,画素値5には4-6の範囲に割り当てられる
// pixs_min:最小値が割り当てられる画素数
// pixs_max:最大値が割り当てられる画素数
// ave:各画素値に割り当てられる画素数
//★★特にmin,max,pixs_min,pixs_maxの説明の意味が分からないのです。
int getMinMax(int *hist,int *min,int *max,int *pixs_min,int *pixs_max,int ave)
{
int i;
int rest;
int now;
int pixels;
int a,b;

rest=0;
now=0;
for(i=0;i<256;i++) {
pixels=rest+hist[i];
min[i]=now;
if(rest>0) pixs_min[i]=ave-rest;
else pixs_min[i]=ave+100;
a=pixels/ave;
rest=pixels%ave;
max[i]=now+a;
if(rest>0) pixs_max[i]=rest;
else pixs_max[i]=ave+100;
now+=a;
}
for(i=0;i<255;i++) {
if(min[i]>255) min[i]=255;
if(max[i]>255) max[i]=255;
}
max[255]=255;
pixs_max[255]=ave*10;
}

// ヒストグラム均等化による画素値の決定
// 割り当てられる画素値の最小,最大の間で順番に割り当てていく
// ただし,最小,最大については割り当てる画素数に制限がある
int getHistEqu(int x,int *now,int *min,int *max,int *pix_min,int *pix_max)
{
int res;

if(now[x]==max[x]) {
if(pix_max[x]<=0) now[x]=min[x];
else pix_max[x]--;
}
if(now[x]==min[x]) {
if(pix_min[x]<=0) now[x]=min[x]+1;
else pix_min[x]--;
}
if(now[x]>max[x]) now[x]=min[x];
res=now[x];
now[x]++;
return res;
}

int effect(ImageData *img,ImageData *outimg)
{
int x,y;
int rr,gg,bb;
int ro,go,bo;
int i;
int val;
int ave;
int histR[256],histG[256],histB[256];// ヒストグラム
int omaxR[256],omaxG[256],omaxB[256];// 変換後,割り当てられる画素値の最小
int ominR[256],ominG[256],ominB[256];// 変換後,割り当てられる画素値の最大
int pix_maxR[256],pix_maxG[256],pix_maxB[256];// 最小値が割り当てられる画素数
int pix_minR[256],pix_minG[256],pix_minB[256];// 最大値が割り当てられる画素数
int onowR[256],onowG[256],onowB[256];// 次に割り当てる画素値
Pixel pix;

for(i=0;i<256;i++) {
histR[i]=histG[i]=histB[i]=0;
}
ave= img->height * img->width /256; // 画像の全画素数/画素値の範囲
// ヒストグラム作成
for(y=0;y<img->height;y++) {
for(x=0;x<img->width;x++) {
getPixel(img,x,y,&pix);//画像上の画素情報を取得
rr=pix.r;
gg=pix.g;
bb=pix.b;
histR[rr]++;
histG[gg]++;
histB[bb]++;
}
}
// 画素値の割り当て決定
getMinMax(histR,ominR,omaxR,pix_minR,pix_maxR,ave);
getMinMax(histG,ominG,omaxG,pix_minG,pix_maxG,ave);
getMinMax(histB,ominB,omaxB,pix_minB,pix_maxB,ave);
for(i=0;i<256;i++) {
onowR[i]=ominR[i];
onowG[i]=ominG[i];
onowB[i]=ominB[i];
}
// ヒストグラム均等化処理
for(y=0;y<img->height;y++) {
for(x=0;x<img->width;x++) {
getPixel(img,x,y,&pix);//画像上の画素情報を取得
ro=pix.r;
go=pix.g;
bo=pix.b;
rr=getHistEqu(ro,onowR,ominR,omaxR,pix_minR,pix_maxR);
gg=getHistEqu(go,onowG,ominG,omaxG,pix_minG,pix_maxG);
bb=getHistEqu(bo,onowB,ominB,omaxB,pix_minB,pix_maxB);
pix.r=rr;
pix.g=gg;
pix.b=bb;
setPixel(outimg,x,y,&pix);// 画像に値をセットする
}
}
return 0;
}

A 回答 (1件)

例えば、解像度が256×256だったとすると、


ヒストグラム均等化処理後は、各輝度値を持つ画素数は全て256ピクセルになる、ということです。

ここで、入力の輝度値のヒストグラムが
0: 600ピクセル
1: 600ピクセル
2: 600ピクセル
(以下略)
だったとしましょう。

変換後の各輝度値は256ピクセルしかおけませんから、
入力の輝度値0の600ピクセル中、256ピクセルは出力輝度値0、256ピクセルは出力輝度値1、88ピクセルは出力輝度値2になります。

入力の輝度値1に付いては、168ピクセル(入力輝度値0が使った残り)が出力輝度値2、256ピクセルが出力3、176ピクセルが出力4になります。

入力の輝度値2に付いては、80ピクセルが出力輝度値4、256ピクセルが出力5、256ピクセルが出力6、8ピクセルが出力7になります。

と、こういう割当ピクセル数を計算するのが getMinMax ですね。

この場合、
min[0]=0, max[0]=2, pix_min[0]=256, pix_max[0]=88
min[1]=2, max[1]=4, pix_min[1]=168, pix_max[1]=176
min[2]=4, max[2]=7, pix_min[2]= 80, pix_max[2]= 8
という結果になります。

この計算結果を基に、入力輝度値から出力輝度値を算出するのが getHistEqu です。
可能なピクセル数の範囲で、min[x]~max[x]を順番に出力していきます。
例えば、、入力輝度値が2の場合、min[2]=4, max[2]=7ですから
入力輝度値2が出てくる度に、4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7, …
と、4~7を順番に出力していきます。
ただし、7を8回出力したところで、出力7のピクセル数は使い切ってますから、
以降は、4, 5, 6, 4, 5, 6, … となり、
4を80回出力した所で、出力4のピクセル数は使い切るので、
以降は 5, 6, 5, 6, …という出力になります。
    • good
    • 0

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