高斯金字塔的思考
首先,关于理论的部分祭上两个博客,
http://blog.csdn.net/poem_qianmo/article/details/26157633
http://amitapba.blog.163.com/blog/static/203610207201281992239/
感觉说的已经比较详细了,在这里我就不搅舌跟子了。
直接上代码:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <boost/concept_check.hpp>
using namespace std;
using namespace cv;
cv::Mat pyrDown(cv::Mat& src);
cv::Mat pyrUp(cv::Mat& src);
static const double gaussianTemplate[7][7] =
{
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067},
{0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771},
{0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},
{0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},
{0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067}
};
int main(int argc, char **argv)
{
Mat src = imread("../0.jpg",-1);
Mat dst = pyrDown(src);
Mat dst1 = pyrUp(dst);
imshow("111",src);
//cv::waitKey(0);
imshow("222",dst);
imshow("333",dst1);
cv::waitKey(0);
return 0;
}
//向下取样
cv::Mat pyrDown(cv::Mat& src)
{
Mat dst;
dst.create(src.size(),src.type());
uchar* srcData = src.data;
uchar* dstData = dst.data;
//将原始图像进行高斯模糊,高斯卷积过程
for(int j = 0; j < src.cols-7; j++)
{
for(int i = 0; i < src.rows-7; i++)
{
double acc = 0;
double accb = 0, accg = 0, accr = 0;
for(int m = 0; m < 7; m++)
{
for(int n = 0; n < 7; n++)
{
if(src.channels() == 1)
acc += *(srcData + src.step * (i+n) + src.channels() * (j+m)) * gaussianTemplate[m][n];
else
{
accb += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 0) * gaussianTemplate[m][n];
accg += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 1) * gaussianTemplate[m][n];
accr += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 2) * gaussianTemplate[m][n];
}
}
}
if(src.channels() == 1)
*(dstData + dst.step * (i+3) + dst.channels() * (j+3))=(int)acc;
else
{
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 0)=(int)accb;
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 1)=(int)accg;
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 2)=(int)accr;
}
}
}
//将高斯卷积得到的结果取其奇数行和奇数列
cv::Mat dst1;
dst1.create(dst.rows/2,dst.cols/2,dst.type());
uchar* dst1Data = dst1.data;
//int m = 0,n = 0;
for(int j = 0,n=0; j < dst.rows-7; j = j + 2,n++)
{
for(int i = 0,m=0; i < dst.cols-7; i = i + 2,m++)
{
if(dst.channels() == 1)
*(dst1Data + dst1.step * n + dst1.channels() * m)=*(dstData + dst.step * j + dst.channels() * i);
else
{
*(dst1Data + dst1.step * n + dst1.channels() * m + 0)=*(dstData + dst.step * j + dst.channels() * i + 0);
*(dst1Data + dst1.step * n + dst1.channels() * m + 1)=*(dstData + dst.step * j + dst.channels() * i + 1);
*(dst1Data + dst1.step * n + dst1.channels() * m + 2)=*(dstData + dst.step * j + dst.channels() * i + 2);
}
}
}
return dst1;
}
cv::Mat pyrUp(cv::Mat& src)
{
cv::Mat dst1;
dst1.create(src.rows*2,src.cols*2,src.type());
uchar* dst1Data = dst1.data;
uchar* srcData = src.data;
//int m = 0,n = 0;
for(int n=0; n < src.rows; n++)
{
for(int m=0; m < src.cols; m++)
{
if(src.channels() == 1)
{
*(dst1Data + dst1.step * n + dst1.channels() * m) = *(srcData + src.step * n + src.channels() * m);
*(dst1Data + dst1.step * n + dst1.channels() * (m+1)) = 0;
*(dst1Data + dst1.step * (n+1) + dst1.channels() * m) = 0;
*(dst1Data + dst1.step * (n+1) + dst1.channels() * (m+1)) = 0;
}
else
{
*(dst1Data + dst1.step * 2 * n + dst1.channels()* 2 * m + 0) = *(srcData + src.step * n + src.channels() * m+ 0);
*(dst1Data + dst1.step * 2 * n + dst1.channels() * 2 * (m+1) + 0) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * m + 0) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * (m+1) + 0) = 0;
*(dst1Data + dst1.step * 2 * n + dst1.channels()* 2 * m + 1) = *(srcData + src.step * n + src.channels() * m+ 1);
*(dst1Data + dst1.step * 2 * n + dst1.channels() * 2 * (m+1) + 1) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * m + 1) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * (m+1) + 1) = 0;
*(dst1Data + dst1.step * 2 * n + dst1.channels()* 2 * m + 2) = *(srcData + src.step * n + src.channels() * m+ 2);
*(dst1Data + dst1.step * 2 * n + dst1.channels() * 2 * (m+1) + 2) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * m + 2) = 0;
*(dst1Data + dst1.step * 2 * (n+1) + dst1.channels() * 2 * (m+1) + 2) = 0;
}
}
}
//cv::imshow("11",dst1);
//cv::waitKey(0);
Mat dst;
dst.create(dst1.size(),dst1.type());
uchar* dstData = dst.data;
for(int j = 0; j < dst1.cols - 7; j++)
{
for(int i = 0; i < dst1.rows - 7; i++)
{
double acc = 0;
double accb = 0, accg = 0, accr = 0;
for(int m = 0; m < 7; m++)
{
for(int n = 0; n < 7; n++)
{
if(dst1.channels() == 1)
acc += *(dst1Data + dst1.step * (i+n) + dst1.channels() * (j+m)) * gaussianTemplate[m][n]*4;
else
{
accb += *(dst1Data + dst1.step * (i+n) + dst1.channels() * (j+m) + 0) * gaussianTemplate[m][n]*4;
accg += *(dst1Data + dst1.step * (i+n) + dst1.channels() * (j+m) + 1) * gaussianTemplate[m][n]*4;
accr += *(dst1Data + dst1.step * (i+n) + dst1.channels() * (j+m) + 2) * gaussianTemplate[m][n]*4;
}
}
}
if(dst1.channels() == 1)
*(dstData + dst.step * (i+3) + dst.channels() * (j+3))=(int)acc;
else
{
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 0)=(int)accb;
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 1)=(int)accg;
*(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 2)=(int)accr;
}
}
}
return dst;
}
这段代码主要是实现了高斯金字塔中向下取样算法和向上取样算法。