1. 之前发表了 python 的这个算法实现.
2.现在 写一个相同的 c++ 实现.
以下是代码:
#ifndef LARCOTM_H
#define LARCOTM_H
#include "opencv.hpp"
namespace larcotm {
cv::Mat larcotm(const std::string& filepath, float strength=0.0f);
cv::Mat larcotm(const cv::Mat& imImg, float strength=0.0f);
void clip(cv::Mat& src,int min,int max);
cv::Mat handle(const cv::Mat& imImg, float strength=0.0f);
}
#endif
#include "larcotm.hpp"
#include <opencv2/ximgproc/edge_filter.hpp>
#include<algorithm>
#include <vector>
static const std::string TAG = "larcotm";
namespace larcotm
{
cv::Mat larcotm(const std::string& filepath, float strength){
cv::Mat inimg = cv::imread(filepath);
return handle(inimg,strength);
}
cv::Mat larcotm(const cv::Mat& inimg, float strength){
return handle(inimg,strength);
}
//这里的clip ==> numpy.clip
void clip(cv::Mat& src,int min,int max){
if(min > max){
return;
}
src.setTo(min,src < min);
src.setTo(max,src > max);
}
cv::Mat handle(const cv::Mat& imImg,float strength){
cv::Mat img;
imImg.convertTo(img,CV_32FC3, 1 / 255.0);
cv::Mat src;
cv::cvtColor(img, src, cv::COLOR_BGR2GRAY);
double m = 0;
if(strength == 0){
//cv::Scalar sc_mean_all = cv::mean(src);
m = cv::mean(src)[0];
std::cout << TAG << " Mean: " << m << std::endl;
double gmean = m*255;
float gstore=std::min(std::max((25-gmean)*5 ,50.),100.);
strength = gstore;
}
float log_min=1.0;
cv::Mat tmp;
auto log_min_temp = 255 - log_min;
cv::multiply(src,1/255.*log_min_temp,tmp);
auto add_num = log_min/255;
cv::Mat tmg;
cv::add(tmp,add_num,tmg);//加法
cv::Mat img_high;
cv::log(tmg,img_high);
std::vector<int> filt_size={100,50,25};
cv::Mat omg;
cv::multiply(img_high,filt_size.size(),omg);//乘法
std::vector<int>::iterator iter;
for(iter = filt_size.begin();iter != filt_size.end();iter++){
cv::Mat img_low;
cv::ximgproc::guidedFilter(src,src,img_low,*iter,1);
cv::subtract(omg,img_low,omg);//减法
}
cv::divide(omg,6,omg);
cv::exp(omg,omg);
cv::normalize(omg,omg,0,1,cv::NORM_MINMAX,CV_32FC1);
cv::normalize(src,tmg,0,1,cv::NORM_MINMAX,CV_32FC1);
cv::multiply(tmg,0.6,tmg);
cv::add(omg,tmg,omg);
cv::normalize(omg,omg,0,0.9,cv::NORM_MINMAX,CV_32FC1);
cv::multiply(omg,65535.,omg);
clip(omg,0,65535);
omg.convertTo(omg,CV_16UC3,1);
auto clahe = cv::createCLAHE(0.4*strength,cv::Size(1,1));
clahe->apply(omg,omg);// 依旧储存在 omg 变量
cv::Mat dst;
omg.convertTo(dst,CV_32FC3, 1 / 65535.0);//将omg 转化为dst
cv::Mat L;
cv::divide(dst,(src + 1./255.),L);//用dst 除以 (src+1/255) 得到L
cv::cvtColor(L,L,cv::COLOR_GRAY2BGR);//颜色转化,依旧用 L 存储
cv::Mat clip_temp;
cv::multiply(img,L,clip_temp);
clip(clip_temp,0,1);
cv::Mat dst_finally;
cv::cvtColor(clip_temp,dst_finally,cv::COLOR_BGR2RGB);
return dst_finally;
}
};