void ImageProximityFFT::MulAndScaleSpectrums(Image& Source, Image& Template, Image& Dest, float scale) { CheckSameSize(Source, Template); CheckSameSize(Source, Dest); // Verify image types if (Source.DataType() != SImage::F32 || Template.DataType() != SImage::F32 || Dest.DataType() != SImage::F32) throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "The function works only with F32 images"); // Verify image types if (Source.NbChannels() != 2 || Template.NbChannels() != 2 || Dest.NbChannels() != 2) throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "The function works only with 2 channel images"); Kernel(mulAndScaleSpectrums, Source, Template, Dest, Source.Step(), Template.Step(), Dest.Step(), Source.Width(), Source.Height(), scale); }
void Integral::IntegralScan(IImage& Source, IImage& Dest) { PrepareFor(Source); CheckSameSize(Source, Dest); CheckFloat(Dest); uint Width = Source.Width(); uint Height = Source.Height(); Kernel(scan1, Source, Dest, Width, Height); if (GetNbGroupsW(Source) > 1) { make_kernel<Image2D, Image2D>(SelectProgram(Dest), "scan2") (EnqueueArgs(*m_CL, NDRange(GetNbGroupsW(Source) - 1, Source.Height())), Dest, *m_VerticalJunctions); } #undef KERNEL_RANGE #define KERNEL_RANGE(src_img) src_img.FullRange() Kernel(scan3, In(Dest, *m_VerticalJunctions), Dest); if (GetNbGroupsH(Source) > 1) { make_kernel<Image2D, Image2D>(SelectProgram(Dest), "scan4") (EnqueueArgs(*m_CL, NDRange(Source.Width(), GetNbGroupsH(Source) - 1)), Dest, *m_HorizontalJunctions); } Kernel(scan5, In(Dest, *m_HorizontalJunctions), Dest); }
void ImageProximityFFT::SqrDistance_Norm(Image& Source, Image& Template, Image& Dest) { CheckFloat(Dest); CheckSameNbChannels(Source, Template); CheckSameNbChannels(Source, Dest); CheckSameSize(Source, Dest); // Verify image size if (Template.Width() > Source.Width() || Template.Height() > Source.Height()) throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "The template image must be smaller than source image."); // Verify image types if(!SameType(Source, Template)) throw cl::Error(CL_IMAGE_FORMAT_MISMATCH, "The source image and the template image must be same type."); PrepareFor(Source, Template); m_integral.SqrIntegral(Source, *m_image_sqsums); double templ_sqsum[4] = {0}; m_statistics.SumSqr(Template, templ_sqsum); CrossCorr(Source, Template, Dest); MatchSquareDiffNorm(Template.Width(), Template.Height(), *m_image_sqsums, templ_sqsum, Dest); }
void Blob::ComputeLabels(IImage& Source, ImageBuffer& Labels, int ConnectType) { if (ConnectType != 4 && ConnectType != 8) throw cl::Error(CL_INVALID_VALUE, "Wrong connect type in Blob::ComputeLabels"); if (Labels.Depth() != 32 || Labels.IsFloat()) throw cl::Error(CL_INVALID_VALUE, "Wrong Labels image type in Blob::ComputeLabels - Labels must be 32 bit integer"); if (m_TempBuffer == nullptr) PrepareFor(Source); CheckSameSize(Source, Labels); CheckCompatibility(Labels, *m_TempBuffer); m_BlobInfo.Init(ConnectType); m_InfoBuffer.Send(); // Initialize the label image Kernel(init_label, Source, Out(Labels, *m_TempBuffer), Labels.Step(), m_TempBuffer->Step(), m_InfoBuffer); // These two labeling steps need to be executed at least twice each int i = 0; while (i <= m_BlobInfo.LastUsefulIteration) { i++; Kernel(label_step1, Labels, *m_TempBuffer, Labels.Step(), m_TempBuffer->Step(), m_InfoBuffer, i); Kernel(label_step2, Labels, *m_TempBuffer, Labels.Step(), m_TempBuffer->Step(), m_InfoBuffer, i); if (i >= 2) m_InfoBuffer.Read(true); } }
void CheckCompatibility(const ImageBase& Img1, const ImageBase& Img2) { CheckSameSize(Img1, Img2); if (Img1.IsFloat() != Img2.IsFloat()) throw cl::Error(CL_INVALID_VALUE, "Different image types used"); if (Img1.IsUnsigned() != Img2.IsUnsigned()) throw cl::Error(CL_INVALID_VALUE, "Different image types used"); }
void ImageProximityFFT::Convolve(Image& Source, Image& Template, Image& Dest) { CheckSameSize(Source, Dest); PrepareFor(Source, Template); // Fill these images with black m_transform.SetAll(*m_bigger_template, 0); m_transform.SetAll(*m_bigger_source, 0); for (uint i = 1; i <= Source.NbChannels(); i++) { // Copy the data from Source and Template in images that are F32 and are big enough Kernel(copy_offset, In(Source), Out(*m_bigger_source), Source.Step(), m_bigger_source->Step(), int(Template.Width()) / 2, int(Template.Height()) / 2, m_bigger_source->Width(), m_bigger_source->Height(), i); Kernel(copy_offset, In(Template), Out(*m_bigger_template), Template.Step(), m_bigger_template->Step(), 0, 0, m_bigger_template->Width(), m_bigger_template->Height(), i); // Forward FFT of Source and Template m_fft.Forward(*m_bigger_source, *m_source_spect); m_fft.Forward(*m_bigger_template, *m_templ_spect); // We need to divide the values by the FFT area to get the proper float Area = float(m_bigger_source->Width() * m_bigger_source->Height()); // Do the convolution using pointwise product of the spectrums // See information here : http://en.wikipedia.org/wiki/Convolution_theorem MulAndScaleSpectrums(*m_source_spect, *m_templ_spect, *m_result_spect, 1 / Area); // Inverse FFT to get the result of the convolution m_fft.Inverse(*m_result_spect, *m_bigger_source); // Reuse m_bigger_source image for the convolution result // Copy the result to Dest Kernel_(*m_CL, SelectProgram(Dest), copy_result, m_bigger_source->FullRange(), LOCAL_RANGE, In(*m_bigger_source), Out(Dest), m_bigger_source->Step(), Dest.Step(), Dest.Width(), Dest.Height(), i); } }
void ImageProximityFFT::CrossCorr(Image& Source, Image& Template, Image& Dest) { CheckFloat(Dest); CheckSameNbChannels(Source, Template); CheckSameNbChannels(Source, Dest); CheckSameSize(Source, Dest); // Verify image size if (Template.Width() > Source.Width() || Template.Height() > Source.Height()) throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "The template image must be smaller than source image."); // Verify image types if(!SameType(Source, Template)) throw cl::Error(CL_IMAGE_FORMAT_MISMATCH, "The source image and the template image must be same type."); PrepareFor(Source, Template); Convolve(Source, Template, Dest); // Computes the cross correlation using FFT }
void Conversions::Convert(Image& Source, Image& Dest) { CheckSameSize(Source, Dest); if (SameType(Source, Dest)) { Copy(Source, Dest); return; } switch (Dest.DataType()) { case SImage::U8: Kernel(to_uchar, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::S8: Kernel(to_char, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::U16: Kernel(to_ushort, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::S16: Kernel(to_short, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::U32: Kernel(to_uint, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::S32: Kernel(to_int, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::F32: Kernel(to_float, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::F64: Kernel(to_double, Source, Dest, Source.Step(), Dest.Step()); break; case SImage::NbDataTypes: default: throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "Unsupported data type"); } }
void Conversions::Scale(Image& Source, Image& Dest) { CheckSameSize(Source, Dest); double SrcRange = GetTypeRange(Source); double DstRange = GetTypeRange(Dest); double SrcMin = GetTypeMin(Source); double DstMin = GetTypeMin(Dest); if (SrcRange == DstRange && SrcMin == DstMin) { Convert(Source, Dest); return; } float Ratio = static_cast<float>(DstRange / SrcRange); int Offset = static_cast<int>(-SrcMin * Ratio + DstMin); Scale(Source, Dest, Offset, Ratio); }
void Conversions::Scale(Image& Source, Image& Dest, int Offset, float Ratio) { CheckSameSize(Source, Dest); switch (Dest.DataType()) { case SImage::U8: Kernel(scale_to_uchar, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::S8: Kernel(scale_to_char, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::U16: Kernel(scale_to_ushort, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::S16: Kernel(scale_to_short, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::U32: Kernel(scale_to_uint, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::S32: Kernel(scale_to_int, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::F32: Kernel(scale_to_float, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::F64: Kernel(scale_to_double, Source, Dest, Source.Step(), Dest.Step(), Offset, Ratio); break; case SImage::NbDataTypes: default: throw cl::Error(CL_IMAGE_FORMAT_NOT_SUPPORTED, "Unsupported data type"); } }