OpenCV图像处理中如何利用多尺度融合提升图像细节

发布时间:2021-12-15 18:00:45 作者:柒染
来源:亿速云 阅读:186

OpenCV图像处理中如何利用多尺度融合提升图像细节,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

前言

今天为大家介绍一个利用多尺度来提升图像细节的算法。如果你想自己的图片细节看起来更加丰富的话可以尝试一下这个算法。

 

算法原理

核心就是,论文使用了Retinex方法类似的思路,使用了多个尺度的高斯核对原图滤波,然后再和原图做减法,获得不同程度的细节信息,然后通过一定的组合方式把这些细节信息融合到原图中,从而得到加强原图信息的能力。公式十分简单,注意到第一个系数有点特殊,实现的话,直接看下图的几个公式即可。

「从深度学习中特征金字塔网络的思想来看,这个算法实际上就是将不同尺度上的特征图进行了融合,不过这个方式是直接针对原图进行,比较粗暴,但有个好处就是这个算法用于预处理阶段是易于优化的,关于如何优化后面讲SSE指令集优化的时候再来讨论,今天先提供原始的实现啦。」

OpenCV图像处理中如何利用多尺度融合提升图像细节  
在这里插入图片描述
 

代码实现

void separateGaussianFilter(const Mat &src, Mat &dst, int ksize, double sigma){
   CV_Assert(src.channels()==1 || src.channels() == 3); //只处理单通道或者三通道图像
   //生成一维的
   double *matrix = new double[ksize];
   double sum = 0;
   int origin = ksize / 2;
   for(int i = 0; i < ksize; i++){
       double g = exp(-(i-origin) * (i-origin) / (2 * sigma * sigma));
       sum += g;
       matrix[i] = g;
   }
   for(int i = 0; i < ksize; i++) matrix[i] /= sum;
   int border = ksize / 2;
   copyMakeBorder(src, dst, border, border, border, border, BORDER_CONSTANT);
   int channels = dst.channels();
   int rows = dst.rows - border;
   int cols = dst.cols - border;
   //水平方向
   for(int i = border; i < rows; i++){
       for(int j = border; j < cols; j++){
           double sum[3] = {0};
           for(int k = -border; k<=border; k++){
               if(channels == 1){
                   sum[0] += matrix[border + k] * dst.at<uchar>(i, j+k);
               }else if(channels == 3){
                   Vec3b rgb = dst.at<Vec3b>(i, j+k);
                   sum[0] += matrix[border+k] * rgb[0];
                   sum[1] += matrix[border+k] * rgb[1];
                   sum[2] += matrix[border+k] * rgb[2];
               }
           }
           for(int k = 0; k < channels; k++){
               if(sum[k] < 0) sum[k] = 0;
               else if(sum[k] > 255) sum[k] = 255;
           }
           if(channels == 1)
               dst.at<Vec3b>(i, j) = static_cast<uchar>(sum[0]);
           else if(channels == 3){
               Vec3b rgb = {static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2])};
               dst.at<Vec3b>(i, j) = rgb;
           }
       }
   }
   //竖直方向
   for(int i = border; i < rows; i++){
       for(int j = border; j < cols; j++){
           double sum[3] = {0};
           for(int k = -border; k<=border; k++){
               if(channels == 1){
                   sum[0] += matrix[border + k] * dst.at<uchar>(i+k, j);
               }else if(channels == 3){
                   Vec3b rgb = dst.at<Vec3b>(i+k, j);
                   sum[0] += matrix[border+k] * rgb[0];
                   sum[1] += matrix[border+k] * rgb[1];
                   sum[2] += matrix[border+k] * rgb[2];
               }
           }
           for(int k = 0; k < channels; k++){
               if(sum[k] < 0) sum[k] = 0;
               else if(sum[k] > 255) sum[k] = 255;
           }
           if(channels == 1)
               dst.at<Vec3b>(i, j) = static_cast<uchar>(sum[0]);
           else if(channels == 3){
               Vec3b rgb = {static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2])};
               dst.at<Vec3b>(i, j) = rgb;
           }
       }
   }
   delete [] matrix;
}

Mat MultiScaleDetailBoosting(Mat src, int Radius){
   int rows = src.rows;
   int cols = src.cols;
   Mat B1, B2, B3;
   separateGaussianFilter(src, B1, Radius, 1.0);
   separateGaussianFilter(src, B2, Radius*2-1, 2.0);
   separateGaussianFilter(src, B3, Radius*4-1, 4.0);
   float w1 = 0.5, w2 = 0.5, w3 = 0.25;
   Mat dst(rows, cols, CV_8UC3);
   for(int i = 0; i < rows; i++){
       for(int j = 0; j < cols; j++){
           for(int k = 0; k < 3; k++){
               int D1 = src.at<Vec3b>(i, j)[k] - B1.at<Vec3b>(i, j)[k];
               int D2 = B1.at<Vec3b>(i, j)[k] - B2.at<Vec3b>(i, j)[k];
               int D3 = B2.at<Vec3b>(i, j)[k] - B3.at<Vec3b>(i, j)[k];
               int sign = D1 > 0 ? 1 : -1;
               dst.at<Vec3b>(i, j)[k] = saturate_cast<uchar>((1 - w1*sign) * D1 - w2 * D2 + w3 * D3 + src.at<Vec3b>(i, j)[k]);
           }
       }
   }
   return dst;
}
   

效果

OpenCV图像处理中如何利用多尺度融合提升图像细节  
原图
OpenCV图像处理中如何利用多尺度融合提升图像细节  
效果图
    

关于OpenCV图像处理中如何利用多尺度融合提升图像细节问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。

推荐阅读:
  1. opencv中图像叠加/图像融合/按位操作的实现案例
  2. python实现泊松图像融合

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

opencv

上一篇:OpenCV中辅助对象指的是什么

下一篇:linux如何修改path环境变量

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》