一维高斯函数:
image.png高斯函数具有线性可分的性质,即可以通过2个一维的高斯函数,分别对图像进行纵向和横向进行一次处理,就能得到和二维高斯函数一致的效果。
重点在于,一维高斯函数处理图像的复杂度为 2xy2r,而二维高斯函数的复杂度达到了xy4r^2,一维比二维降低了指数级的复杂度!
QT代码:
void getWeights1D(double* weights,int r){
//计算高斯核权重
const float sigma = (r*2+1) / 2.0;
const float exp = std::exp(1);
const float sigma2 = sigma*sigma;
const float dSigma2 = 2*sigma2;
const float k = 1 / sqrt(2*3.1415926*sigma2);
double sum = 0;
for(int i = -r;i<=r;i++){
int absI =abs(i);
int it = i+r;
weights[it] = k * std::pow(exp,-absI*absI / dSigma2);
sum+= weights[it];
}
for(int i = 0;i<=r*2;++i)
weights[i] /= sum;
}
void MainWindow::GuassianBlur1D(){
int r = 10;
double* weights = new double[r*2+1];
getWeights1D(weights,r);
int width = m_srcImg.width();
int height = m_srcImg.height();
QImage newImg(m_srcImg);
auto startTime = clock();
//横向模糊
for(int i = 0 ;i<width;++i){
for(int j =0;j<height;++j){
float sumR = 0;
float sumG = 0;
float sumB = 0;
for(int x = -r;x<=r;++x){
int pos = i+x;
if(pos < 0 || pos >= width)
pos = i - x;
QColor color = m_srcImg.pixel(pos,j);
sumR += color.red()*weights[x+r];
sumG += color.green()*weights[x+r];
sumB += color.blue()*weights[x+r];
}
QColor finalColor;
int r = std::round(sumR);
int g = std::round(sumG);
int b = std::round(sumB);
finalColor.setRed(r);
finalColor.setGreen(g);
finalColor.setBlue(b);
QPoint point(i,j);
newImg.setPixelColor(point,finalColor);
}
}
//纵向模糊
for(int i = 0 ;i<width;++i){
for(int j =0;j<height;++j){
float sumR = 0;
float sumG = 0;
float sumB = 0;
for(int x = -r;x<=r;++x){
int pos = j + x;
if(pos < 0 || pos >= height)
pos = j - x;
QColor color = newImg.pixel(i,pos);
sumR += color.red()*weights[x+r];
sumG += color.green()*weights[x+r];
sumB += color.blue()*weights[x+r];
}
QColor finalColor;
int r = std::round(sumR);
int g = std::round(sumG);
int b = std::round(sumB);
finalColor.setRed(r);
finalColor.setGreen(g);
finalColor.setBlue(b);
QPoint point(i,j);
newImg.setPixelColor(point,finalColor);
}
}
auto endTime = clock();
qDebug()<<"模糊耗时"<<endTime - startTime;
newImg.save("D:/tag.jpg");
qDebug()<<"done";
delete [] weights;
}
void MainWindow::on_btnGaussBlur_clicked()
{
//GuassianBlur2D();
GuassianBlur1D();
}
运行结果为:
模糊耗时 1457
done
比二维高斯函数快了近10倍!
原图:
原图一维高斯模糊效果图:
一维高斯模糊效果图二维高斯模糊效果图
网友评论