【发布时间】:2015-11-12 09:15:21
【问题描述】:
我一直在试验 AForge 框架中的图像双三次重采样算法,其想法是在我的图像处理解决方案中引入类似的东西。见原算法here和插值内核here
不幸的是,我碰壁了。在我看来,我以某种方式错误地计算了样本目标位置,这可能是由于为Format24bppRgb 图像设计的算法,而我使用的是Format32bppPArgb 格式。
这是我的代码:
public Bitmap Resize(Bitmap source, int width, int height)
{
int sourceWidth = source.Width;
int sourceHeight = source.Height;
Bitmap destination = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
destination.SetResolution(source.HorizontalResolution, source.VerticalResolution);
using (FastBitmap sourceBitmap = new FastBitmap(source))
{
using (FastBitmap destinationBitmap = new FastBitmap(destination))
{
double heightFactor = sourceWidth / (double)width;
double widthFactor = sourceHeight / (double)height;
// Coordinates of source points
double ox, oy, dx, dy, k1, k2;
int ox1, oy1, ox2, oy2;
// Width and height decreased by 1
int maxHeight = height - 1;
int maxWidth = width - 1;
for (int y = 0; y < height; y++)
{
// Y coordinates
oy = (y * widthFactor) - 0.5;
oy1 = (int)oy;
dy = oy - oy1;
for (int x = 0; x < width; x++)
{
// X coordinates
ox = (x * heightFactor) - 0.5f;
ox1 = (int)ox;
dx = ox - ox1;
// Destination color components
double r = 0;
double g = 0;
double b = 0;
double a = 0;
for (int n = -1; n < 3; n++)
{
// Get Y cooefficient
k1 = Interpolation.BiCubicKernel(dy - n);
oy2 = oy1 + n;
if (oy2 < 0)
{
oy2 = 0;
}
if (oy2 > maxHeight)
{
oy2 = maxHeight;
}
for (int m = -1; m < 3; m++)
{
// Get X cooefficient
k2 = k1 * Interpolation.BiCubicKernel(m - dx);
ox2 = ox1 + m;
if (ox2 < 0)
{
ox2 = 0;
}
if (ox2 > maxWidth)
{
ox2 = maxWidth;
}
Color color = sourceBitmap.GetPixel(ox2, oy2);
r += k2 * color.R;
g += k2 * color.G;
b += k2 * color.B;
a += k2 * color.A;
}
}
destinationBitmap.SetPixel(
x,
y,
Color.FromArgb(a.ToByte(), r.ToByte(), g.ToByte(), b.ToByte()));
}
}
}
}
source.Dispose();
return destination;
}
以及应该代表Wikipedia上给定方程的内核
public static double BiCubicKernel(double x)
{
if (x < 0)
{
x = -x;
}
double bicubicCoef = 0;
if (x <= 1)
{
bicubicCoef = (1.5 * x - 2.5) * x * x + 1;
}
else if (x < 2)
{
bicubicCoef = ((-0.5 * x + 2.5) * x - 4) * x + 2;
}
return bicubicCoef;
}
这是 500 像素 x 667 像素的原始图片。
图片大小调整为 400px x 543px。
从视觉上看,图像被过度缩小,然后一旦我们到达特定点,就会重复应用相同的像素。
谁能给我一些建议来解决这个问题?
注意 FastBitmap 是 Bitmap 的包装器,它使用 LockBits 来操作内存中的像素。它适用于everything else 我将其应用于。
编辑
根据要求,这里是ToByte中涉及的方法
public static byte ToByte(this double value)
{
return Convert.ToByte(ImageMaths.Clamp(value, 0, 255));
}
public static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
{
if (value.CompareTo(min) < 0)
{
return min;
}
if (value.CompareTo(max) > 0)
{
return max;
}
return value;
}
【问题讨论】:
-
你能发布你的扩展方法 ToByte(this double...) 吗?
-
这也是我的想法。顺便说一句,即使登录到我的 Dropbox 帐户,我也看不到您链接到的那张图片。
-
可以分享一下原图吗?我已经尝试过您之前发布的那个,但结果不同。我猜 stackoverflow 对发布的图片进行了一些修改。
-
是的,当然。它在 github 上。 raw.githubusercontent.com/JimBobSquarePants/ImageProcessor/…
标签: c# algorithm image-processing