opencv小練習:哈爾小波(Haar)
阿新 • • 發佈:2019-01-27
首先說一下一維haar小波的原理。
例如我們有一個一維的影象[2,4,6,8,10,12,14,16].
- 求均值:我們求相鄰畫素的均值[3,7,11,15]。這個新的影象解析度就成了原來的一半(8/2=4)。
求差值。上面的均值我們儲存了影象的整體資訊。但是很多細節資訊我們丟掉了,所以我們同時要記錄影象的細節資訊,這樣在重構時能夠恢復影象的全部資訊。下面是求第m個差值的公式:
b[m]=(a[2m]−a[2m+1])/2
經過計算我們得到了結果[-1,-1,-1,-1]。這個新的解析度也成了原來的一半(8/2=4)。
3. 此時上面兩步形成了第一次分解的結果[3,7,11,15,-1,-1,-1,-1]。包含了影象的整體資訊和細節資訊。接下來的分解我們重複1,2步,將整體資訊再次進行分解,得到了二級分解結果[5,13,-2,-2].同樣的,前面的[5,13]是整體資訊,後面的[-2,-2]是細節資訊。
解析度 | 整體資訊 | 細節資訊 |
---|---|---|
4 | 3,7,11,15 | -1,-1,-1,-1 |
2 | 5,13 | -2,-2 |
1 | 9 | -4 |
經過三次分解,我們得到了一個整體資訊和三個細節係數,這個就是一維小波變換。
對於二維haar小波,我們通常一次分解形成了整體影象,水平細節,垂直細節,對角細節。首先我們按照一維haar小波分解的原理,按照行順序對行進行處理,然後按照列順序對行處理結果進行同樣的處理。最後形成了如下的形式。
接下來就是程式碼時間了,首先看下程式碼結果:
c++程式碼(opencv版本:opencv3.0):
/*************************************************
Copyright:zhuchen
Author: zhuchen
Date:2016-01-10
Description:多級haar小波變換
**************************************************/
# include<opencv2/opencv.hpp>
# include<iostream>
using namespace std;
using namespace cv;
int main(){
Mat img = imread("lenna.bmp",0);
int Height = img.cols;
int Width = img.rows;
int depth = 3; //定義分解深度
int depthcount = 1;
Mat tmp = Mat::ones(Width, Height, CV_32FC1);
Mat wavelet = Mat::ones(Width, Height, CV_32FC1);
Mat imgtmp = img.clone();
imgtmp.convertTo(imgtmp, CV_32FC1);
while (depthcount<=depth){
Width = img.rows / depthcount;
Height = img.cols / depthcount;
for (int i = 0; i < Width; i++){
for (int j = 0; j < Height / 2; j++){
tmp.at<float>(i, j) = (imgtmp.at<float>(i, 2 * j) + imgtmp.at<float>(i, 2 * j + 1)) / 2;
tmp.at<float>(i, j + Height / 2) = (imgtmp.at<float>(i, 2 * j) - imgtmp.at<float>(i, 2 * j + 1)) / 2;
}
}
for (int i = 0; i < Width / 2; i++){
for (int j = 0; j < Height; j++){
wavelet.at<float>(i, j) = (tmp.at<float>(2 * i, j) + tmp.at<float>(2 * i + 1, j)) / 2;
wavelet.at<float>(i + Width / 2, j) = (tmp.at<float>(2 * i, j) - tmp.at<float>(2 * i + 1, j)) / 2;
}
}
imgtmp = wavelet;
depthcount++;
}
namedWindow("jpg",0);
wavelet.convertTo(wavelet, CV_8UC1);
wavelet += 50; //影象暗度過低,所以這裡我加了50
imshow("jpg", wavelet);
waitKey(0);
return 0;
}