Opencvベースのウェーブレット変換
11078 ワード
申明、本文は筆者のオリジナルではなく、原文は転載した.http://www.cnblogs.com/zhangzhi/archive/2009/09/19/1569888.html
関数DWT()とIDWT()が提供され、前者は任意の階層のウェーブレット変換を完了し、後者は任意の階層のウェーブレット逆変換を完了する.入力画像は単一チャネル浮動小数点画像でなければならず、画像サイズにも要求があり(1層変換:w,hは2の倍数でなければならない;2層変換:w,hは4の倍数でなければならない;3層変換:w,hは8の倍数でなければならない......)、変換後の結果は入力画像に直接保存される.1、関数パラメータが簡単で、画像ポインタpImageと変換層数nLayer.2、1つの関数は直接多層2次元ウェーブレット変換を完成し、できるだけ下付き演算を減らし、不要な関数呼び出しを避け、実行効率を高める.3、変換中、1つのポインタ配列pDataを使用して各行のデータの開始位置を保存し、pRowとpColumnを使用して1行と1列の一時データを保存し、パリティの分離やマージに使用し、メモリ消費量が少ない.
コード:すべて選択
上記のコードは、単一チャネルのみを変換することができ、画像のビット深度やサイズも要求されるため、あまり使いにくい.大丈夫です.この2つの関数について、任意のサイズのカラー画像に対して任意の階層のウェーブレット変換を行い、セグメントコードを与えることができます.
コード:すべて選択
関数DWT()とIDWT()が提供され、前者は任意の階層のウェーブレット変換を完了し、後者は任意の階層のウェーブレット逆変換を完了する.入力画像は単一チャネル浮動小数点画像でなければならず、画像サイズにも要求があり(1層変換:w,hは2の倍数でなければならない;2層変換:w,hは4の倍数でなければならない;3層変換:w,hは8の倍数でなければならない......)、変換後の結果は入力画像に直接保存される.1、関数パラメータが簡単で、画像ポインタpImageと変換層数nLayer.2、1つの関数は直接多層2次元ウェーブレット変換を完成し、できるだけ下付き演算を減らし、不要な関数呼び出しを避け、実行効率を高める.3、変換中、1つのポインタ配列pDataを使用して各行のデータの開始位置を保存し、pRowとpColumnを使用して1行と1列の一時データを保存し、パリティの分離やマージに使用し、メモリ消費量が少ない.
コード:すべて選択
// ( )
void DWT(IplImage *pImage, int nLayer)
{
//
if (pImage)
{
if (pImage->nChannels == 1 &&
pImage->depth == IPL_DEPTH_32F &&
((pImage->width >> nLayer) << nLayer) == pImage->width &&
((pImage->height >> nLayer) << nLayer) == pImage->height)
{
int i, x, y, n;
float fValue = 0;
float fRadius = sqrt(2.0f);
int nWidth = pImage->width;
int nHeight = pImage->height;
int nHalfW = nWidth / 2;
int nHalfH = nHeight / 2;
float **pData = new float*[pImage->height];
float *pRow = new float[pImage->width];
float *pColumn = new float[pImage->height];
for (i = 0; i < pImage->height; i++)
{
pData[i] = (float*) (pImage->imageData + pImage->widthStep * i);
}
//
for (n = 0; n < nLayer; n++, nWidth /= 2, nHeight /= 2, nHalfW /= 2, nHalfH /= 2)
{
//
for (y = 0; y < nHeight; y++)
{
//
memcpy(pRow, pData[y], sizeof(float) * nWidth);
for (i = 0; i < nHalfW; i++)
{
x = i * 2;
pData[y][i] = pRow[x];
pData[y][nHalfW + i] = pRow[x + 1];
}
//
for (i = 0; i < nHalfW - 1; i++)
{
fValue = (pData[y][i] + pData[y][i + 1]) / 2;
pData[y][nHalfW + i] -= fValue;
}
fValue = (pData[y][nHalfW - 1] + pData[y][nHalfW - 2]) / 2;
pData[y][nWidth - 1] -= fValue;
fValue = (pData[y][nHalfW] + pData[y][nHalfW + 1]) / 4;
pData[y][0] += fValue;
for (i = 1; i < nHalfW; i++)
{
fValue = (pData[y][nHalfW + i] + pData[y][nHalfW + i - 1]) / 4;
pData[y][i] += fValue;
}
//
for (i = 0; i < nHalfW; i++)
{
pData[y][i] *= fRadius;
pData[y][nHalfW + i] /= fRadius;
}
}
//
for (x = 0; x < nWidth; x++)
{
//
for (i = 0; i < nHalfH; i++)
{
y = i * 2;
pColumn[i] = pData[y][x];
pColumn[nHalfH + i] = pData[y + 1][x];
}
for (i = 0; i < nHeight; i++)
{
pData[i][x] = pColumn[i];
}
//
for (i = 0; i < nHalfH - 1; i++)
{
fValue = (pData[i][x] + pData[i + 1][x]) / 2;
pData[nHalfH + i][x] -= fValue;
}
fValue = (pData[nHalfH - 1][x] + pData[nHalfH - 2][x]) / 2;
pData[nHeight - 1][x] -= fValue;
fValue = (pData[nHalfH][x] + pData[nHalfH + 1][x]) / 4;
pData[0][x] += fValue;
for (i = 1; i < nHalfH; i++)
{
fValue = (pData[nHalfH + i][x] + pData[nHalfH + i - 1][x]) / 4;
pData[i][x] += fValue;
}
//
for (i = 0; i < nHalfH; i++)
{
pData[i][x] *= fRadius;
pData[nHalfH + i][x] /= fRadius;
}
}
}
delete[] pData;
delete[] pRow;
delete[] pColumn;
}
}
}
// ( )
void IDWT(IplImage *pImage, int nLayer)
{
//
if (pImage)
{
if (pImage->nChannels == 1 &&
pImage->depth == IPL_DEPTH_32F &&
((pImage->width >> nLayer) << nLayer) == pImage->width &&
((pImage->height >> nLayer) << nLayer) == pImage->height)
{
int i, x, y, n;
float fValue = 0;
float fRadius = sqrt(2.0f);
int nWidth = pImage->width >> (nLayer - 1);
int nHeight = pImage->height >> (nLayer - 1);
int nHalfW = nWidth / 2;
int nHalfH = nHeight / 2;
float **pData = new float*[pImage->height];
float *pRow = new float[pImage->width];
float *pColumn = new float[pImage->height];
for (i = 0; i < pImage->height; i++)
{
pData[i] = (float*) (pImage->imageData + pImage->widthStep * i);
}
//
for (n = 0; n < nLayer; n++, nWidth *= 2, nHeight *= 2, nHalfW *= 2, nHalfH *= 2)
{
//
for (x = 0; x < nWidth; x++)
{
//
for (i = 0; i < nHalfH; i++)
{
pData[i][x] /= fRadius;
pData[nHalfH + i][x] *= fRadius;
}
//
fValue = (pData[nHalfH][x] + pData[nHalfH + 1][x]) / 4;
pData[0][x] -= fValue;
for (i = 1; i < nHalfH; i++)
{
fValue = (pData[nHalfH + i][x] + pData[nHalfH + i - 1][x]) / 4;
pData[i][x] -= fValue;
}
for (i = 0; i < nHalfH - 1; i++)
{
fValue = (pData[i][x] + pData[i + 1][x]) / 2;
pData[nHalfH + i][x] += fValue;
}
fValue = (pData[nHalfH - 1][x] + pData[nHalfH - 2][x]) / 2;
pData[nHeight - 1][x] += fValue;
//
for (i = 0; i < nHalfH; i++)
{
y = i * 2;
pColumn[y] = pData[i][x];
pColumn[y + 1] = pData[nHalfH + i][x];
}
for (i = 0; i < nHeight; i++)
{
pData[i][x] = pColumn[i];
}
}
//
for (y = 0; y < nHeight; y++)
{
//
for (i = 0; i < nHalfW; i++)
{
pData[y][i] /= fRadius;
pData[y][nHalfW + i] *= fRadius;
}
//
fValue = (pData[y][nHalfW] + pData[y][nHalfW + 1]) / 4;
pData[y][0] -= fValue;
for (i = 1; i < nHalfW; i++)
{
fValue = (pData[y][nHalfW + i] + pData[y][nHalfW + i - 1]) / 4;
pData[y][i] -= fValue;
}
for (i = 0; i < nHalfW - 1; i++)
{
fValue = (pData[y][i] + pData[y][i + 1]) / 2;
pData[y][nHalfW + i] += fValue;
}
fValue = (pData[y][nHalfW - 1] + pData[y][nHalfW - 2]) / 2;
pData[y][nWidth - 1] += fValue;
//
for (i = 0; i < nHalfW; i++)
{
x = i * 2;
pRow[x] = pData[y][i];
pRow[x + 1] = pData[y][nHalfW + i];
}
memcpy(pData[y], pRow, sizeof(float) * nWidth);
}
}
delete[] pData;
delete[] pRow;
delete[] pColumn;
}
}
}
上記のコードは、単一チャネルのみを変換することができ、画像のビット深度やサイズも要求されるため、あまり使いにくい.大丈夫です.この2つの関数について、任意のサイズのカラー画像に対して任意の階層のウェーブレット変換を行い、セグメントコードを与えることができます.
コード:すべて選択
//
int nLayer = 2;
//
IplImage *pSrc = cvLoadImage("Lena.jpg", CV_LOAD_IMAGE_COLOR);
//
CvSize size = cvGetSize(pSrc);
if ((pSrc->width >> nLayer) << nLayer != pSrc->width)
{
size.width = ((pSrc->width >> nLayer) + 1) << nLayer;
}
if ((pSrc->height >> nLayer) << nLayer != pSrc->height)
{
size.height = ((pSrc->height >> nLayer) + 1) << nLayer;
}
//
IplImage *pWavelet = cvCreateImage(size, IPL_DEPTH_32F, pSrc->nChannels);
if (pWavelet)
{
//
cvSetImageROI(pWavelet, cvRect(0, 0, pSrc->width, pSrc->height));
cvConvertScale(pSrc, pWavelet, 1, -128);
cvResetImageROI(pWavelet);
//
IplImage *pImage = cvCreateImage(cvGetSize(pWavelet), IPL_DEPTH_32F, 1);
if (pImage)
{
for (int i = 1; i <= pWavelet->nChannels; i++)
{
cvSetImageCOI(pWavelet, i);
cvCopy(pWavelet, pImage, NULL);
//
DWT(pImage, nLayer);
//
// IDWT(pImage, nLayer);
cvCopy(pImage, pWavelet, NULL);
}
cvSetImageCOI(pWavelet, 0);
cvReleaseImage(&pImage);
}
//
cvSetImageROI(pWavelet, cvRect(0, 0, pSrc->width, pSrc->height));
cvConvertScale(pWavelet, pSrc, 1, 128);
cvResetImageROI(pWavelet); // ,
cvReleaseImage(&pWavelet);
}
// pSrc
// ...
cvReleaseImage(&pSrc);