解説
周囲8ピクセルを含めた9ピクセルの各値をソートしてその中間の値を新しい値と する。ソートはR、G、B各色ごとに処理する。一般的にノイズ除去処理に用いられるフィルター。完全に"点"のノイズに対し ては有効に働くがそれ以外のノイズに対してはイマイチ。
実行例
以下のコードで処理を施した。_cImage2.Median();

ソースコード
GDI+を利用した画像処理テストのスケルトン2を 元に拡張する。前に作成した「DnpImage.h」に処理関数を追加する。
#include "math.h"
class CDnpImage : public CDnpImageBase
,public CDnpImageConvolution
,public CDnpColorSpaceHLS
,public CDnpColorSpaceHSV
{
public:
//
// メディアンフィルター
//
//周囲8ピクセルを含めた9ピクセルの各値をソートしてその中間の値を新しい値と
//する。ソートはR.G.B各色ごとに処理する。
//一般的にノイズ除去処理に用いられるフィルター。完全に"点"のノイズに対し
//ては有効に働くがそれ以外のノイズに対してはイマイチ。
//
bool Median(void)
{
if(IsValidImage() == false)
return false;
int nStrideBytes;
bool ret;
UINT x;
UINT y;
UINT nWidth;
UINT nHeight;
BYTE* pData;
BYTE* pDataOrg;
RGBTRIPLE* pRGB;
nWidth = GetWidth();
nHeight = GetHeight();
ret = LockBits(&pData,&nStrideBytes);
if(ret == false)
return false;
pDataOrg = pData;
//バブルソート用マクロ
#define BUBBLE_SORT(pcbData,nCount) \
{ \
int i; \
int j; \
int nTmp; \
\
for(i = 0; i < nCount - 1; i++) \
{ \
for(j = 0; j < nCount - 1; j++) \
{ \
if (pcbData[j + 1] > pcbData[j]) \
continue; \
nTmp = pcbData[j]; \
pcbData[j] = pcbData[j + 1]; \
pcbData[j + 1] = nTmp; \
} \
} \
}
///////////////////////////////////////
//メディアン処理
//
BYTE pnData[9];
RGBTRIPLE prgbData[9];
BYTE* pNew;
BYTE* pTmp;
RGBTRIPLE* prgbNew;
RGBTRIPLE* prgbDown;
RGBTRIPLE* prgbUp;
pNew = new BYTE[nStrideBytes * nHeight];
pData = pDataOrg;
pTmp = pNew;
for(y = 0; y < nHeight; y++)
{
prgbNew = (RGBTRIPLE*)pTmp;
pRGB = (RGBTRIPLE*)pData;
prgbUp = (RGBTRIPLE*)(pData - nStrideBytes);
prgbDown= (RGBTRIPLE*)(pData + nStrideBytes);
for(x = 0; x < nWidth; x++)
{
int nCount;
nCount = 0;
if(x >= 1)
prgbData[nCount++] = pRGB[x - 1];
prgbData[nCount++] = pRGB[x];
if(x < nWidth - 1)
prgbData[nCount++] = pRGB[x + 1];
if(y >= 1)
{
if(x >= 1)
prgbData[nCount++] = prgbUp[x - 1];
prgbData[nCount++] = prgbUp[x];
if(x < nWidth - 1)
prgbData[nCount++] = prgbUp[x + 1];
}
if(y < nHeight - 1)
{
if(x >= 1)
prgbData[nCount++] = prgbDown[x - 1];
prgbData[nCount++] = prgbDown[x];
if(x < nWidth - 1)
prgbData[nCount++] = prgbDown[x + 1];
}
int a;
int i;
#define MEDIAN(color) \
{ \
BUBBLE_SORT(pnData,nCount); \
\
if(nCount % 2) \
color = pnData[nCount / 2]; \
else \
{ \
a = nCount / 2 - 1; \
color = (pnData[a] + pnData[a + 1]) / 2; \
} \
}
//R
for(i = 0; i < nCount; i++)
pnData[i] = prgbData[i].rgbtRed;
MEDIAN(prgbNew[x].rgbtRed);
//G
for(i = 0; i < nCount; i++)
pnData[i] = prgbData[i].rgbtGreen;
MEDIAN(prgbNew[x].rgbtGreen);
//B
for(i = 0; i < nCount; i++)
pnData[i] = prgbData[i].rgbtBlue;
MEDIAN(prgbNew[x].rgbtBlue);
}
pData += nStrideBytes;
pTmp += nStrideBytes;
}
memcpy(pDataOrg,pNew,nStrideBytes * nHeight);
delete pNew;
UnlockBits();
return true;
}
。。。。省略。。。。
};
