@@ -43,7 +43,7 @@ void ImageProximityFFT::PrepareFor(ImageBase& Source, Image& Template)
4343 size.Height = Source.Height ();
4444
4545 if (m_image_sqsums == nullptr || m_image_sqsums->Width () < size.Width || m_image_sqsums->Height () < size.Height )
46- m_image_sqsums = std::make_shared<TempImage>(*m_CL, size, SImage::F32, 1 );
46+ m_image_sqsums = std::make_shared<TempImage>(*m_CL, size, SImage::F32, Source. NbChannels () );
4747
4848
4949 // Size of the FFT input and output
@@ -81,62 +81,88 @@ void ImageProximityFFT::PrepareFor(ImageBase& Source, Image& Template)
8181 m_statistics.PrepareFor (Template);
8282 m_transform.PrepareFor (Source);
8383 m_fft.PrepareFor (*m_bigger_source, *m_source_spect);
84+ SelectProgram (Source).Build ();
85+ SelectProgram (*m_source_spect).Build ();
8486}
8587
86- void ImageProximityFFT::MatchTemplatePrepared_SQDIFF (int width, int hight, Image& Source, float templ_sqsum, Image& Dest)
88+ void ImageProximityFFT::MatchSquareDiff (int width, int hight, Image& Source, double * templ_sqsum, Image& Dest)
8789{
88- Check1Channel (Dest);
89- Kernel (matchTemplatePreparedSQDIFF, In (Source), Out (Dest), width, hight, templ_sqsum, Source.Step (), Dest.Step (), Dest.Width (), Dest.Height ());
90+ cl_float4 TemplateSqSum = {float (templ_sqsum[0 ]), float (templ_sqsum[1 ]), float (templ_sqsum[2 ]), float (templ_sqsum[3 ])};
91+
92+ Kernel (square_difference, In (Source), Out (Dest), Source.Step (), Dest.Width (), Dest.Height (), Dest.Step (),
93+ width, hight, TemplateSqSum);
9094}
9195
92- void ImageProximityFFT::MatchTemplatePrepared_SQDIFF_NORM (int width, int hight, Image& Source, float templ_sqsum, Image& Dest)
96+ void ImageProximityFFT::MatchSquareDiffNorm (int width, int hight, Image& Source, double * templ_sqsum, Image& Dest)
9397{
94- Check1Channel (Dest);
95- Kernel (matchTemplatePreparedSQDIFF_NORM, In (Source), Out (Dest), width, hight, templ_sqsum, Source.Step (), Dest.Step (), Dest.Width (), Dest.Height ());
98+ cl_float4 TemplateSqSum = {float (templ_sqsum[0 ]), float (templ_sqsum[1 ]), float (templ_sqsum[2 ]), float (templ_sqsum[3 ])};
99+
100+ Kernel (square_difference_norm, In (Source), Out (Dest), Source.Step (), Dest.Step (), Dest.Width (), Dest.Height (),
101+ width, hight, TemplateSqSum);
96102}
97103
98- void ImageProximityFFT::MatchTemplatePrepared_CCORR_NORM (int width, int hight, Image& Source, float templ_sqsum, Image& Dest)
104+ void ImageProximityFFT::MatchCrossCorrNorm (int width, int hight, Image& Source, double * templ_sqsum, Image& Dest)
99105{
100- Check1Channel (Dest);
101- Kernel (matchTemplatePreparedCCORR_NORM, In (Source), Out (Dest), width, hight, templ_sqsum, Source.Step (), Dest.Step (), Dest.Width (), Dest.Height ());
106+ cl_float4 TemplateSqSum = {float (templ_sqsum[0 ]), float (templ_sqsum[1 ]), float (templ_sqsum[2 ]), float (templ_sqsum[3 ])};
107+
108+ Kernel (crosscorr_norm, In (Source), Out (Dest), Source.Step (), Dest.Step (), Dest.Width (), Dest.Height (),
109+ width, hight, TemplateSqSum);
102110}
103111
104112void ImageProximityFFT::CrossCorr (Image& Source, Image& Template, Image& Dest)
105113{
106- CheckSameSize (Source, Dest);
107- Check1Channel (Source);
108- Check1Channel (Template);
109114 CheckFloat (Dest);
115+ CheckSameNbChannels (Source, Template);
116+ CheckSameNbChannels (Source, Dest);
117+ CheckSameSize (Source, Dest);
118+
119+ // Verify image size
120+ if (Template.Width () > Source.Width () || Template.Height () > Source.Height ())
121+ throw cl::Error (CL_IMAGE_FORMAT_NOT_SUPPORTED, " The template image must be smaller than source image." );
110122
123+ // Verify image types
111124 if (!SameType (Source, Template))
112125 throw cl::Error (CL_IMAGE_FORMAT_MISMATCH, " The source image and the template image must be same type." );
113126
114- Convolve (Source, Template, Dest);
127+ PrepareFor (Source, Template);
128+
129+ Convolve (Source, Template, Dest); // Computes the cross correlation using FFT
115130}
116131
117132void ImageProximityFFT::CrossCorr_Norm (Image& Source, Image& Template, Image& Dest)
118133{
119- CheckSameSize (Source, Dest);
120- Check1Channel (Source);
121- Check1Channel (Template);
122134 CheckFloat (Dest);
135+ CheckSameNbChannels (Source, Template);
136+ CheckSameNbChannels (Source, Dest);
137+ CheckSameSize (Source, Dest);
123138
139+ // Verify image size
140+ if (Template.Width () > Source.Width () || Template.Height () > Source.Height ())
141+ throw cl::Error (CL_IMAGE_FORMAT_NOT_SUPPORTED, " The template image must be smaller than source image." );
142+
143+ // Verify image types
124144 if (!SameType (Source, Template))
125145 throw cl::Error (CL_IMAGE_FORMAT_MISMATCH, " The source image and the template image must be same type." );
126146
127147 PrepareFor (Source, Template);
128148
129149 m_integral.SqrIntegral (Source, *m_image_sqsums);
130150
131- float templ_sqsum = static_cast <float >(m_statistics.SumSqr (Template));
151+ double templ_sqsum[4 ] = {0 };
152+ m_statistics.SumSqr (Template, templ_sqsum);
132153
133- Convolve (Source, Template, Dest);
154+ Convolve (Source, Template, Dest); // Computes the cross correlation using FFT
134155
135- MatchTemplatePrepared_CCORR_NORM (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
156+ MatchCrossCorrNorm (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
136157}
137158
138159void ImageProximityFFT::SqrDistance (Image& Source, Image& Template, Image& Dest)
139160{
161+ CheckFloat (Dest);
162+ CheckSameNbChannels (Source, Template);
163+ CheckSameNbChannels (Source, Dest);
164+ CheckSameSize (Source, Dest);
165+
140166 // Verify image size
141167 if (Template.Width () > Source.Width () || Template.Height () > Source.Height ())
142168 throw cl::Error (CL_IMAGE_FORMAT_NOT_SUPPORTED, " The template image must be smaller than source image." );
@@ -145,23 +171,25 @@ void ImageProximityFFT::SqrDistance(Image& Source, Image& Template, Image& Dest)
145171 if (!SameType (Source, Template))
146172 throw cl::Error (CL_IMAGE_FORMAT_MISMATCH, " The source image and the template image must be same type." );
147173
148- Check1Channel (Source);
149- Check1Channel (Template);
150- CheckFloat (Dest);
151-
152174 PrepareFor (Source, Template);
153175
154176 m_integral.SqrIntegral (Source, *m_image_sqsums);
155177
156- float templ_sqsum = static_cast <float >(m_statistics.SumSqr (Template));
178+ double templ_sqsum[4 ] = {0 };
179+ m_statistics.SumSqr (Template, templ_sqsum);
157180
158- CrossCorr (Source, Template, Dest);
181+ Convolve (Source, Template, Dest); // Computes the cross correlation using FFT
159182
160- MatchTemplatePrepared_SQDIFF (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
183+ MatchSquareDiff (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
161184}
162185
163186void ImageProximityFFT::SqrDistance_Norm (Image& Source, Image& Template, Image& Dest)
164187{
188+ CheckFloat (Dest);
189+ CheckSameNbChannels (Source, Template);
190+ CheckSameNbChannels (Source, Dest);
191+ CheckSameSize (Source, Dest);
192+
165193 // Verify image size
166194 if (Template.Width () > Source.Width () || Template.Height () > Source.Height ())
167195 throw cl::Error (CL_IMAGE_FORMAT_NOT_SUPPORTED, " The template image must be smaller than source image." );
@@ -170,18 +198,15 @@ void ImageProximityFFT::SqrDistance_Norm(Image& Source, Image& Template, Image&
170198 if (!SameType (Source, Template))
171199 throw cl::Error (CL_IMAGE_FORMAT_MISMATCH, " The source image and the template image must be same type." );
172200
173- Check1Channel (Source);
174- Check1Channel (Template);
175- CheckFloat (Dest);
176-
177201 PrepareFor (Source, Template);
178202
179203 m_integral.SqrIntegral (Source, *m_image_sqsums);
180204
181- float templ_sqsum = static_cast <float >(m_statistics.SumSqr (Template));
205+ double templ_sqsum[4 ] = {0 };
206+ m_statistics.SumSqr (Template, templ_sqsum);
182207
183208 CrossCorr (Source, Template, Dest);
184- MatchTemplatePrepared_SQDIFF_NORM (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
209+ MatchSquareDiffNorm (Template.Width (), Template.Height (), *m_image_sqsums, templ_sqsum, Dest);
185210}
186211
187212void ImageProximityFFT::MulAndScaleSpectrums (Image& Source, Image& Template, Image& Dest, float scale)
@@ -210,47 +235,52 @@ void ImageProximityFFT::Convolve(Image& Source, Image& Template, Image& Dest)
210235 m_transform.SetAll (*m_bigger_template, 0 );
211236 m_transform.SetAll (*m_bigger_source, 0 );
212237
213- // Copy the data from Source and Template in images that are F32 and are big enough
214- Kernel (copy_offset, In (Source), Out (*m_bigger_source), Source.Step (), m_bigger_source->Step (),
215- int (Template.Width ()) / 2 , int (Template.Height ()) / 2 , m_bigger_source->Width (), m_bigger_source->Height ());
238+ for (uint i = 1 ; i <= Source.NbChannels (); i++)
239+ {
240+ // Copy the data from Source and Template in images that are F32 and are big enough
241+ Kernel (copy_offset, In (Source), Out (*m_bigger_source), Source.Step (), m_bigger_source->Step (),
242+ int (Template.Width ()) / 2 , int (Template.Height ()) / 2 , m_bigger_source->Width (), m_bigger_source->Height (), i);
243+
244+ Kernel (copy_offset, In (Template), Out (*m_bigger_template), Template.Step (), m_bigger_template->Step (),
245+ 0 , 0 , m_bigger_template->Width (), m_bigger_template->Height (), i);
216246
217- Kernel (copy_offset, In (Template), Out (*m_bigger_template), Template.Step (), m_bigger_template->Step (),
218- 0 , 0 , m_bigger_template->Width (), m_bigger_template->Height ());
219247
248+ // Forward FFT of Source and Template
249+ m_fft.Forward (*m_bigger_source, *m_source_spect);
250+ m_fft.Forward (*m_bigger_template, *m_templ_spect);
220251
221- // Forward FFT of Source and Template
222- m_fft.Forward (*m_bigger_source, *m_source_spect);
223- m_fft.Forward (*m_bigger_template, *m_templ_spect);
224252
253+ // We need to divide the values by the FFT area to get the proper
254+ float Area = float (m_bigger_source->Width () * m_bigger_source->Height ());
225255
226- // We need to divide the values by the FFT area to get the proper
227- float Area = float (m_bigger_source->Width () * m_bigger_source->Height ());
256+ // Do the convolution using pointwise product of the spectrums
257+ // See information here : http://en.wikipedia.org/wiki/Convolution_theorem
258+ MulAndScaleSpectrums (*m_source_spect, *m_templ_spect, *m_result_spect, 1 / Area);
228259
229- // Do the convolution using pointwise product of the spectrums
230- // See information here : http://en.wikipedia.org/wiki/Convolution_theorem
231- MulAndScaleSpectrums (*m_source_spect, *m_templ_spect, *m_result_spect, 1 / Area);
232260
261+ // Inverse FFT to get the result of the convolution
262+ m_fft.Inverse (*m_result_spect, *m_bigger_source); // Reuse m_bigger_source image for the convolution result
233263
234- // Inverse FFT to get the result of the convolution
235- m_fft.Inverse (*m_result_spect, *m_bigger_source); // Reuse m_bigger_source image for the convolution result
236264
265+ // Copy the result to Dest
266+ Kernel_ (*m_CL, SelectProgram (Dest), copy_result, m_bigger_source->FullRange (), LOCAL_RANGE,
267+ In (*m_bigger_source), Out (Dest), m_bigger_source->Step (), Dest.Step (), Dest.Width (), Dest.Height (), i);
268+ }
237269
238- // Copy the result to Dest
239- Kernel (copy_roi, In ((*m_bigger_source)), Out (Dest), m_bigger_source->Step (), Dest.Step (), Dest.Width (), Dest.Height ());
240270}
241271
242272#else // USE_CLFFT
243273
244274void ImageProximityFFT::PrepareFor (ImageBase& , Image& )
245275{ }
246276
247- void ImageProximityFFT::MatchTemplatePrepared_SQDIFF (int , int , Image& , float , Image& )
277+ void ImageProximityFFT::MatchSquareDiff (int , int , Image& , float , Image& )
248278{ }
249279
250- void ImageProximityFFT::MatchTemplatePrepared_SQDIFF_NORM (int , int , Image& , float , Image& )
280+ void ImageProximityFFT::MatchSquareDiffNorm (int , int , Image& , float , Image& )
251281{ }
252282
253- void ImageProximityFFT::MatchTemplatePrepared_CCORR_NORM (int , int , Image& , float , Image& )
283+ void ImageProximityFFT::MatchCrossCorrNorm (int , int , Image& , float , Image& )
254284{ }
255285
256286void ImageProximityFFT::CrossCorr (Image& , Image& , Image& )
0 commit comments