【学习OpenCV】图像金字塔

图像金字塔

以多分辨率来解释图像的一种有效但概念简单的结构就是图像金字塔(Burt和Adelson[1983])。图像盒字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低的图像集合。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。当向金字塔的上层移动时,尺寸和分辨率就降低。
金字塔图示
因为基础级的尺寸是2^J * 2^J 或N * N (J = log2(N)),中间级j的尺寸是2^j * 2^j,其中j∈[0,J]
完整的金字塔由J+1个分辨率级构成,但大部分只有P+1级,其中P∈[1,J],即限制只使用P+1级来减少处理量。
右边是一个建立图像金字塔的简单系统。首先输入原始图像(J级),经过近似滤波器(一般为高斯模糊,起到平滑作用)然后2倍抽取(下采样),获得下一层图像(“j-1级近似”),不断重复该步骤P次直到第J-P级,总共获得P层子图像;对于每层子图像,如j-1层,做2倍内插(零插值),使其与上一层(j层)图像的尺寸一致,然后用插入滤波器(一般为高斯模糊,用于估计丢失像素的近似值)处理得到“预测”;最后把j级图像减去“j-1级预测”获得“j级预测残差”,这个残差信号蕴含着每一层(每个尺度下)图像的“本质”,本质的意思是与其它尺度无关的,独立的信息。
近似值和预测残差金字塔都是以一种迭代的方式进行计算的,可以归纳为下面3步:
1、计算“j-1级近似”。输入”j级近似”(如果j=J,就是原始图像),进行近似滤波和2倍抽样。滤波器可采用领域平均(平均值金字塔)、高斯低通(高斯金字塔),滤波的作用在于使抽样点更具有代表性,即模糊了抽样点附近的像素点;
2、计算“预测”。输入“j-1级近似”,进行2倍内插和插入滤波,插入滤波器与第1步的一致,滤波的作用在于消除内插造成的失真;
3、计算”j级预测残差“=“j级近似”-“预测”;
以上过程迭代P次,将产生P个”近似“和”预测残差“,每一次迭代得到的”近似“作为下一次的输入,所有的”预测残差“将用作金字塔的复原。

以上过程产生了两个金字塔:高斯金字塔(”近似“)和拉普拉斯金字塔(”预测残差“)。
两种金字塔
对于高斯金字塔,金字塔的分辨率越低,伴随的细节越少。通常金字塔的低分辨率图像用于分析大的结构或图像的整体内容,而高分辨率图像用于分析单个物体的特性。这样的由粗糙到精细的分析策略在模式识别中特别适用。
对于拉普拉斯金字塔,实现了每个尺度下的细节提取,可以用于图像增强和特征提取;同时由于排除了大量冗余信息,可以通过分配较少比特实现高比例压缩。

(注:以上内容及图出自《数字图像处理》冈萨雷斯,有删改)

OpenCV中的图像金字塔

opencv中只需要用到两个函数就可以实现图像金字塔
pyrDown和pyrUp

pyrDown
Blurs an image and downsamples it.
C++: void pyrDown( InputArray src, OutputArray dst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT )
Python: cv2. pyrDown( src[, dst[, dstsize[, borderType]]]) → dst
C: void cvPyrDown( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 )
Parameters
    src – input image.
    dst – output image; it has the specified size and the same type as src.
    dstsize – size of the output image.
    borderType – Pixel extrapolation method (BORDER_CONSTANT don’t supported). See
                borderInterpolate for details.
By default, size of the output image is computed as Size((src.cols+1)/2, (src.rows+1)/2) , but in any case, the
following conditions should be satisfied:
    |dstsize.width * 2 − src.cols | ≤ 2
    |dstsize.height * 2 − src.rows | ≤ 2
The function performs the downsampling step of the Gaussian pyramid construction. First, it convolves the source
image with the kernel:
1/256 = 
[⎡⎢⎣
    1  4  6  4 1
    4 16 24 16 4
    6 24 36 24 6
    4 16 24 16 4
    1  4  6  4 1
]⎥⎦
Then, it downsamples the image by rejecting even rows and columns.
pyrUp
Upsamples an image and then blurs it.
C++: void pyrUp( InputArray src, OutputArray dst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT )
Python: cv2. pyrUp( src[, dst[, dstsize[, borderType]]]) → dst
C: cvPyrUp( const CvArr* src, CvArr* dst, int filter=CV_GAUSSIAN_5x5 )
Parameters
    src – input image.
    dst – output image. It has the specified size and the same type as src .
    dstsize – size of the output image.
    borderType – Pixel extrapolation method (only BORDER_DEFAULT supported). See
                borderInterpolate for details.
By default, size of the output image is computed as Size(src.cols*2, (src.rows*2) , but in any case, the following
conditions should be satisfied:
    |dstsize.width − src.cols * 2 | ≤ (dstsize.width mod 2)
    |dstsize.height − src.rows * 2 | ≤ (dstsize.height mod 2)
The function performs the upsampling step of the Gaussian pyramid construction, though it can actually be used to
construct the Laplacian pyramid. First, it upsamples the source image by injecting even zero rows and columns and
then convolves the result with the same kernel as in pyrDown() multiplied by 4.

(注:以上内容出自opencv2refman.pdf)

实例:

//预先计算每一层的尺寸
vector<Size> levelsz;           //保存每一层的尺寸
Mat src = img;                  //img为原始图像,尺寸为h*w
int nLevel = 7;                 //总层数
levelsz.push_back(src.size());  // levelsz[0]保存原始图像的尺寸,即金字塔底部大小
for (int i = 1; i < nLevel; i++ )
{
    //计算每一层的尺寸
    Size sz = levelsz[i-1], downsz;
    int m = sz.width, n = sz.height;
    downsz.width = (1+sz.width)/2;
    downsz.height = (1+sz.height)/2;
    levelsz.push_back(downsz);
}

//金字塔分解
vector<Mat> GausVec, LaplVec; 
//初始化高斯金字塔
GausVec.clear();
GausVec.resize(nLevel);   
GausVec[0] = src.clone();   //原始图像作为第一次迭代输入
//初始化拉普拉斯金字塔
LaplVec.clear();
LaplVec.resize(nLevel);   
Mat pred;
for (int i = 0; i+1 < nLevel; i++)
{
    pyrDown(GausVec[i], GausVec[i+1], levelsz[i+1]);//迭代步骤1,下一级近似
    pyrUp(GausVec[i+1], pred, levelsz[i]);          //迭代步骤2,预测
    LaplVec[i] = GausVec[i] - pred;                 //迭代步骤3,残差=本级近似-预测  
}

//重建原始图像
Mat reImg = GausVec[nLevel-1];       //从金字塔顶端开始
for (int i = nLevel - 2; i >= 0; i--)
{
    Mat img1, img2; 
    pyrUp(reImg, img1, levelsz[i]);  
    reImg = img1.clone();            //j-1级近似
    reImg = reImg + LaplVec[i];      //j级近似=j-1级近似+残差
}// end for
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值