/// <summary>
        /// Does non-maxima supression for the following gray image. Can be useful for detections filtering (e.g. post-processing output from Harris detector).
        /// </summary>
        /// <typeparam name="TDepth">Channel type.</typeparam>
        /// <param name="img">Image.</param>
        /// <param name="dest">Destination image. Must have the same size as source image.</param>
        /// <param name="radius">Non-maxima supression radius (kernel radius).</param>
        /// <param name="discardValue">The value will be discarded (0 - for black).</param>
        public static void SupressNonMaxima <TDepth>(this Image <Gray, TDepth> img, Image <Gray, TDepth> dest, int radius = 3, int discardValue = 0)
            where TDepth : struct
        {
            SupressNonMaximaFunc supressNonMaximaFunc = null;

            if (supressNonMaximaFuncs.TryGetValue(img.ColorInfo.ChannelType, out supressNonMaximaFunc) == false)
            {
                throw new NotSupportedException(string.Format("Can not perform non-maxima suppression on an image of type {0}", img.ColorInfo.ChannelType.Name));
            }

            var proc = new ParallelProcessor <IImage, bool>(img.Size,
                                                            () => true,
                                                            (_src, _, area) =>
            {
                Rectangle srcArea = new Rectangle
                {
                    X      = 0,
                    Y      = area.Y,
                    Width  = _src.Width,
                    Height = area.Height + 2 * radius
                };
                srcArea.Intersect(new Rectangle(new Point(), img.Size));

                supressNonMaximaFunc(img.GetSubRect(srcArea), dest.GetSubRect(srcArea), radius, discardValue);
            },
                                                            new ParallelOptions2D { /*ForceSequential = true*/
            });

            proc.Process(img);
        }
        public static ParallelProcessor <T[, ], T[, ]> GetProcessor <T>(this T[,] field, Func <T, T> processFunc, bool forceSequential = false)
        {
            var fieldSize = new Size(field.GetLength(1), field.GetLength(0));

            ParallelProcessor <T[, ], T[, ]> proc = new ParallelProcessor <T[, ], T[, ]>
                                                    (
                fieldSize,
                () =>
                new T[fieldSize.Height, fieldSize.Width],

                (inputArray, outputArray, patch) =>
            {
                for (int y = patch.Top; y < patch.Bottom; y++)
                {
                    for (int x = patch.Left; x < patch.Right; x++)
                    {
                        outputArray[y, x] = processFunc(inputArray[y, x]);
                    }
                }
            },

                new ParallelOptions2D {
                ForceSequential = forceSequential
            }
                                                    );

            return(proc);
        }
        internal static void SetValue <TColor, TDepth>(this Image <TColor, TDepth> img, TDepth[] valueArr)
            where TColor : IColor
            where TDepth : struct
        {
            if (valueArr.Length > img.ColorInfo.NumberOfChannels)
            {
                throw new Exception("Value array length must be the same as number of channels (or less)!");
            }

            Type depthType = img.ColorInfo.ChannelType;

            SetValueFunc valueSetter = null;

            if (valueSetters.TryGetValue(typeof(TDepth), out valueSetter) == false)
            {
                throw new Exception(string.Format("Setter function can not split image of color depth type {0}", depthType));
            }

            ParallelProcessor <IImage, bool> proc = new ParallelProcessor <IImage, bool>(img.Size,
                                                                                         () =>    //called once
            {
                return(true);
            },

                                                                                         (IImage srcImg, bool dummy, Rectangle area) =>    //called for every thread
            {
                valueSetter(srcImg.GetSubRect(area), valueArr);
            }
                                                                                         /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(img); //result is in srcImg
        }
        /// <summary>
        /// Copies values from source to destination image using mask. Destination values where mask == 0 are not erased!.
        /// </summary>
        /// <param name="img">Image.</param>
        /// <param name="destImg">Destination image</param>
        /// <param name="mask">Mask. Color locations that need to be copied must be set to !=0 in mask.</param>
        public static void CopyTo(this IImage img, IImage destImg, Image <Gray, byte> mask)
        {
            if (img.Size != mask.Size || img.Size != destImg.Size)
            {
                throw new Exception("Image, mask, destImg size must be the same!");
            }

            if (img.ColorInfo.Equals(destImg.ColorInfo, ColorInfo.ComparableParts.Castable) == false)
            {
                throw new Exception("Image and dest image must be castable (the same number of channels, the same channel type)!");
            }

            Type depthType = img.ColorInfo.ChannelType;

            ConditionalCopyFunc conditionalCopyFunc = null;

            if (conditionalCopyFuncs.TryGetValue(depthType, out conditionalCopyFunc) == false)
            {
                throw new Exception(string.Format("Conditional copy function of color depth type {0}", depthType));
            }

            ParallelProcessor <IImage, IImage> proc = new ParallelProcessor <IImage, IImage>(img.Size,
                                                                                             () => //called once
            {
                return(destImg);
            },

                                                                                             (IImage srcImg, IImage dstImg, Rectangle area) => //called for every thread
            {
                conditionalCopyFunc(srcImg.GetSubRect(area), dstImg.GetSubRect(area), mask.GetSubRect(area));
            }
                                                                                             /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(img); //result is in destImg
        }
        public async Task ParallelProcessing()
        {
            var count      = 500_000;
            var shouldFind = count / 2;
            var strings    = new string[count];

            for (var i = 0; i < count; i++)
            {
                if (i % 2 == 0)
                {
                    strings[i] = "Some text here and This is the pattern I want to find! and some text here";
                    continue;
                }

                strings[i] = "Some text here but not the pattern I am looking for!";
            }


            var parallelStopwatch = new Stopwatch();

            parallelStopwatch.Start();

            var processor      = new ParallelProcessor <string, string>(strings, IndexOfSomeString);
            var parallelResult = await processor.Process();

            var parallelFoundEntries = parallelResult.Count(s => !string.IsNullOrWhiteSpace(s));

            parallelStopwatch.Stop();
            Debug.WriteLine($"Parallel time ms: {parallelStopwatch.ElapsedMilliseconds}");

            Assert.Equal(shouldFind, parallelFoundEntries);
        }
        private static void calculate(IImage src, IImage dest, Image <Gray, byte> mask = null)
        {
            if (mask == null)
            {
                mask = new Image <Gray, byte>(dest.Width, dest.Height);
                mask.SetValue(new Gray(255));
            }

            NotFunc mathOpFunc = null;

            if (notFuncs.TryGetValue(src.ColorInfo.ChannelType, out mathOpFunc) == false)
            {
                throw new Exception(string.Format("Bitwise NOT can not be executed on an image of type {0}", src.ColorInfo.ChannelType));
            }

            var proc = new ParallelProcessor <bool, bool>(dest.Size,
                                                          () =>
            {
                return(true);
            },
                                                          (bool _, bool __, Rectangle area) =>
            {
                var srcPatch  = src.GetSubRect(area);
                var destPatch = dest.GetSubRect(area);
                var maskPatch = mask.GetSubRect(area);

                mathOpFunc(srcPatch, destPatch, maskPatch);
            }
                                                          /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(true);
        }
Beispiel #7
0
        private static IImage max(IImage imageA, IImage imageB, bool inPlace)
        {
            Type channelType = imageA.ColorInfo.ChannelType;

            MaxFunc maxFunc = null;

            if (maxFuncs.TryGetValue(channelType, out maxFunc) == false)
            {
                throw new NotSupportedException(string.Format("Can not calculate max from a image of type {0}", channelType));
            }

            var proc = new ParallelProcessor <bool, IImage>(imageA.Size,
                                                            () =>
            {
                if (!inPlace)
                {
                    return(Image.Create(imageA.ColorInfo, imageA.Width, imageA.Height));
                }
                else
                {
                    return(imageA);
                }
            },
                                                            (bool _, IImage dest, Rectangle area) =>
            {
                maxFunc(imageA.GetSubRect(area), imageB.GetSubRect(area), dest.GetSubRect(area));
            }
                                                            /*, new ParallelOptions { ForceSequential = true }*/);

            return(proc.Process(true));
        }
Beispiel #8
0
        protected virtual void AfterBind()
        {
            if (UseParallelSystemComponentsProcessing())
            {
#if UNITY_EDITOR
                sampler = UnityEngine.Profiling.CustomSampler.Create(SystemName);
#endif
                parallelSystemComponentProcessor = new ParallelProcessor(ProcessAtIndex);
            }
        }
Beispiel #9
0
        public void Parallel4KImageProcessingTest()
        {
            var url1 = @"../../TestData/4k/4k-TD1.jpg";
            var url2 = @"../../TestData/4k/4k-TD2.jpg";
            var parallelProcessor = new ParallelProcessor(url1, url2);
            var sw = new Stopwatch();

            sw.Start();
            parallelProcessor.Process();
            sw.Stop();
            var t = sw.ElapsedMilliseconds;

            TestContext.WriteLine($"Parallel Processor Elapsed Time(4K): {t.ToString()}ms");
        }
        /// <summary>
        /// Searches the image for the good features to track.
        /// <para>For each location a Hessian matrix is made and min eig-value is compared against threshold.</para>
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="winSize">Window size.</param>
        /// <param name="minEigVal">Minimum eigen value.</param>
        /// <param name="minimalDistance">Minimum distance from two features.</param>
        /// <returns>List of locations that have eigen value larger than <paramref name="minEigVal"/>.</returns>
        public static List <Point> GoodFeaturesToTrack(this Image <Gray, float> image, int winSize = 10, float minEigVal = 0.3f, float minimalDistance = 3)
        {
            var strengthImg = new Image <Gray, float>(image.Size);

            var Dx = image.Sobel(1, 0, 3);
            var Dy = image.Sobel(0, 1, 3);

            var Dxx = Dx.Mul(Dx).MakeIntegral();
            var Dxy = Dx.Mul(Dy).MakeIntegral();
            var Dyy = Dy.Mul(Dy).MakeIntegral();

            var proc = new ParallelProcessor <bool, bool>(image.Size,
                                                          () => true,
                                                          (_, __, area) =>
            {
                Rectangle srcArea = new Rectangle
                {
                    X      = 0,
                    Y      = area.Y,
                    Width  = image.Width,
                    Height = area.Height + winSize
                };
                srcArea.Intersect(new Rectangle(new Point(), image.Size));

                goodFeaturesToTrack(Dxx.GetSubRect(srcArea), Dxy.GetSubRect(srcArea), Dyy.GetSubRect(area),
                                    winSize, minEigVal, strengthImg.GetSubRect(srcArea));
            },
                                                          new ParallelOptions2D { /*ForceSequential = true*/
            },
                                                          winSize);

            proc.Process(true);


            var filteredStrengthImg = strengthImg.SupressNonMaxima();
            //var filteredStrengthImg = strengthImg;

            List <float> values;
            var          locations = filteredStrengthImg.FindNonZero(out values);

            var sortedFeatures = locations.Zip(values, (f, s) => new { f, s })
                                 .OrderByDescending(x => x.s)
                                 .Select(x => x.f)
                                 .ToList();

            sortedFeatures = sortedFeatures.EnforceMinimalDistance(minimalDistance);

            return(sortedFeatures);
        }
        /// <summary>
        /// Searches the image for the good features to track. 
        /// <para>For each location a Hessian matrix is made and min eig-value is compared against threshold.</para>
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="winSize">Window size.</param>
        /// <param name="minEigVal">Minimum eigen value.</param>
        /// <param name="minimalDistance">Minimum distance from two features.</param>
        /// <returns>List of locations that have eigen value larger than <paramref name="minEigVal"/>.</returns>
        public static List<Point> GoodFeaturesToTrack(this Image<Gray, float> image, int winSize = 10, float minEigVal = 0.3f, float minimalDistance = 3)
        {
            var strengthImg = new Image<Gray, float>(image.Size);

            var Dx = image.Sobel(1, 0, 3);
            var Dy = image.Sobel(0, 1, 3);

            var Dxx = Dx.Mul(Dx).MakeIntegral();
            var Dxy = Dx.Mul(Dy).MakeIntegral();
            var Dyy = Dy.Mul(Dy).MakeIntegral();

            var proc = new ParallelProcessor<bool, bool>(image.Size,
                                                         () => true,
                                                         (_, __, area) =>
                                                         {
                                                             Rectangle srcArea = new Rectangle
                                                             {
                                                                 X = 0,
                                                                 Y = area.Y,
                                                                 Width = image.Width,
                                                                 Height = area.Height + winSize
                                                             };
                                                             srcArea.Intersect(new Rectangle(new Point(), image.Size));

                                                             goodFeaturesToTrack(Dxx.GetSubRect(srcArea), Dxy.GetSubRect(srcArea), Dyy.GetSubRect(area),
                                                                                 winSize, minEigVal, strengthImg.GetSubRect(srcArea));
                                                         },
                                                         new ParallelOptions2D {  /*ForceSequential = true*/ },
                                                         winSize);

            proc.Process(true);

            var filteredStrengthImg = strengthImg.SupressNonMaxima();
            //var filteredStrengthImg = strengthImg;

            List<float> values;
            var locations = filteredStrengthImg.FindNonZero(out values);

            var sortedFeatures = locations.Zip(values, (f, s) => new { f, s })
                                          .OrderByDescending(x => x.s)
                                          .Select(x => x.f)
                                          .ToList();

            sortedFeatures = sortedFeatures.EnforceMinimalDistance(minimalDistance);

            return sortedFeatures;
        }
Beispiel #12
0
        internal static IImage[] SplitChannels(IImage img, params int[] channelIndicies)
        {
            if (channelIndicies == null || channelIndicies.Length == 0)
            {
                channelIndicies = Enumerable.Range(0, img.ColorInfo.NumberOfChannels).ToArray();
            }

            Type      depthType   = img.ColorInfo.ChannelType;
            ColorInfo channelType = ColorInfo.GetInfo(typeof(Gray), depthType);

            SplitImage splitter = null;

            if (splitters.TryGetValue(depthType, out splitter) == false)
            {
                throw new Exception(string.Format("Splitting function can not split image of color depth type {0}", depthType));
            }

            ParallelProcessor <IImage, IImage[]> proc = new ParallelProcessor <IImage, IImage[]>(img.Size,
                                                                                                 () => //called once
            {
                IImage[] channels = new IImage[channelIndicies.Length];
                for (int i = 0; i < channels.Length; i++)
                {
                    channels[i] = Image.Create(channelType, img.Width, img.Height);
                }

                return(channels);
            },

                                                                                                 (IImage src, IImage[] dest, Rectangle area) => //called for every thread
            {
                IImage srcPatch    = src.GetSubRect(area);
                IImage[] destPatch = new IImage[dest.Length];

                for (int i = 0; i < dest.Length; i++)
                {
                    destPatch[i] = dest[i].GetSubRect(area);
                }

                splitter(srcPatch, destPatch, channelIndicies);
            }
                                                                                                 /*,new ParallelOptions { ForceSequential = true}*/);

            return(proc.Process(img));
        }
        internal static Image <Gray, byte> InRange <TColor, TDepth>(this Image <TColor, TDepth> img, TDepth[] minArr, TDepth[] maxArr, byte valueToSet = 255, params int[] channelIndicies)
            where TColor : IColor
            where TDepth : struct
        {
            Type depthType = img.ColorInfo.ChannelType;

            InRangeFunc inRangeFilter = null;

            if (inRangeFilters.TryGetValue(typeof(TDepth), out inRangeFilter) == false)
            {
                throw new Exception(string.Format("InRange function can not process image of color depth type {0}", depthType));
            }

            if (channelIndicies == null || channelIndicies.Length == 0)
            {
                channelIndicies = Enumerable.Range(0, ColorInfo.GetInfo <TColor, TDepth>().NumberOfChannels).ToArray();
            }

            if (channelIndicies.Length > img.ColorInfo.NumberOfChannels)
            {
                throw new Exception("Number of processed channels must not exceed the number of available image channels!");
            }

            ParallelProcessor <IImage, Image <Gray, byte> > proc = new ParallelProcessor <IImage, Image <Gray, byte> >(img.Size,
                                                                                                                       () => //called once
            {
                var destImg = new Image <Gray, byte>(img.Width, img.Height);
                destImg.SetValue(new Gray(255));                                                                              //initialize destination mask.
                return(destImg);
            },

                                                                                                                       (IImage srcImg, Image <Gray, byte> dstImg, Rectangle area) => //called for every thread
            {
                var srcPatch  = srcImg.GetSubRect(area);
                var destPatch = dstImg.GetSubRect(area);
                inRangeFilter(srcPatch, minArr, maxArr, channelIndicies, destPatch, valueToSet);
            }
                                                                                                                       /*,new ParallelOptions { ForceSequential = true}*/);

            var dest = proc.Process(img);

            return(dest as Image <Gray, byte>);
        }
Beispiel #14
0
        internal override void Compute(IImage image)
        {
            Reset();

            RawMomentsFunc rawMomentsFunc = null;

            if (rawMomentsFuncs.TryGetValue(image.ColorInfo.ChannelType, out rawMomentsFunc) == false)
            {
                throw new Exception(string.Format("Raw moments can not be calculated of an image of type {0}", image.ColorInfo.ChannelType));
            }

            object sync = new object();
            ParallelProcessor <IImage, bool> proc = new ParallelProcessor <IImage, bool>(image.Size,
                                                                                         () =>
            {
                return(true);
            },
                                                                                         (IImage src, bool _, Rectangle area) => //called for every thread
            {
                IntPoint offset = new IntPoint(area.X, area.Y);

                float m00, m01, m10, m11, m02, m20, m12, m21, m30, m03;
                rawMomentsFunc(src.GetSubRect(area), offset, Order,
                               out m00, out m01, out m10,
                               out m11, out m02, out m20,
                               out m12, out m21, out m30, out m03);

                lock (sync)
                {
                    this.M00 += m00; this.M01 += m01; this.M10 += m10;
                    this.M11 += m11; this.M02 += m02; this.M20 += m20;
                    this.M12 += m12; this.M21 += m21; this.M30 += m30; this.M03 += m03;
                }
            }
                                                                                         /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(image);

            InvM00  = 1f / M00;
            CenterX = M10 * InvM00;
            CenterY = M01 * InvM00;
        }
        /// <summary>
        /// Converts an image by using specified conversion path.
        /// </summary>
        /// <param name="img">Image to convert.</param>
        /// <param name="conversionData">Conversion path.</param>
        /// <returns>Converted image.</returns>
        public static IImage Convert(this IImage img, ConversionData <ColorInfo> conversionData)
        {
            var proc = new ParallelProcessor <IImage, IImage>
                       (
                img.Size,
                () => conversionData.CreateFunc(img, conversionData.Destination),
                (src, dest, area) => conversionData.ConvertFunc(src.GetSubRect(area), dest.GetSubRect(area))
#if DEBUG
                , new ParallelOptions2D {
                ForceSequential = true
            }
#else
                , new ParallelOptions2D {
                ForceSequential = conversionData.ForceSequential
            }
#endif
                       );

            return(proc.Process(img));
        }
Beispiel #16
0
        internal static void MergeChannels(IImage[] channels, IImage destImg, params int[] destChannelIndicies)
        {
            if (destChannelIndicies == null || destChannelIndicies.Length == 0)
            {
                destChannelIndicies = Enumerable.Range(0, channels.Length).ToArray();
            }

            Type depthType = destImg.ColorInfo.ChannelType;

            MergeImage merger = null;

            if (mergers.TryGetValue(depthType, out merger) == false)
            {
                throw new Exception(string.Format("Merge function can not merge image of color depth type {0}", depthType));
            }

            ParallelProcessor <IImage[], IImage> proc = new ParallelProcessor <IImage[], IImage>(destImg.Size,
                                                                                                 () => //called once
            {
                return(destImg);
            },

                                                                                                 (IImage[] _channels, IImage _destImg, Rectangle area) => //called for every thread
            {
                IImage[] channelsPatches = new IImage[_channels.Length];

                for (int i = 0; i < channelsPatches.Length; i++)
                {
                    channelsPatches[i] = _channels[i].GetSubRect(area);
                }

                IImage imgPatch = _destImg.GetSubRect(area);

                merger(channelsPatches, imgPatch, destChannelIndicies);
            }
                                                                                                 /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(channels); //result is in srcImg
        }
        /// <summary>
        /// Find non-zero locations in the image.
        /// </summary>
        /// <typeparam name="TDepth">Channel type.</typeparam>
        /// <param name="img">Image.</param>
        /// <param name="values">Values for the found locations.</param>
        /// <returns>List of found non-zero locations.</returns>
        public static List <Point> FindNonZero <TDepth>(this Image <Gray, TDepth> img, out List <TDepth> values)
            where TDepth : struct
        {
            FindNonZeroFunc findNonZeroFunc = null;

            if (findNonZeroFuncs.TryGetValue(img.ColorInfo.ChannelType, out findNonZeroFunc) == false)
            {
                throw new NotSupportedException(string.Format("Can not perform FindNonZero on an image of type {0}", img.ColorInfo.ChannelType.Name));
            }

            var locations = new List <Point>();
            var _values   = new List <TDepth>();

            var proc = new ParallelProcessor <IImage, bool>(img.Size,
                                                            () => true,
                                                            (_src, _, area) =>
            {
                List <Point> locationsPatch;
                IList valuesPatch;
                findNonZeroFunc(img.GetSubRect(area), out locationsPatch, out valuesPatch);

                lock (locations)
                    lock (_values)
                    {
                        locationsPatch.ForEach(x =>
                        {
                            locations.Add(x + area.Location);
                        });

                        _values.AddRange(valuesPatch  as IList <TDepth>);
                    }
            });

            proc.Process(img);

            values = _values;
            return(locations);
        }
Beispiel #18
0
        private static void calculate(MathOps mathOpIdx, IImage src1, IImage src2, IImage dest, Image <Gray, byte> mask = null)
        {
            Debug.Assert(src1.ColorInfo.Equals(src2.ColorInfo) && src1.Size.Equals(src2.Size));

            if (mask == null)
            {
                mask = new Image <Gray, byte>(dest.Width, dest.Height);
                mask.SetValue(new Gray(255));
            }

            var mathOperationOnTypes = mathOperatorFuncs[(int)mathOpIdx];

            MathOpFunc mathOpFunc = null;

            if (mathOperationOnTypes.TryGetValue(src1.ColorInfo.ChannelType, out mathOpFunc) == false)
            {
                throw new Exception(string.Format("Math operation {0} can not be executed on an image of type {1}", mathOpIdx.ToString(), src1.ColorInfo.ChannelType));
            }

            var proc = new ParallelProcessor <bool, bool>(dest.Size,
                                                          () =>
            {
                return(true);
            },
                                                          (bool _, bool __, Rectangle area) =>
            {
                var src1Patch = src1.GetSubRect(area);
                var src2Patch = src2.GetSubRect(area);
                var destPatch = dest.GetSubRect(area);
                var maskPatch = mask.GetSubRect(area);

                mathOpFunc(src1Patch, src2Patch, destPatch, maskPatch);
            }
                                                          /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(true);
        }
Beispiel #19
0
        internal static IImage Convolve(IImage src, IImage kernel, ConvolutionBorder options)
        {
            ConvolutionFunc convolutionFunc = null;

            if (convolutionFuncs.TryGetValue(src.ColorInfo.ChannelType, out convolutionFunc) == false)
            {
                throw new NotSupportedException(string.Format("Can not perform spatial convolution on an image of type {0}", src.ColorInfo.ChannelType.Name));
            }

            Rectangle validRegion;
            var       preparedSrc = prepareSourceImage(src, kernel.Size, options, out validRegion);

            var proc = new ParallelProcessor <IImage, IImage>(src.Size,
                                                              () => preparedSrc.CopyBlank(), //in-place convolution is not supported due to parallel processing (junction patches handling)
                                                              (_src, _dest, area) =>
            {
                Rectangle srcArea = new Rectangle
                {
                    X      = 0,
                    Y      = area.Y,
                    Width  = _src.Width,
                    Height = area.Height + kernel.Height                                     //get area sufficient to process with the selected kernel; area.Height is processed
                };
                //srcArea.Inflate(-kernel.Width , -kernel.Height );
                srcArea.Width  -= kernel.Width;
                srcArea.Height -= kernel.Height;

                srcArea.Intersect(new Rectangle(new Point(), _src.Size));

                convolutionFunc(_src, srcArea, _dest, new Point(kernel.Width / 2, area.Y + kernel.Height / 2), kernel);
            }
                                                              /*,new ParallelOptions2D { ForceSequential = true }*/);

            var dest = proc.Process(preparedSrc);

            return(dest.GetSubRect(validRegion));
        }
Beispiel #20
0
        private Image <Gray, TDepth> BackProject <TDepth>(Image <Gray, TDepth>[] srcs)
            where TDepth : struct
        {
            var destColor = ColorInfo.GetInfo <Gray, TDepth>();

            BackpropagateFunc backpropagateFunc = null;

            if (backpropagateFuncs.TryGetValue(destColor.ChannelType, out backpropagateFunc) == false)
            {
                throw new Exception(string.Format("Back-propagate function does not support an image of type {0}", destColor.ChannelType));
            }

            var imgSize = srcs[0].Size;

            var proc = new ParallelProcessor <IImage[], IImage>(imgSize,
                                                                () => //executed once
            {
                return(Image.Create(destColor, imgSize.Width, imgSize.Height));
            },

                                                                (IImage[] srcImgs, IImage destImg, Rectangle area) => //executed for each thread
            {
                var channelPatches = new IImage[srcImgs.Length];
                for (int i = 0; i < channelPatches.Length; i++)
                {
                    channelPatches[i] = srcImgs[i].GetSubRect(area);
                }

                var projPatch = destImg.GetSubRect(area);

                backpropagateFunc(this, channelPatches, projPatch);
            }
                                                                /*,new ParallelOptions { ForceSequential = true}*/);

            return(proc.Process(srcs) as Image <Gray, TDepth>);
        }
        /// <summary>
        /// Two dimensional Fast Fourier Transform.
        /// </summary>
        /// <param name="width">Image width.</param> 
        /// <param name="height">Image height.</param>
        /// <param name="stride">Image stride.</param>
        /// <param name="data">Data to transform.</param>
        /// <param name="direction">Transformation direction.</param>
        /// 
        /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size
        /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array
        /// is valid, but 15x15 is not.</note></para></remarks>
        /// 
        /// <exception cref="ArgumentException">Incorrect data length.</exception>
        /// 
        public static unsafe void FFT2(ComplexF* data, int width, int height, int stride, Direction direction)
        {
            const int MIN_PATCH_SIZE = 32; //how much rows/columns should one thread process

            int k = height;
            int n = width;

            // check data size
            if (
                    (!AForge.Math.Tools.IsPowerOf2(k)) ||
                    (!AForge.Math.Tools.IsPowerOf2(n)) ||
                    (k < minLength) || (k > maxLength) ||
                    (n < minLength) || (n > maxLength)
                    )
            {
                throw new ArgumentException("Incorrect data length.");
            }

            // process rows
            var procRow = new ParallelProcessor<bool, bool>(new Size(1 /*does not matter*/, height),
                                                            () => true,
                                                            (_, __, area) =>
                                                            {
                                                                ComplexF* dataPatchPtr = data + area.Y * stride / sizeof(ComplexF); //get row

                                                                for (int i = 0; i < area.Height; i++)
                                                                {
                                                                    // transform it
                                                                    FourierTransform.FFT(dataPatchPtr, n, direction);

                                                                    dataPatchPtr += stride / sizeof(ComplexF);
                                                                }
                                                            },
                                                            new ParallelOptions2D { ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                                                                  /*,ForceSequential = true*/}
                                                              );

            // process columns
            //(y and x are swaped => proc thinks it is diving horizontal pacthes but instead we are using them as vertical ones)
            var procCol = new ParallelProcessor<bool, bool>(new Size(1 /*does not matter*/, width),
                                                            () => true,
                                                            (_, __, area) =>
                                                            {
                                                                ComplexF* dataPatchPtr = &data[area.Y]; //get column

                                                                fixed (ComplexF* _col = new ComplexF[k])
                                                                {
                                                                    ComplexF* col = _col;

                                                                    for (int j = 0; j < area.Height; j++)
                                                                    {
                                                                        // copy column
                                                                        ComplexF* dataColPtr = &dataPatchPtr[j];
                                                                        for (int i = 0; i < k; i++)
                                                                        {
                                                                            col[i] = *dataColPtr;
                                                                            dataColPtr += stride / sizeof(ComplexF);
                                                                        }

                                                                        // transform it
                                                                        FourierTransform.FFT(col, k, direction);

                                                                        // copy back
                                                                        dataColPtr = &dataPatchPtr[j];
                                                                        for (int i = 0; i < k; i++)
                                                                        {
                                                                            *dataColPtr = col[i];
                                                                            dataColPtr += stride / sizeof(ComplexF);
                                                                        }
                                                                    }
                                                                }
                                                            },
                                                            new ParallelOptions2D { ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                                                                 /*,ForceSequential = true */}
                                                            );

               procRow.Process(true);
               procCol.Process(true);
        }
        IEnumerator WriteCameraFeed()
        {
            writingCamFile = true;
            var tempLocalPos = feedCam.transform.localPosition;
            var bridgeCamPos = memoryBridge.GetVector3("CamLocalPos" + fileName + memoryBridge.cameraFeeds.Count);

            tempLocalPos.x = bridgeCamPos.x;
            tempLocalPos.y = -bridgeCamPos.z;
            tempLocalPos.z = bridgeCamPos.y;
            feedCam.transform.localPosition = tempLocalPos;

            feedCam.transform.localEulerAngles = memoryBridge.GetVector3("CamLocalEuler" + fileName + memoryBridge.cameraFeeds.Count);
            RenderTexture.active = rendText;
            tex.ReadPixels(new Rect(0, 0, rendTextWidth, rendTextHeight), 0, 0);
            //tex.Apply();
            //  camTexture = tex;
            var textureByte = tex.GetRawTextureData();
            // //Debug.Log(textureByte.Length);

            var multiple = textureByte.Length / threadList.Count;

            Stream mapStream0 = camFeedFile.MapView(MapAccess.FileMapAllAccess, 0, multiple);
            Stream mapStream1 = camFeedFile.MapView(MapAccess.FileMapAllAccess, 0, multiple);
            Stream mapStream2 = camFeedFile.MapView(MapAccess.FileMapAllAccess, 0, multiple);
            Stream mapStream3 = camFeedFile.MapView(MapAccess.FileMapAllAccess, 0, multiple);

            ParallelProcessor.EachParallel(threadList,
                                           thread =>
            {
                switch (thread)
                {
                case 0:
                    mapStream0.Write(textureByte, 0, multiple);
                    break;

                case 1:
                    mapStream1.Write(textureByte, 0, multiple);
                    break;

                case 2:
                    mapStream2.Write(textureByte, 0, multiple);
                    break;

                case 3:
                    mapStream3.Write(textureByte, 0, multiple);
                    break;
                }
            });
            mapStream0.Flush();
            mapStream1.Flush();
            mapStream2.Flush();
            mapStream3.Flush();

            mapStream0.Close();
            mapStream1.Close();
            mapStream2.Close();
            mapStream3.Close();

            RenderTexture.active = null;

            writingCamFile = false;

            yield break;
        }
        internal override void Compute(IImage image)
        {
            Reset();

            RawMomentsFunc rawMomentsFunc = null;
            if (rawMomentsFuncs.TryGetValue(image.ColorInfo.ChannelType, out rawMomentsFunc) == false)
                throw new Exception(string.Format("Raw moments can not be calculated of an image of type {0}", image.ColorInfo.ChannelType));

            object sync = new object();
            ParallelProcessor<IImage, bool> proc = new ParallelProcessor<IImage, bool>(image.Size,
                                                                                      () =>
                                                                                      {
                                                                                          return true;
                                                                                      },
                                                                                      (IImage src, bool _, Rectangle area) => //called for every thread
                                                                                      {
                                                                                          IntPoint offset = new IntPoint(area.X, area.Y);

                                                                                          float m00, m01, m10, m11, m02, m20, m12, m21, m30, m03;
                                                                                          rawMomentsFunc(src.GetSubRect(area), offset, Order,
                                                                                                         out m00, out m01, out m10,
                                                                                                         out m11, out m02, out m20,
                                                                                                         out m12, out m21, out m30, out m03);

                                                                                          lock (sync)
                                                                                          {
                                                                                              this.M00 += m00; this.M01 += m01; this.M10 += m10;
                                                                                              this.M11 += m11; this.M02 += m02; this.M20 += m20;
                                                                                              this.M12 += m12; this.M21 += m21; this.M30 += m30; this.M03 += m03;
                                                                                          }
                                                                                      }
                                                                                      /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(image);

            InvM00 = 1f / M00;
            CenterX = M10 * InvM00;
            CenterY = M01 * InvM00;
        }
Beispiel #24
0
        /// <summary>
        /// Two dimensional Fast Fourier Transform.
        /// </summary>
        /// <param name="width">Image width.</param>
        /// <param name="height">Image height.</param>
        /// <param name="stride">Image stride.</param>
        /// <param name="data">Data to transform.</param>
        /// <param name="direction">Transformation direction.</param>
        ///
        /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size
        /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array
        /// is valid, but 15x15 is not.</note></para></remarks>
        ///
        /// <exception cref="ArgumentException">Incorrect data length.</exception>
        ///
        public unsafe static void FFT2(ComplexF *data, int width, int height, int stride, Direction direction)
        {
            const int MIN_PATCH_SIZE = 32; //how much rows/columns should one thread process

            int k = height;
            int n = width;

            // check data size
            if (
                (!AForge.Math.Tools.IsPowerOf2(k)) ||
                (!AForge.Math.Tools.IsPowerOf2(n)) ||
                (k < minLength) || (k > maxLength) ||
                (n < minLength) || (n > maxLength)
                )
            {
                throw new ArgumentException("Incorrect data length.");
            }

            // process rows
            var procRow = new ParallelProcessor <bool, bool>(new Size(1 /*does not matter*/, height),
                                                             () => true,
                                                             (_, __, area) =>
            {
                ComplexF *dataPatchPtr = data + area.Y * stride / sizeof(ComplexF);                                                 //get row

                for (int i = 0; i < area.Height; i++)
                {
                    // transform it
                    FourierTransform.FFT(dataPatchPtr, n, direction);

                    dataPatchPtr += stride / sizeof(ComplexF);
                }
            },
                                                             new ParallelOptions2D {
                ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                  /*,ForceSequential = true*/ }
                                                             );

            // process columns
            //(y and x are swaped => proc thinks it is diving horizontal pacthes but instead we are using them as vertical ones)
            var procCol = new ParallelProcessor <bool, bool>(new Size(1 /*does not matter*/, width),
                                                             () => true,
                                                             (_, __, area) =>
            {
                ComplexF *dataPatchPtr = &data[area.Y];                                                 //get column

                fixed(ComplexF * _col = new ComplexF[k])
                {
                    ComplexF *col = _col;

                    for (int j = 0; j < area.Height; j++)
                    {
                        // copy column
                        ComplexF *dataColPtr = &dataPatchPtr[j];
                        for (int i = 0; i < k; i++)
                        {
                            col[i]      = *dataColPtr;
                            dataColPtr += stride / sizeof(ComplexF);
                        }

                        // transform it
                        FourierTransform.FFT(col, k, direction);

                        // copy back
                        dataColPtr = &dataPatchPtr[j];
                        for (int i = 0; i < k; i++)
                        {
                            *dataColPtr = col[i];
                            dataColPtr += stride / sizeof(ComplexF);
                        }
                    }
                }
            },
                                                             new ParallelOptions2D {
                ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                  /*,ForceSequential = true */ }
                                                             );

            procRow.Process(true);
            procCol.Process(true);
        }
        private static void calculate(MathOps mathOpIdx, IImage src1, IImage src2, IImage dest, Image<Gray, byte> mask = null)
        {
            Debug.Assert(src1.ColorInfo.Equals(src2.ColorInfo) && src1.Size.Equals(src2.Size));

            if (mask == null)
            {
                mask = new Image<Gray, byte>(dest.Width, dest.Height);
                mask.SetValue(new Gray(255));
            }

            var mathOperationOnTypes = mathOperatorFuncs[(int)mathOpIdx];

            MathOpFunc mathOpFunc = null;
            if (mathOperationOnTypes.TryGetValue(src1.ColorInfo.ChannelType, out mathOpFunc) == false)
                throw new Exception(string.Format("Math operation {0} can not be executed on an image of type {1}", mathOpIdx.ToString(), src1.ColorInfo.ChannelType));

            var proc = new ParallelProcessor<bool, bool>(dest.Size,
                                                            () =>
                                                            {
                                                                return true;
                                                            },
                                                            (bool _, bool __, Rectangle area) =>
                                                            {
                                                                var src1Patch = src1.GetSubRect(area);
                                                                var src2Patch = src2.GetSubRect(area);
                                                                var destPatch = dest.GetSubRect(area);
                                                                var maskPatch = mask.GetSubRect(area);

                                                                mathOpFunc(src1Patch, src2Patch, destPatch, maskPatch);
                                                            }
                                                            /*,new ParallelOptions { ForceSequential = true}*/);

            proc.Process(true);
        }