【圖像處理】sift特徵——生成高斯金字塔圖像c++
計算sift特徵第一步是生成高斯金字塔圖像
計算過程:
1.設置參數,高斯濾波初始化標準差,Lowe設置的爲1.6,每一組層數,這裏設置爲3。
2.計算每一組每一層的標準差float cal_scale(int group, int layer);
3.圖像首先放大爲原先的兩倍(上採樣),計算每一層的高斯濾波圖像,然後降採樣,循環至最後一組。
代碼如下:
#include <vector>
#include <assert.h>
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
class build_gauss_pyrmaid{
public:
void set_param(float delta0, int s);
void process(const cv::Mat& src);
public:
void test_save_mats();//test saved images
void test_printf_scales();//test scales
protected:
void cal_nums_of_group(cv::Size imageSize, int a = 3);//calculate the group number
void build_pyrmaid(const cv::Mat& src);
cv::Mat bgr2gray(const cv::Mat& src);
float cal_scale(int group, int layer);
private:
vector<vector<cv::Mat>> _gauss_pyrmaid;
int _nums_of_group;
float _delta0;
int _layer_each_group;
float _K;
vector<vector<float>> _scales;
};
void build_gauss_pyrmaid::set_param(float delta0, int s)
{
_delta0 = delta0;
_layer_each_group = s;
_K = (float)std::pow(2, 1.0/_layer_each_group);
}
float build_gauss_pyrmaid::cal_scale(int group, int layer)
{
assert(group < _nums_of_group);
assert(layer < _layer_each_group);
return _delta0 * std::pow(2, (group+layer)/(float)_layer_each_group);
}
void build_gauss_pyrmaid::process(const cv::Mat& src)
{
cal_nums_of_group(src.size(), 3);
build_pyrmaid(src);
}
void build_gauss_pyrmaid::cal_nums_of_group(cv::Size imageSize, int a)
{
int lens = std::min(imageSize.width, imageSize.height);
_nums_of_group = (int)std::log(lens) / std::log(2) - a;
}
cv::Mat build_gauss_pyrmaid::bgr2gray(const cv::Mat& src)
{
cv::Mat mat8;
if(src.type() == CV_8UC3) cv::cvtColor(src, mat8, CV_BGR2GRAY);
else mat8 = src.clone();
return mat8;
}
void build_gauss_pyrmaid::build_pyrmaid(const cv::Mat& src)
{
cv::Mat I0 = bgr2gray(src);
cv::pyrUp(I0, I0);
cv::Mat each_mat;
for(int group = 0; group < _nums_of_group; group++)
{
std::vector<cv::Mat> scale_mats;
std::vector<float> scales;
for(int layer = 0; layer < _layer_each_group; layer++)
{
float delta = cal_scale(group, layer);
cv::GaussianBlur(I0, each_mat, cv::Size(0,0), delta);
scale_mats.push_back(each_mat.clone());
scales.push_back(delta);
}
cv::pyrDown(I0, I0);
_scales.push_back(scales);
_gauss_pyrmaid.push_back(scale_mats);
}
}
void build_gauss_pyrmaid::test_save_mats()//test saved images
{
int group(0);
for(auto iter = _gauss_pyrmaid.begin(); iter != _gauss_pyrmaid.end(); iter++)
{
std::vector<cv::Mat> mats(*iter);
char buf[128];
int layer = 0;
for(auto jter = mats.begin(); jter != mats.end(); jter++)
{
sprintf(buf, "scale_image/%d-%d.jpg", group,layer);
cv::imwrite(buf, *jter);
layer++;
}
group++;
}
}
void build_gauss_pyrmaid::test_printf_scales()//test scales
{
int group(0);
for(auto iter = _scales.begin(); iter != _scales.end(); iter++)
{
std::vector<float> scale(*iter);
int layer = 0;
for(auto jter = scale.begin(); jter != scale.end(); jter++)
{
printf("%dth group %dth layer sacles: %.3f\n", group,layer,*jter);
layer++;
}
group++;
}
}
int main(int argc, char** argv)
{
cv::Mat src = cv::imread("lena.jpg");
build_gauss_pyrmaid* ptr = new build_gauss_pyrmaid;
ptr->set_param(1.6, 3);
ptr->process(src);
ptr->test_save_mats();
ptr->test_printf_scales();
delete ptr;
return 0;
}
爲了測試結果是否正確,添加測試接口。
void test_save_mats();//test saved images
void test_printf_scales();//test scales
結果爲:
存儲的高斯金字塔圖像爲:
只貼出第二層圖像
delta = 2.016
delta = 2.540
delta = 3.200