난, 3 × 3 커널을 사용하여 그레이 스케일 이미지를 선명하게하기 위해 몇몇 루틴을 작성한는 FFT는 컨볼 루션 - 3 × 3 커널
-1 -1 -1
-1 9 -1
-1 -1 -1
다음 코드는 비 FFT (공간 영역) 회선의 경우에 잘 작동하고, 그러나 FFT 기반 (주파수 영역) 컨볼 루션에서는 작동하지 않습니다.
출력 이미지가 흐리게 보입니다.
나는 몇 가지 문제가 있습니다
(1)이 루틴은 원하는 결과를 생성 할 수있는 없습니다. 또한 응용 프로그램을 고정시킵니다.
public static Bitmap ApplyWithPadding(Bitmap image, Bitmap mask)
{
if(image.PixelFormat == PixelFormat.Format8bppIndexed)
{
Bitmap imageClone = (Bitmap)image.Clone();
Bitmap maskClone = (Bitmap)mask.Clone();
/////////////////////////////////////////////////////////////////
Complex[,] cPaddedLena = ImageDataConverter.ToComplex(imageClone);
Complex[,] cPaddedMask = ImageDataConverter.ToComplex(maskClone);
Complex[,] cConvolved = Convolution.Convolve(cPaddedLena, cPaddedMask);
return ImageDataConverter.ToBitmap(cConvolved);
}
else
{
throw new Exception("not a grascale");
}
}
(2)이 루틴은 좋은 결과를 제공합니다. 그러나 지옥처럼 느립니다.
public static Bitmap Apply(Bitmap sourceBitmap)
{
Sharpen filter = new Sharpen();
BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
double blue = 0.0;
double green = 0.0;
double red = 0.0;
int filterWidth = filter.FilterMatrix.GetLength(1);
int filterHeight = filter.FilterMatrix.GetLength(0);
int filterOffset = (filterWidth - 1)/2;
int calcOffset = 0;
int byteOffset = 0;
for (int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++)
{
for (int offsetX = filterOffset; offsetX <
sourceBitmap.Width - filterOffset; offsetX++)
{
blue = 0;
green = 0;
red = 0;
byteOffset = offsetY *
sourceData.Stride +
offsetX * 4;
for (int filterY = -filterOffset;
filterY <= filterOffset; filterY++)
{
for (int filterX = -filterOffset;
filterX <= filterOffset; filterX++)
{
calcOffset = byteOffset +
(filterX * 4) +
(filterY * sourceData.Stride);
blue += (double)(pixelBuffer[calcOffset]) *
filter.FilterMatrix[filterY + filterOffset,
filterX + filterOffset];
green += (double)(pixelBuffer[calcOffset + 1]) *
filter.FilterMatrix[filterY + filterOffset,
filterX + filterOffset];
red += (double)(pixelBuffer[calcOffset + 2]) *
filter.FilterMatrix[filterY + filterOffset,
filterX + filterOffset];
}
}
blue = filter.Factor * blue + filter.Bias;
green = filter.Factor * green + filter.Bias;
red = filter.Factor * red + filter.Bias;
if (blue > 255)
{ blue = 255; }
else if (blue < 0)
{ blue = 0; }
if (green > 255)
{ green = 255; }
else if (green < 0)
{ green = 0; }
if (red > 255)
{ red = 255; }
else if (red < 0)
{ red = 0; }
resultBuffer[byteOffset] = (byte)(blue);
resultBuffer[byteOffset + 1] = (byte)(green);
resultBuffer[byteOffset + 2] = (byte)(red);
resultBuffer[byteOffset + 3] = 255;
}
}
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
resultBitmap.UnlockBits(resultData);
return resultBitmap;
}
(3) 다음 내 GUI 코드입니다. 이미지를 마스크로 사용하면 SharpenFilter.ApplyWithPadding()
이 제대로 작동합니다. 하지만, 말하자면, 3
x 3
커널을 사용하면 작동하지 않습니다.
string path = @"E:\lena.png";
string path2 = @"E:\mask.png";
Bitmap _inputImage;
Bitmap _maskImage;
private void LoadImages_Click(object sender, EventArgs e)
{
_inputImage = Grayscale.ToGrayscale(Bitmap.FromFile(path) as Bitmap);
/*
_maskImage = Grayscale.ToGrayscale(Bitmap.FromFile(path2) as Bitmap);
*/
SharpenFilter filter = new SharpenFilter();
double[,] mask = new double[,] { { -1, -1, -1, },
{ -1, 9, -1, },
{ -1, -1, -1, }, };
_maskImage = ImageDataConverter.ToBitmap(mask);
inputImagePictureBox.Image = _inputImage;
maskPictureBox.Image = _maskImage;
}
Bitmap _paddedImage;
Bitmap _paddedMask;
private void padButton_Click(object sender, EventArgs e)
{
Bitmap lena = Grayscale.ToGrayscale(_inputImage);
Bitmap mask = Grayscale.ToGrayscale(_maskImage);
////Not working...
//int maxWidth = (int)Math.Max(lena.Width, mask.Width);
//int maxHeight = (int)Math.Max(lena.Height, mask.Height);
////This is working correctly in case if I use a png image as a mask.
int maxWidth = (int)Tools.ToNextPow2(Convert.ToUInt32(lena.Width + mask.Width));
int maxHeight = (int)Tools.ToNextPow2(Convert.ToUInt32(lena.Height + mask.Height));
_paddedImage = ImagePadder.Pad(lena, maxWidth, maxHeight);
_paddedMask = ImagePadder.Pad(mask, maxWidth, maxHeight);
paddedImagePictureBox.Image = _paddedImage;
paddedMaskPictureBox.Image = _paddedMask;
}
private void filterButton_Click(object sender, EventArgs e)
{
// Not working properly.
// Freezes the application.
Bitmap sharp = SharpenFilter.ApplyWithPadding(_paddedImage, _paddedMask);
////Works well. But, very slow.
//Bitmap sharp = SharpenFilter.Apply(_paddedImage);
filteredPictureBox.Image = sharp as Bitmap;
}
출력 :
소스 코드 :
- 요 u는 here in this link에서 전체 솔루션을 다운로드 할 수 있습니다.
안녕 수 당신이 'Convolution.Convolve (x, y)'는 무엇을할까요? 어쨌든 4 중 공간에서의 회선은 곱셈이다. 따라서 용어로 용어를 복잡하게 곱하면 cPaddedLena와 cPaddedMask의 4 변형 변환 (4 배 공간에서 동일한 차원을 갖도록 패딩되어야 함)을 수행하고 반전 4 배 변환을 수행하면 연산이 작동합니다 –