public static unsafe void ApplyConvolution(ImageChannel <TPixel> img, ConvolutionKernel k) { if (img.Width < 2 || img.Height < 2) { return; } int widthTypeScaled = img.Width * img.Step; int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; ImageChannel <TPixel> maskImage = new ImageChannel <TPixel>(img.Width + extend * 2, img.Height + extend * 2); FillImage(maskImage, (TPixel)0); //这里效率不高。原本只需要填充四周扩大的部分即可 CopyChannel(img, maskImage, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, img.Width, img.Height), new System.Drawing.Point(extend, extend)); int step = img.Step; int maskStep = maskImage.Step; int width = img.Width; int height = img.Height; TPixel *start = (TPixel *)img.StartIntPtr; TPixel *maskStart = (TPixel *)maskImage.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskStart + extend; int maskWidth = img.Width + extend * 2; int maskHeight = img.Height + extend * 2; TPixel *dstContentStart = maskStart + extend + maskWidth * extend; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制下方的像素 for (int y = height + extend; y < maskHeight; y++) { TPixel *lineStart = dstStart + y * maskWidth; TPixel *lineEnd = lineStart + width; TPixel *copyStart = dstContentStart + height * maskWidth - maskWidth; while (lineStart != lineEnd) { *lineStart = *copyStart; lineStart++; copyStart++; } } // 复制左右两侧的像素 TPixel *dstLine = maskStart + maskWidth * extend; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { p = dstLine[extend]; for (int x = 0; x < extend; x++) { dstLine[x] = p; } p = dstLine[extend + width - 1]; for (int x = width + extend; x < maskWidth; x++) { dstLine[x] = p; } dstLine += maskWidth; } // 复制四个角落的像素 // 左上 p = dstContentStart[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右上 p = dstContentStart[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } // 左下 p = dstContentStart[(height - 1) * maskWidth]; for (int y = height + extend; y < maskHeight; y++) { for (int x = 0; x < extend; x++) { maskStart[y * maskWidth + x] = p; } } // 右下 p = dstContentStart[(height - 1) * maskWidth + width - 1]; for (int y = height + extend; y < maskHeight; y++) { for (int x = width + extend; x < maskWidth; x++) { maskStart[y * maskWidth + x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { TValue val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskStart[(h + kh) * maskWidth + (w + kw)] * kernel[kh, kw]; } } start[h * widthTypeScaled + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }
public void ApplyConvolution(ConvolutionKernel k) { ApplyConvolution(this, k); }
public unsafe void ApplyConvolution(ConvolutionKernel k) { int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2); maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可 maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend)); int width = this.Width; int height = this.Height; TPixel *start = (TPixel *)this.StartIntPtr; // 复制边界像素 TPixel *dstStart = maskImage.Start + extend; int extendWidth = this.Width + extend * 2; int extendHeight = this.Height + extend * 2; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制下方的像素 for (int y = height + extend; y < extendHeight; y++) { TPixel *dstP = dstStart + y * extendWidth; TPixel *srcStart = start + (height - 1) * width; TPixel *srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制左右两侧的像素 TPixel *dstLine = maskImage.Start + extendWidth * extend; TPixel *srcLine = start; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { for (int x = 0; x < extend; x++) { p = srcLine[0]; dstLine[x] = p; } p = srcLine[width - 1]; for (int x = width + extend; x < extendWidth; x++) { dstLine[x] = p; } dstLine += extendWidth; srcLine += width; } // 复制四个角落的像素 // 左上 p = start[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右上 p = start[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } // 左下 p = start[(height - 1) * width]; for (int y = height + extend; y < extendHeight; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右下 p = start[height * width - 1]; for (int y = height + extend; y < extendHeight; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }
public unsafe void ApplyConvolution(ConvolutionKernel k) { int kernelHeight = k.Width; int kernelWidth = k.Height; int scale = k.Scale; int[,] kernel = k.Kernel; int extend = Math.Max(kernelWidth, kernelHeight) / 2; TImage maskImage = new TImage(Width + extend * 2, Height + extend * 2); maskImage.Fill(0);//这里效率不高。原本只需要填充四周扩大的部分即可 maskImage.Copy(this, new System.Drawing.Point(0, 0), new System.Drawing.Rectangle(0, 0, this.Width, this.Height), new System.Drawing.Point(extend, extend)); int width = this.Width; int height = this.Height; TPixel* start = (TPixel*)this.StartIntPtr; // 复制边界像素 TPixel* dstStart = maskImage.Start + extend; int extendWidth = this.Width + extend * 2; int extendHeight = this.Height + extend * 2; // 复制上方的像素 for (int y = 0; y < extend; y++) { TPixel* dstP = dstStart + y * extendWidth; TPixel* srcStart = start; TPixel* srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制下方的像素 for (int y = height + extend; y < extendHeight; y++) { TPixel* dstP = dstStart + y * extendWidth; TPixel* srcStart = start + (height - 1)*width; TPixel* srcEnd = srcStart + width; while (srcStart != srcEnd) { *dstP = *srcStart; srcStart++; dstP++; } } // 复制左右两侧的像素 TPixel* dstLine = maskImage.Start + extendWidth * extend; TPixel* srcLine = start; TPixel p = default(TPixel); for (int y = extend; y < height + extend; y++) { for(int x = 0; x < extend; x ++) { p = srcLine[0]; dstLine[x] = p; } p = srcLine[width-1]; for(int x = width + extend; x < extendWidth; x++) { dstLine[x] = p; } dstLine += extendWidth; srcLine += width; } // 复制四个角落的像素 // 左上 p = start[0]; for (int y = 0; y < extend; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右上 p = start[width - 1]; for (int y = 0; y < extend; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } // 左下 p = start[(height - 1) * width]; for (int y = height + extend; y < extendHeight; y++) { for (int x = 0; x < extend; x++) { maskImage[y, x] = p; } } // 右下 p = start[height * width - 1]; for (int y = height + extend; y < extendHeight; y++) { for (int x = width + extend; x < extendWidth; x++) { maskImage[y, x] = p; } } if (scale == 1) { for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)val; } } } else { double factor = 1.0 / scale; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int val = 0; for (int kw = 0; kw < kernelWidth; kw++) { for (int kh = 0; kh < kernelHeight; kh++) { val += maskImage[h + kh, w + kw] * kernel[kh, kw]; } } start[h * width + w] = (TPixel)(val * factor); } } } maskImage.Dispose(); }
public void ApplyGaussianBlur(double sigma = 1.4, int size = 5) { ConvolutionKernel kernel = ConvolutionKernel.CreateGaussianKernel(sigma, size); this.ApplyConvolution(kernel); }