Skip to content

Commit dc609db

Browse files
committed
Add GuidedFilter
1 parent f7cb726 commit dc609db

File tree

2 files changed

+263
-0
lines changed

2 files changed

+263
-0
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
2+
#include <iostream>
3+
#include <opencv2/core.hpp>
4+
#include <opencv2/highgui.hpp>
5+
#include <opencv2/imgproc.hpp>
6+
7+
8+
///////////////////////////////////////////////////////////////////
9+
// GUIDEDFILTER_COLOR O(1) time implementation of guided filter using a color image as the guidance.
10+
//
11+
// -guidance image : I(should be a color(RGB) image)
12+
// -filtering input image : p(should be a gray - scale / single channel image)
13+
// -local window radius : r
14+
// -regularization parameter : eps
15+
///////////////////////////////////////////////////////////////////
16+
cv::Mat GuidedFilter_Color(cv::Mat& I, cv::Mat& p, int r, double eps ){
17+
int wsize = 2 * r + 1;
18+
//鑒앴잚謹瘻뻣
19+
I.convertTo(I, CV_64F, 1.0 / 255.0);
20+
p.convertTo(p, CV_64F, 1.0 / 255.0);
21+
22+
//多돔暠繫돛롸잼
23+
if (I.channels() == 1){
24+
std::cout<<"I should be a color(RGB) image "<<std::endl;
25+
}
26+
std::vector<cv::Mat> rgb;
27+
cv::split(I, rgb);
28+
29+
//meanI=fmean(I)
30+
cv::Mat mean_I_r, mean_I_g, mean_I_b;
31+
cv::boxFilter(rgb[0], mean_I_b, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
32+
cv::boxFilter(rgb[1], mean_I_g, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
33+
cv::boxFilter(rgb[2], mean_I_r, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
34+
35+
//meanP=fmean(P)
36+
cv::Mat mean_p;
37+
cv::boxFilter(p, mean_p, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
38+
39+
//corrI=fmean(I.*I)
40+
cv::Mat mean_II_rr, mean_II_rg, mean_II_rb, mean_II_gb, mean_II_gg, mean_II_bb;
41+
cv::boxFilter(rgb[2].mul(rgb[2]), mean_II_rr, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
42+
cv::boxFilter(rgb[2].mul(rgb[1]), mean_II_rg, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
43+
cv::boxFilter(rgb[2].mul(rgb[0]), mean_II_rb, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
44+
cv::boxFilter(rgb[1].mul(rgb[0]), mean_II_gb, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
45+
cv::boxFilter(rgb[1].mul(rgb[1]), mean_II_gg, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
46+
cv::boxFilter(rgb[0].mul(rgb[0]), mean_II_bb, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
47+
48+
//corrIp=fmean(I.*p)
49+
cv::Mat mean_Ip_r, mean_Ip_g, mean_Ip_b;
50+
mean_Ip_b = rgb[0].mul(p);
51+
mean_Ip_g = rgb[1].mul(p);
52+
mean_Ip_r = rgb[2].mul(p);
53+
cv::boxFilter(mean_Ip_b, mean_Ip_b, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
54+
cv::boxFilter(mean_Ip_g, mean_Ip_g, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
55+
cv::boxFilter(mean_Ip_r, mean_Ip_r, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
56+
57+
//covIp=corrIp-meanI.*meanp
58+
cv::Mat cov_Ip_r, cov_Ip_g, cov_Ip_b;
59+
cv::subtract(mean_Ip_r, mean_I_r.mul(mean_p), cov_Ip_r);
60+
cv::subtract(mean_Ip_g, mean_I_g.mul(mean_p), cov_Ip_g);
61+
cv::subtract(mean_Ip_b, mean_I_b.mul(mean_p), cov_Ip_b);
62+
63+
//varI=corrI-meanI.*meanI
64+
//variance of I in each local patch : the matrix Sigma in Eqn(14).
65+
//Note the variance in each local patch is a 3x3 symmetric matrix :
66+
// rr, rg, rb
67+
// Sigma = rg, gg, gb
68+
// rb, gb, bb
69+
cv::Mat var_I_rr, var_I_rg, var_I_rb, var_I_gb, var_I_gg, var_I_bb;
70+
cv::subtract(mean_II_rr, mean_I_r.mul(mean_I_r), var_I_rr);
71+
cv::subtract(mean_II_rg, mean_I_r.mul(mean_I_g), var_I_rg);
72+
cv::subtract(mean_II_rb, mean_I_r.mul(mean_I_b), var_I_rb);
73+
cv::subtract(mean_II_gb, mean_I_g.mul(mean_I_b), var_I_gb);
74+
cv::subtract(mean_II_gg, mean_I_g.mul(mean_I_g), var_I_gg);
75+
cv::subtract(mean_II_bb, mean_I_b.mul(mean_I_b), var_I_bb);
76+
77+
//a=conIp./(varI+eps)
78+
int cols = p.cols;
79+
int rows = p.rows;
80+
cv::Mat Mat_a = cv::Mat::zeros(rows, cols,CV_64FC3);
81+
std::vector<cv::Mat> a;
82+
cv::split(Mat_a, a);
83+
double rr, rg, rb, gg, gb, bb;
84+
for (int i = 0; i < rows; ++i){
85+
for (int j = 0; j < cols; ++j){
86+
rr = var_I_rr.at<double>(i, j); rg = var_I_rg.at<double>(i, j); rb = var_I_rb.at<double>(i, j);
87+
gg = var_I_gg.at<double>(i, j); gb = var_I_gb.at<double>(i, j);
88+
bb = var_I_bb.at<double>(i, j);
89+
cv::Mat sigma = (cv::Mat_<double>(3, 3) << rr, rg, rb,
90+
rg, gg, gb,
91+
rb, gb, bb);
92+
cv::Mat cov_Ip = (cv::Mat_<double>(1, 3) << cov_Ip_r.at<double>(i, j), cov_Ip_g.at<double>(i, j), cov_Ip_b.at<double>(i, j));
93+
cv::Mat eye = cv::Mat::eye(3, 3, CV_64FC1);
94+
sigma = sigma + eps*eye;
95+
cv::Mat sigma_inv = sigma.inv();//헹쾀앤黎
96+
cv::Mat tmp = cov_Ip*sigma_inv;
97+
a[2].at<double>(i, j) = tmp.at<double>(0, 0);//r
98+
a[1].at<double>(i, j) = tmp.at<double>(0, 1);//g
99+
a[0].at<double>(i, j) = tmp.at<double>(0, 2);//b
100+
}
101+
}
102+
103+
//b=meanp-a.*meanI
104+
cv::Mat b = mean_p - a[0].mul(mean_I_b) - a[1].mul(mean_I_g) - a[2].mul(mean_I_r);
105+
106+
//meana=fmean(a)
107+
//meanb=fmean(b)
108+
cv::Mat mean_a_r, mean_a_g, mean_a_b, mean_b;
109+
cv::boxFilter(a[0], mean_a_b, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
110+
cv::boxFilter(a[1], mean_a_g, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
111+
cv::boxFilter(a[2], mean_a_r, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
112+
cv::boxFilter(b, mean_b, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//분綾쫀꺼
113+
114+
//q=meana.*I+meanb
115+
cv::Mat q = mean_a_r.mul(rgb[2]) + mean_a_g.mul(rgb[1]) + mean_a_b.mul(rgb[0]) + mean_b;
116+
117+
//鑒앴잚謹瘻뻣
118+
I.convertTo(I, CV_8UC3, 255);
119+
p.convertTo(p, CV_8U, 255);
120+
q.convertTo(q, CV_8U, 255);
121+
122+
return q;
123+
}
124+
125+
int main(){
126+
cv::Mat I = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\woman.jpg");
127+
cv::Mat P = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\woman.jpg");
128+
if (I.empty() || P.empty()){
129+
return -1;
130+
}
131+
if (P.channels() > 1)
132+
cv::cvtColor(P, P, CV_RGB2GRAY);
133+
134+
//菱긍GuidedFilter꿎桿
135+
double t2 = (double)cv::getTickCount(); //꿎珂쇌
136+
cv::Mat q;
137+
q = GuidedFilter_Color(I, P, 9, 0.1*0.1);
138+
t2 = (double)cv::getTickCount() - t2;
139+
double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());
140+
std::cout << "MyGuidedFilter_process=" << time2 << " ms. " << std::endl << std::endl;
141+
142+
cv::namedWindow("GuidedImg", CV_WINDOW_NORMAL);
143+
cv::imshow("GuidedImg", I);
144+
cv::namedWindow("src", CV_WINDOW_NORMAL);
145+
cv::imshow("src", P);
146+
cv::namedWindow("GuidedFilter", CV_WINDOW_NORMAL);
147+
cv::imshow("GuidedFilter", q);
148+
cv::waitKey(0);
149+
150+
}

Image Filtering/Guided Filter.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <iostream>
2+
#include <opencv2/core.hpp>
3+
#include <opencv2/highgui.hpp>
4+
#include <opencv2/imgproc.hpp>
5+
6+
//////////////////////////////////////////////
7+
// GUIDEDFILTER O(1) time implementation of guided filter.
8+
// -guidance image : I(should be a gray - scale / single channel image)
9+
// -filtering input image : p(should be a gray - scale / single channel image)
10+
// -local window radius : r
11+
// -regularization parameter : eps
12+
/////////////////////////////////////////////
13+
cv::Mat GuidedFilter(cv::Mat& I, cv::Mat& p, int r, double eps){
14+
int wsize = 2 * r + 1;
15+
//数据类型转换
16+
I.convertTo(I, CV_64F, 1.0 / 255.0);
17+
p.convertTo(p, CV_64F, 1.0 / 255.0);
18+
19+
//meanI=fmean(I)
20+
cv::Mat mean_I;
21+
cv::boxFilter(I, mean_I, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
22+
23+
//meanP=fmean(P)
24+
cv::Mat mean_p;
25+
cv::boxFilter(p, mean_p, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
26+
27+
//corrI=fmean(I.*I)
28+
cv::Mat mean_II;
29+
mean_II = I.mul(I);
30+
cv::boxFilter(mean_II, mean_II, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
31+
32+
//corrIp=fmean(I.*p)
33+
cv::Mat mean_Ip;
34+
mean_Ip = I.mul(p);
35+
cv::boxFilter(mean_Ip, mean_Ip, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
36+
37+
//varI=corrI-meanI.*meanI
38+
cv::Mat var_I, mean_mul_I;
39+
mean_mul_I=mean_I.mul(mean_I);
40+
cv::subtract(mean_II, mean_mul_I, var_I);
41+
42+
//covIp=corrIp-meanI.*meanp
43+
cv::Mat cov_Ip;
44+
cv::subtract(mean_Ip, mean_I.mul(mean_p), cov_Ip);
45+
46+
//a=conIp./(varI+eps)
47+
//b=meanp-a.*meanI
48+
cv::Mat a, b;
49+
cv::divide(cov_Ip, (var_I+eps),a);
50+
cv::subtract(mean_p, a.mul(mean_I), b);
51+
52+
//meana=fmean(a)
53+
//meanb=fmean(b)
54+
cv::Mat mean_a, mean_b;
55+
cv::boxFilter(a, mean_a, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
56+
cv::boxFilter(b, mean_b, -1, cv::Size(wsize, wsize), cv::Point(-1, -1), true, cv::BORDER_REFLECT);//盒子滤波
57+
58+
//q=meana.*I+meanb
59+
cv::Mat q;
60+
q = mean_a.mul(I) + mean_b;
61+
62+
//数据类型转换
63+
I.convertTo(I, CV_8U, 255);
64+
p.convertTo(p, CV_8U, 255);
65+
q.convertTo(q, CV_8U, 255);
66+
67+
return q;
68+
69+
}
70+
71+
int main(){
72+
cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\woman.jpg");
73+
if (src.empty()){
74+
return -1;
75+
}
76+
77+
//if (src.channels() > 1)
78+
// cv::cvtColor(src, src, CV_RGB2GRAY);
79+
80+
//自编GuidedFilter测试
81+
double t2 = (double)cv::getTickCount(); //测时间
82+
83+
cv::Mat dst1, src_input, I;
84+
src.copyTo(src_input);
85+
if (src.channels() > 1)
86+
cv::cvtColor(src, I, CV_RGB2GRAY); //若引导图为彩色图,则转为灰度图
87+
std::vector<cv::Mat> p,q;
88+
if (src.channels() > 1){ //输入为彩色图
89+
cv::split(src_input, p);
90+
for (int i = 0; i < src.channels(); ++i){
91+
dst1 = GuidedFilter(I, p[i], 9, 0.1*0.1);
92+
q.push_back(dst1);
93+
}
94+
cv::merge(q, dst1);
95+
}
96+
else{ //输入为灰度图
97+
src.copyTo(I);
98+
dst1 = GuidedFilter(I, src_input, 9, 0.1*0.1);
99+
}
100+
101+
t2 = (double)cv::getTickCount() - t2;
102+
double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());
103+
std::cout << "MyGuidedFilter_process=" << time2 << " ms. " << std::endl << std::endl;
104+
105+
cv::namedWindow("GuidedImg", CV_WINDOW_NORMAL);
106+
cv::imshow("GuidedImg", I);
107+
cv::namedWindow("src", CV_WINDOW_NORMAL);
108+
cv::imshow("src", src);
109+
cv::namedWindow("GuidedFilter_box", CV_WINDOW_NORMAL);
110+
cv::imshow("GuidedFilter_box", dst1);
111+
cv::waitKey(0);
112+
113+
}

0 commit comments

Comments
 (0)