You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求C#版Lanczos算法实现,或更优图像降维方案用于平均哈希计算

Hey there! Let's tackle your image resizing and average hash problem in C#—I've got some solid options for you.

Getting Lanczos Resizing in C#

You have two main paths to implement Lanczos resizing: rolling your own code for full control, or using a mature library that handles it out of the box.

1. Custom Lanczos Implementation (Tailored for Average Hash)

If you want to build it yourself, Lanczos interpolation uses a convolution kernel based on the Lanczos window function. Here's a simplified implementation for Lanczos3 (the most widely used variant, with a window size of 3), optimized for grayscale images (since you'll convert to grayscale for average hash anyway):

using System;
using System.Drawing;

public static class LanczosResizer
{
    public static Bitmap ResizeTo8x8Lanczos(Bitmap source)
    {
        // First convert source to grayscale
        Bitmap graySource = ConvertToGrayscale(source);
        Bitmap result = new Bitmap(8, 8);

        double scaleX = (double)graySource.Width / 8;
        double scaleY = (double)graySource.Height / 8;
        int windowSize = 3;

        for (int y = 0; y < 8; y++)
        {
            for (int x = 0; x < 8; x++)
            {
                double sum = 0;
                double weightSum = 0;

                // Calculate centered source coordinates
                double sourceX = (x + 0.5) * scaleX - 0.5;
                double sourceY = (y + 0.5) * scaleY - 0.5;

                // Define the Lanczos window boundaries
                int startX = Math.Max(0, (int)Math.Floor(sourceX - windowSize + 1));
                int endX = Math.Min(graySource.Width - 1, (int)Math.Ceiling(sourceX + windowSize - 1));
                int startY = Math.Max(0, (int)Math.Floor(sourceY - windowSize + 1));
                int endY = Math.Min(graySource.Height - 1, (int)Math.Ceiling(sourceY + windowSize - 1));

                // Sample pixels within the window
                for (int sy = startY; sy <= endY; sy++)
                {
                    double dy = sy - sourceY;
                    double weightY = Lanczos(dy, windowSize);

                    for (int sx = startX; sx <= endX; sx++)
                    {
                        double dx = sx - sourceX;
                        double weightX = Lanczos(dx, windowSize);
                        double weight = weightX * weightY;

                        Color pixel = graySource.GetPixel(sx, sy);
                        sum += pixel.R * weight; // Grayscale, so R=G=B
                        weightSum += weight;
                    }
                }

                // Clamp value to valid byte range and set result pixel
                byte grayValue = (byte)Math.Clamp(sum / weightSum, 0, 255);
                result.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue));
            }
        }

        return result;
    }

    private static Bitmap ConvertToGrayscale(Bitmap source)
    {
        Bitmap gray = new Bitmap(source.Width, source.Height);
        for (int y = 0; y < source.Height; y++)
        {
            for (int x = 0; x < source.Width; x++)
            {
                Color color = source.GetPixel(x, y);
                int grayValue = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
                gray.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue));
            }
        }
        return gray;
    }

    private static double Lanczos(double x, int windowSize)
    {
        if (x == 0) return 1;
        if (Math.Abs(x) >= windowSize) return 0;
        x *= Math.PI;
        return windowSize * Math.Sin(x) * Math.Sin(x / windowSize) / (x * x);
    }
}

Note: This is a basic implementation—for production, optimize it with unsafe code (to avoid GetPixel/SetPixel overhead) or parallel processing for faster performance.

2. Use ImageSharp (Easier, Production-Ready)

If you don't want to reinvent the wheel, ImageSharp is a modern, cross-platform .NET image library that has built-in Lanczos resampling. It's far more efficient than a custom implementation and handles edge cases perfectly.

First, install the NuGet package via the Package Manager Console:

Install-Package SixLabors.ImageSharp

Then, here's how to resize an image to 8x8 with Lanczos3:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;

public static Image<Rgba32> ResizeTo8x8WithLanczos(Image<Rgba32> sourceImage)
{
    return sourceImage.Clone(ctx => ctx
        .Grayscale() // Convert to grayscale first
        .Resize(new ResizeOptions
        {
            Size = new Size(8, 8),
            Sampler = KnownResamplers.Lanczos3,
            Mode = ResizeMode.Stretch // Use Pad/Crop if you need to maintain aspect ratio
        }));
}
Are There Better Alternatives to Lanczos for Average Hash?

For average hash, the goal is to capture the overall brightness pattern of the image—not preserve every tiny detail. So while Lanczos is top-tier for high-quality resizing, it might be overkill here. Here are some alternatives to consider:

  • Bicubic Interpolation: Faster than Lanczos, and produces nearly identical results for 8x8 resizing. The difference in average hash values will be negligible for most similarity checks. Most image libraries (including System.Drawing and ImageSharp) support this out of the box.
  • Mitchell-Netravali: This method balances sharpness and smoothness, which can be better for edge preservation in some scenarios. However, for 8x8 resizing, the advantage over Lanczos or bicubic is minimal.
  • Bilinear Interpolation: If speed is your highest priority, bilinear is much faster than Lanczos. Even with this simpler method, the 8x8 grid will still capture the key brightness distribution needed for average hash—you won't lose meaningful similarity detection accuracy.

Quick Recommendation

If you want the best possible resizing quality (and don't mind a tiny performance hit), stick with Lanczos. But if speed matters more, bicubic is a great compromise. For average hash specifically, even bilinear will work just fine—you won't notice a difference in similarity matching.

内容的提问来源于stack exchange,提问作者Hemanath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:26:32