Skip to content

Commit 941a33a

Browse files
committed
Merge pull request #1163 from tucna:FastFuzzyTransform
2 parents d8eac20 + aceaa03 commit 941a33a

File tree

5 files changed

+370
-5
lines changed

5 files changed

+370
-5
lines changed

modules/fuzzy/include/opencv2/fuzzy/fuzzy_F0_math.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ namespace ft
121121
*/
122122
CV_EXPORTS_W int FT02D_iteration(InputArray matrix, InputArray kernel, OutputArray output, InputArray mask, OutputArray maskOutput, bool firstStop);
123123

124+
/** @brief Sligtly less accurate version of F0-transfrom computation optimized for higher speed. The methods counts with linear basic function.
125+
@param matrix Input 3 channels matrix.
126+
@param radius Radius of the **LINEAR** basic function.
127+
@param output Output array.
128+
129+
This function computes F-transfrom and inverse F-transfotm using linear basic function in one step. It is ~10 times faster than **FT02D_process** method.
130+
*/
131+
CV_EXPORTS_W void FT02D_FL_process(InputArray matrix, const int radius, OutputArray output);
132+
133+
/** @brief Sligtly less accurate version of F0-transfrom computation optimized for higher speed. The methods counts with linear basic function.
134+
@param matrix Input 3 channels matrix.
135+
@param radius Radius of the **LINEAR** basic function.
136+
@param output Output array.
137+
138+
This function computes F-transfrom and inverse F-transfotm using linear basic function in one step. It is ~9 times faster then **FT02D_process** method and more accurate than **FT02D_FL_process** method.
139+
*/
140+
CV_EXPORTS_W void FT02D_FL_process_float(InputArray matrix, const int radius, OutputArray output);
141+
124142
//! @}
125143
}
126144
}

modules/fuzzy/include/opencv2/fuzzy/fuzzy_image.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace ft
5656
/** @brief Creates kernel from basic functions.
5757
@param A Basic function used in axis **x**.
5858
@param B Basic function used in axis **y**.
59-
@param kernel Final 32-b kernel derived from **A** and **B**.
59+
@param kernel Final 32-bit kernel derived from **A** and **B**.
6060
@param chn Number of kernel channels.
6161
6262
The function creates kernel usable for latter fuzzy image processing.
@@ -67,7 +67,7 @@ namespace ft
6767
@param function Function type could be one of the following:
6868
- **LINEAR** Linear basic function.
6969
@param radius Radius of the basic function.
70-
@param kernel Final 32-b kernel.
70+
@param kernel Final 32-bit kernel.
7171
@param chn Number of kernel channels.
7272
7373
The function creates kernel from predefined functions.

modules/fuzzy/samples/fuzzy_inpainting.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ int main(void)
3838
Mat I = imread("input.png");
3939

4040
// Various masks
41-
Mat mask1 = imread("mask1.png");
42-
Mat mask2 = imread("mask2.png");
43-
Mat mask3 = imread("mask3.png");
41+
Mat mask1 = imread("mask1.png", IMREAD_GRAYSCALE);
42+
Mat mask2 = imread("mask2.png", IMREAD_GRAYSCALE);
43+
Mat mask3 = imread("mask3.png", IMREAD_GRAYSCALE);
4444

4545
// Apply the damage
4646
Mat input1, input2, input3;

modules/fuzzy/src/fuzzy_F0_math.cpp

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,262 @@
4343

4444
using namespace cv;
4545

46+
void ft::FT02D_FL_process(InputArray matrix, const int radius, OutputArray output)
47+
{
48+
CV_Assert(matrix.channels() == 3);
49+
50+
int borderPadding = 2 * radius + 1;
51+
Mat imagePadded;
52+
53+
copyMakeBorder(matrix, imagePadded, radius, borderPadding, radius, borderPadding, BORDER_CONSTANT, Scalar(0));
54+
55+
Mat channel[3];
56+
split(imagePadded, channel);
57+
58+
uchar *im_r = channel[2].data;
59+
uchar *im_g = channel[1].data;
60+
uchar *im_b = channel[0].data;
61+
62+
int width = imagePadded.cols;
63+
int height = imagePadded.rows;
64+
int n_width = width / radius + 1;
65+
int n_height = height / radius + 1;
66+
67+
std::vector<uchar> c_r(n_width * n_height);
68+
std::vector<uchar> c_g(n_width * n_height);
69+
std::vector<uchar> c_b(n_width * n_height);
70+
71+
int sum_r, sum_g, sum_b, num, c_wei;
72+
int c_pos, pos, pos2, wy;
73+
int cy = 0;
74+
float num_f;
75+
76+
std::vector<int> wei(radius + 1);
77+
78+
for (int i = 0; i <= radius; i++)
79+
{
80+
wei[i] = radius - i;
81+
}
82+
83+
for (int y = radius; y < height - radius; y += radius)
84+
{
85+
c_pos = cy;
86+
87+
for (int x = radius; x < width - radius; x += radius)
88+
{
89+
num = sum_r = sum_g = sum_b = 0;
90+
91+
for (int y1 = y - radius; y1 <= y + radius; y1++)
92+
{
93+
pos = y1 * width;
94+
wy = wei[abs(y1 - y)];
95+
96+
for (int x1 = x - radius; x1 <= x + radius; x1++)
97+
{
98+
c_wei = wei[abs(x1 - x)] * wy;
99+
pos2 = pos + x1;
100+
sum_r += im_r[pos2] * c_wei;
101+
sum_g += im_g[pos2] * c_wei;
102+
sum_b += im_b[pos2] * c_wei;
103+
num += c_wei;
104+
}
105+
}
106+
107+
num_f = 1.0f / (float)num;
108+
109+
c_r[c_pos] = (uchar)cvRound(sum_r * num_f);
110+
c_g[c_pos] = (uchar)cvRound(sum_g * num_f);
111+
c_b[c_pos] = (uchar)cvRound(sum_b * num_f);
112+
113+
c_pos++;
114+
}
115+
116+
cy += n_width;
117+
}
118+
119+
int p1, p2, p3, p4, yw, w1, w2, w3, w4, lx, ly, lx1, ly1, pos_iFT;
120+
float num_iFT;
121+
122+
int output_height = matrix.rows();
123+
int output_width = matrix.cols();
124+
125+
uchar *img_r = new uchar[output_height * output_width];
126+
uchar *img_g = new uchar[output_height * output_width];
127+
uchar *img_b = new uchar[output_height * output_width];
128+
129+
for (int y = 0; y < output_height; y++)
130+
{
131+
ly1 = (y % radius);
132+
ly = radius - ly1;
133+
yw = y / radius * n_width;
134+
pos_iFT = y * output_width;
135+
136+
for (int x = 0; x < output_width; x++)
137+
{
138+
lx1 = (x % radius);
139+
lx = radius - lx1;
140+
141+
p1 = x / radius + yw;
142+
p2 = p1 + 1;
143+
p3 = p1 + n_width;
144+
p4 = p3 + 1;
145+
146+
w1 = lx * ly;
147+
w2 = lx1 * ly;
148+
w3 = lx * ly1;
149+
w4 = lx1 * ly1;
150+
151+
num_iFT = 1.0f / (float)(w1 + w2 + w3 + w4);
152+
153+
img_r[pos_iFT] = (uchar)((c_r[p1] * w1 + c_r[p2] * w2 + c_r[p3] * w3 + c_r[p4] * w4) * num_iFT);
154+
img_g[pos_iFT] = (uchar)((c_g[p1] * w1 + c_g[p2] * w2 + c_g[p3] * w3 + c_g[p4] * w4) * num_iFT);
155+
img_b[pos_iFT] = (uchar)((c_b[p1] * w1 + c_b[p2] * w2 + c_b[p3] * w3 + c_b[p4] * w4) * num_iFT);
156+
157+
pos_iFT++;
158+
}
159+
}
160+
161+
Mat compR(output_height, output_width, CV_8UC1, img_r);
162+
Mat compG(output_height, output_width, CV_8UC1, img_g);
163+
Mat compB(output_height, output_width, CV_8UC1, img_b);
164+
165+
std::vector<Mat> oComp;
166+
167+
oComp.push_back(compB);
168+
oComp.push_back(compG);
169+
oComp.push_back(compR);
170+
171+
merge(oComp, output);
172+
}
173+
174+
void ft::FT02D_FL_process_float(InputArray matrix, const int radius, OutputArray output)
175+
{
176+
CV_Assert(matrix.channels() == 3);
177+
178+
int borderPadding = 2 * radius + 1;
179+
Mat imagePadded;
180+
181+
copyMakeBorder(matrix, imagePadded, radius, borderPadding, radius, borderPadding, BORDER_CONSTANT, Scalar(0));
182+
183+
Mat channel[3];
184+
split(imagePadded, channel);
185+
186+
uchar *im_r = channel[2].data;
187+
uchar *im_g = channel[1].data;
188+
uchar *im_b = channel[0].data;
189+
190+
int width = imagePadded.cols;
191+
int height = imagePadded.rows;
192+
int n_width = width / radius + 1;
193+
int n_height = height / radius + 1;
194+
195+
std::vector<float> c_r(n_width * n_height);
196+
std::vector<float> c_g(n_width * n_height);
197+
std::vector<float> c_b(n_width * n_height);
198+
199+
int sum_r, sum_g, sum_b, num, c_wei;
200+
int c_pos, pos, pos2, wy;
201+
int cy = 0;
202+
float num_f;
203+
204+
std::vector<int> wei(radius + 1);
205+
206+
for (int i = 0; i <= radius; i++)
207+
{
208+
wei[i] = radius - i;
209+
}
210+
211+
for (int y = radius; y < height - radius; y += radius)
212+
{
213+
c_pos = cy;
214+
215+
for (int x = radius; x < width - radius; x += radius)
216+
{
217+
num = sum_r = sum_g = sum_b = 0;
218+
219+
for (int y1 = y - radius; y1 <= y + radius; y1++)
220+
{
221+
pos = y1 * width;
222+
wy = wei[abs(y1 - y)];
223+
224+
for (int x1 = x - radius; x1 <= x + radius; x1++)
225+
{
226+
c_wei = wei[abs(x1 - x)] * wy;
227+
pos2 = pos + x1;
228+
sum_r += im_r[pos2] * c_wei;
229+
sum_g += im_g[pos2] * c_wei;
230+
sum_b += im_b[pos2] * c_wei;
231+
num += c_wei;
232+
}
233+
}
234+
235+
num_f = 1.0f / (float)num;
236+
237+
c_r[c_pos] = sum_r * num_f;
238+
c_g[c_pos] = sum_g * num_f;
239+
c_b[c_pos] = sum_b * num_f;
240+
241+
c_pos++;
242+
}
243+
244+
cy += n_width;
245+
}
246+
247+
int p1, p2, p3, p4, yw, w1, w2, w3, w4, lx, ly, lx1, ly1, pos_iFT;
248+
float num_iFT;
249+
250+
int output_height = matrix.rows();
251+
int output_width = matrix.cols();
252+
253+
float *img_r = new float[output_height * output_width];
254+
float *img_g = new float[output_height * output_width];
255+
float *img_b = new float[output_height * output_width];
256+
257+
for (int y = 0; y < output_height; y++)
258+
{
259+
ly1 = (y % radius);
260+
ly = radius - ly1;
261+
yw = y / radius * n_width;
262+
pos_iFT = y * output_width;
263+
264+
for (int x = 0; x < output_width; x++)
265+
{
266+
lx1 = (x % radius);
267+
lx = radius - lx1;
268+
269+
p1 = x / radius + yw;
270+
p2 = p1 + 1;
271+
p3 = p1 + n_width;
272+
p4 = p3 + 1;
273+
274+
w1 = lx * ly;
275+
w2 = lx1 * ly;
276+
w3 = lx * ly1;
277+
w4 = lx1 * ly1;
278+
279+
num_iFT = 1.0f / (float)(w1 + w2 + w3 + w4);
280+
281+
img_r[pos_iFT] = (c_r[p1] * w1 + c_r[p2] * w2 + c_r[p3] * w3 + c_r[p4] * w4) * num_iFT;
282+
img_g[pos_iFT] = (c_g[p1] * w1 + c_g[p2] * w2 + c_g[p3] * w3 + c_g[p4] * w4) * num_iFT;
283+
img_b[pos_iFT] = (c_b[p1] * w1 + c_b[p2] * w2 + c_b[p3] * w3 + c_b[p4] * w4) * num_iFT;
284+
285+
pos_iFT++;
286+
}
287+
}
288+
289+
Mat compR(output_height, output_width, CV_32FC1, img_r);
290+
Mat compG(output_height, output_width, CV_32FC1, img_g);
291+
Mat compB(output_height, output_width, CV_32FC1, img_b);
292+
293+
std::vector<Mat> oComp;
294+
295+
oComp.push_back(compB);
296+
oComp.push_back(compG);
297+
oComp.push_back(compR);
298+
299+
merge(oComp, output);
300+
}
301+
46302
void ft::FT02D_components(InputArray matrix, InputArray kernel, OutputArray components, InputArray mask)
47303
{
48304
CV_Assert(matrix.channels() == kernel.channels() && mask.channels() == 1);

0 commit comments

Comments
 (0)