コード例 #1
0
ファイル: MainForm.cs プロジェクト: cuplexProjects/C-Projects
        private async void btnApplyFilter_Click(object sender, EventArgs e)
        {
            if (!_imageProcessService.ImageLoaded)
            {
                MessageBox.Show("Please select an image before applying a filter", "No Image Loaded", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }


            if (!_imageProcessService.IsRunning)
            {
                SetFilterParameters();
                EdgeHandling edgeHandling = rbExtend.Checked ? EdgeHandling.Extend : EdgeHandling.Wrap;
                btnApplyFilter.Text = "Cancel";
                await _imageProcessService.ApplyFilter(_selectedImageFilter, edgeHandling);

                btnApplyFilter.Text = "Apply Filter";
            }
            else
            {
                await _imageProcessService.CancelApplyFilter();

                btnApplyFilter.Text = "Apply Filter";
            }
        }
コード例 #2
0
 private KernelFunction GetKernelFunction(Kernel kernel, EdgeHandling edgeHandling, int range)
 {
     if (edgeHandling == EdgeHandling.MIRROR_EXTENSION)
     {
         return((channel, ppx, ppy, action) =>
         {
             int middleX = (int)ppx;
             int middleY = (int)ppy;
             for (int x = 0; x < kernel.Size; x++)
             {
                 for (int y = 0; y < kernel.Size; y++)
                 {
                     int pixelX = middleX - range + x;
                     int pixelY = middleY - range + y;
                     int finalX, finalY;
                     if (pixelX < 0)
                     {
                         finalX = -pixelX;
                     }
                     else if (pixelX >= Width)
                     {
                         finalX = (int)(Width - (pixelX - Width + 1));
                     }
                     else
                     {
                         finalX = pixelX;
                     }
                     if (pixelY < 0)
                     {
                         finalY = -pixelY;
                     }
                     else if (pixelY >= Height)
                     {
                         finalY = (int)(Height - (pixelY - Height + 1));
                     }
                     else
                     {
                         finalY = pixelY;
                     }
                     action(channel.GetMultipliedValue((uint)finalX, (uint)finalY, kernel[(uint)x, (uint)y]));
                 }
             }
         });
     }
     else
     {
         return((channel, ppx, ppy, action) =>
         {
             int middleX = (int)ppx;
             int middleY = (int)ppy;
             for (int x = 0; x < kernel.Size; x++)
             {
                 for (int y = 0; y < kernel.Size; y++)
                 {
                     int pixelX = middleX - range + x;
                     int pixelY = middleY - range + y;
                     if (pixelX < 0 || pixelX >= Width || pixelY < 0 || pixelY >= Height)
                     {
                         action(default);
コード例 #3
0
 public SourceDataBase(Bitmap source, EdgeHandling edgeHandling)
 {
     _imageSize      = source.Size;
     _edgeHandling   = edgeHandling;
     _imageDataBytes = GetImageBytes(source, out _stride);
     ImageWidth      = source.Width;
     ImageHeight     = source.Height;
     NumberOfPixels  = source.Height * source.Width;
 }
コード例 #4
0
        public async Task ApplyFilter(IImageFilter imageFilter, EdgeHandling edgeHandling)
        {
            if (IsRunning || _sourceBitmap == null)
            {
                return;
            }
            IsRunning = true;
            await Task.Run(() => { ApplyFilterMultithreaded(imageFilter, edgeHandling); });

            IsRunning = false;
        }
コード例 #5
0
 private void GetFilterArea(EdgeHandling edgeHandling, uint range, out uint lowerX, out uint upperX, out uint lowerY, out uint upperY)
 {
     if (edgeHandling == EdgeHandling.SKIP_UNDEFINED)
     {
         lowerX = range;
         upperX = Width - range;
         lowerY = range;
         upperY = Height - range;
     }
     else
     {
         lowerX = 0;
         upperX = Width;
         lowerY = 0;
         upperY = Height;
     }
 }
コード例 #6
0
        public static Convolution <T> Create <T>(
            Matrix <double> kernel,
            Accumulator <T> accumulate,
            EdgeHandling edgeHandling) where T : struct, IEquatable <T>, IFormattable
        {
            if (kernel.RowCount % 2 == 0)
            {
                const string err = "Kernel must have an odd number of rows.";
                throw new ArgumentException(err, nameof(kernel));
            }

            if (kernel.ColumnCount % 2 == 0)
            {
                const string err = "Kernel must have an odd number of columns.";
                throw new ArgumentException(err, nameof(kernel));
            }

            IAccumulationStrategy <T> strategy;

            switch (edgeHandling)
            {
            case EdgeHandling.Crop:
                strategy = new CroppingStrategy <T>(accumulate);
                break;

            case EdgeHandling.Extend:
                strategy = new ExtendingStrategy <T>(accumulate);
                break;

            case EdgeHandling.Mirror:
                strategy = new MirroringStrategy <T>(accumulate);
                break;

            case EdgeHandling.Wrap:
                strategy = new WrappingStrategy <T>(accumulate);
                break;

            default:
                const string err = "Please specify an edge handling strategy.";
                throw new ArgumentException(err, nameof(edgeHandling));
            }

            return(new Convolution <T>(kernel, strategy));
        }
コード例 #7
0
        public void Convolution(ConvolutionKernel kernel, EdgeHandling edgeHandling)
        {
            unsafe
            {
                var                  _workingBitmap             = new Bitmap(Image);
                var                  _rect                      = new Rectangle(0, 0, Image.Width, Image.Height);
                BitmapData           _originalBitmapData        = Image.LockBits(_rect, ImageLockMode.ReadWrite, Image.PixelFormat);
                var                  _workingBitmapData         = _workingBitmap.LockBits(_rect, ImageLockMode.ReadWrite, Image.PixelFormat);
                int                  _bytesPerPixel             = Bitmap.GetPixelFormatSize(Image.PixelFormat) / 8;
                int                  _heightInPixels            = _originalBitmapData.Height;
                int                  _widthInBytes              = _originalBitmapData.Width * _bytesPerPixel;
                int                  _offset                    = kernel.Offset;
                int                  _imageOffset               = 0; //edge position
                byte *               _firstPixelPointerOriginal = (byte *)_originalBitmapData.Scan0;
                byte *               _firstPixelPointerWorking  = (byte *)_workingBitmapData.Scan0;
                byte *[]             _rowsOriginal              = new byte *[_heightInPixels];
                Func <int, int, int> _clamping                  = null;
                switch (edgeHandling)
                {
                case EdgeHandling.Extend:
                    _clamping = ClampExtend;
                    break;

                case EdgeHandling.Wrap:
                    _clamping = ClampWrap;
                    break;

                case EdgeHandling.Mirror:
                    _clamping = ClampMirror;
                    break;

                case EdgeHandling.Crop:
                default:
                    _imageOffset = kernel.Offset;
                    _clamping    = ClampCrop;
                    break;
                }
                for (int i = 0; i < _heightInPixels; i++)
                {
                    _rowsOriginal[i] = _firstPixelPointerOriginal + (i * _originalBitmapData.Stride);
                }
                //BGR format
                for (int y = _imageOffset; y < _heightInPixels - _imageOffset; y++)
                {
                    for (int x = _imageOffset * _bytesPerPixel; x < _widthInBytes - _imageOffset * _bytesPerPixel; x = x + _bytesPerPixel)
                    {
                        double _r = 0.0;
                        double _g = 0.0;
                        double _b = 0.0;
                        byte * _workingScanLine = _firstPixelPointerWorking + (y * _workingBitmapData.Stride);
                        for (int ky = -_offset; ky <= _offset; ky++)
                        {
                            int _yOffset = _clamping(y + ky, _heightInPixels - 1);
                            //
                            byte *_originalScanLine = _rowsOriginal[_yOffset];
                            for (int kx = -_offset; kx <= _offset; kx++)
                            {
                                double _k       = kernel[kx, ky];
                                int    _xOffset = _clamping(x + kx * _bytesPerPixel, _widthInBytes - 3);
                                _b += _originalScanLine[_xOffset] * _k;
                                _g += _originalScanLine[_xOffset + 1] * _k;
                                _r += _originalScanLine[_xOffset + 2] * _k;
                            }
                        }
                        _workingScanLine[x]     = Clamp(_b / kernel.NormalizationFactor + kernel.Bias);
                        _workingScanLine[x + 1] = Clamp(_g / kernel.NormalizationFactor + kernel.Bias);
                        _workingScanLine[x + 2] = Clamp(_r / kernel.NormalizationFactor + kernel.Bias);
                    }
                }
                _workingBitmap.UnlockBits(_workingBitmapData);
                Image.UnlockBits(_originalBitmapData);
                Image = _workingBitmap;
                //originalBitmap = _workingBitmap.Clone(_rect, originalBitmap.PixelFormat);
                //_workingBitmap.Save(@"C:\Users\rokr\Desktop\aaa_no.bmp");
            }
        }
コード例 #8
0
        private void ApplyFilterMultithreaded(IImageFilter imageFilter, EdgeHandling edgeHandling)
        {
            int numberOfThreads = Environment.ProcessorCount;

            // ReSharper disable once InconsistentlySynchronizedField
            _updateProgressDictionary.Clear();

            try
            {
                _sourceDataBase = new SourceDataBase(_sourceBitmap, edgeHandling);

                int imgPixelSize = _sourceDataBase.NumberOfPixels;

                int workSize       = Convert.ToInt32(Math.Floor(imgPixelSize / (double)numberOfThreads));
                int remaningPixels = imgPixelSize % numberOfThreads;


                //Split work into number of threads awailable for this system
                var doneEvents = new ManualResetEvent[numberOfThreads];
                processFilterArray = new ProcessFilter[numberOfThreads];

                int startIndex = 0;

                for (int i = 0; i < numberOfThreads; i++)
                {
                    doneEvents[i] = new ManualResetEvent(false);
                    ProcessFilter processFilter;
                    var           sourceData = new SourceData(_sourceDataBase);

                    if (remaningPixels > 0 && i == numberOfThreads - 1)
                    {
                        processFilter = new ProcessFilter(sourceData, imageFilter, startIndex, startIndex + workSize + remaningPixels, doneEvents[i]);
                    }
                    else
                    {
                        processFilter = new ProcessFilter(sourceData, imageFilter, startIndex, startIndex + workSize, doneEvents[i]);
                    }

                    processFilter.OnProgressUpdate += processFilter_OnProgressUpdate;

                    startIndex           += workSize;
                    processFilterArray[i] = processFilter;
                    ThreadPool.QueueUserWorkItem(processFilter.ThreadPoolCallback, i);
                }

                waitHandleArray = new WaitHandle[doneEvents.Length];
                for (int i = 0; i < doneEvents.Length; i++)
                {
                    waitHandleArray[i] = doneEvents[i];
                }

                // Wait for all threads in pool to complete.
                WaitHandle.WaitAll(waitHandleArray);
                _outputBitmap = _sourceDataBase.GetOutputBitmap();
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                Console.WriteLine(message);
            }

            processFilterArray = null;
            waitHandleArray    = null;
            IsRunning          = false;

            if (OnProcessComplete != null)
            {
                OnProcessComplete.Invoke(this, new EventArgs());
            }
        }
コード例 #9
0
        public override Image Filter(Kernel kernel, FilterType filter = FilterType.AVERAGE, EdgeHandling edgeHandling = EdgeHandling.MIRROR_EXTENSION)
        {
            uint size  = kernel.Size;
            uint range = size / 2;

            if (Width < range + 1 || Height < range + 1)
            {
                throw new IndexOutOfRangeException("Neighborhood range cannot be greater than image size.");
            }

            Image result;

            if (edgeHandling == EdgeHandling.SKIP_UNDEFINED)
            {
                result = Clone();
            }
            else
            {
                result = ImageFactory.Create(Width, Height, GetColorModel(), GetDataType());
            }

            uint lowerX, upperX, lowerY, upperY;

            GetFilterArea(edgeHandling, range, out lowerX, out upperX, out lowerY, out upperY);
            KernelFunction  kernelFunction  = GetKernelFunction(kernel, edgeHandling, (int)range);
            FilterOperation filterOperation = GetFilterOperation(filter);

            for (uint x = lowerX; x < upperX; x++)
            {
                for (uint y = lowerY; y < upperY; y++)
                {
                    filterOperation(this, kernelFunction, size, x, y, result);
                }
            }
            return(result);
        }
コード例 #10
0
        /// <summary>
        /// Convolves the image using a specified kernel edge handling technique.
        /// </summary>
        /// <param name="image">Image to convolve</param>
        /// <param name="kernel">Convolution kernel</param>
        /// <param name="edgeHandling">Convolution Edge Handling Technique</param>
        /// <returns>Convolved Image</returns>
        public static IImage <double> Convolve(this IImage <double> image, double[][] kernel, EdgeHandling edgeHandling)
        {
            // Kernel
            var kernel_height = kernel.Length;
            var kernel_width  = kernel[0].Length;

            // Mid Point
            var k_mid_h = kernel_height % 2 == 0 ? (kernel_height >> 1) - 1 : (kernel_height >> 1);
            var k_mid_w = kernel_width % 2 == 0 ? (kernel_width >> 1) - 1 : (kernel_width >> 1);

            // Dimensions for the new Image
            int width  = image.Width;
            int height = image.Height;

            Func <int, int> edgeX;
            Func <int, int> edgeY;

            switch (edgeHandling)
            {
            // Wrap Pixels
            case EdgeHandling.Wrap:
                edgeX = x => x >= width ? x - width : (x < 0 ? width + x : x);
                edgeY = y => y >= height ? y - width : (y < 0 ? height + y : y);
                break;

            // Start with offset and insert into cropped image
            case EdgeHandling.Crop:
                width  -= kernel_width;
                height -= kernel_height;
                edgeX   = x => x + k_mid_w;
                edgeY   = y => y + k_mid_h;
                break;

            // Extend
            case EdgeHandling.Extend:
            default:
                edgeX = x => x < 0 ? 0 : (x >= width ? width - 1 : x);
                edgeY = y => y < 0 ? 0 : (y >= height ? height - 1 : y);
                break;
            }

            IImage <double> conv = new Image(width, height);

            // Convolution is a general purpose filter effect for images
            // Is a matrix applied to an image and a mathematical operation
            // comprised of integers
            // It works by determining the value of a central pixel by adding the
            // weighted values of all its neighbors together
            // The output is a new modified filtered image
            // for each image row in output image,
            Parallel.For(0, height - 1, y =>
            {
                // for each pixel in image row:
                for (int x = 0; x < width; x++)
                {
                    // set accumulator to zero
                    double accumulator = 0.0;

                    // for each kernel row in kernel:
                    for (int k_x = 0; k_x < kernel_width; k_x++)
                    {
                        // for each element in kernel row:
                        for (int k_y = 0; k_y < kernel_height; k_y++)
                        {
                            // int index1 = image.Width * Mod(y + kcol - w, image.Height) + Mod(x + krow - h, image.Width);
                            int index1   = image.Width * edgeY(y + k_y - k_mid_h) + edgeX(x + k_x - k_mid_w);
                            int kernelX  = kernel_width - k_x - 1;
                            int kernelY  = kernel_height - k_y - 1;
                            accumulator += image[index1] * kernel[kernelY][kernelX];
                        }
                    }

                    // set output image pixel to accumulator
                    conv[y * width + x] = accumulator;
                }
            });

            return(conv);
        }
コード例 #11
0
ファイル: Image.cs プロジェクト: SmiledProgrammer/SeeMore
 public abstract Image Filter(Kernel kernel, FilterType filter = FilterType.AVERAGE, EdgeHandling edgeHandling = EdgeHandling.MIRROR_EXTENSION);