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

在C#中调用Python图像处理脚本时出现Delegates类型初始化异常的求助

Hey there! Let's break down how to fix that "Delegates type initializer" error you're hitting when using Python.NET to process images. I've run into similar issues before, so here's what's likely going wrong and how to fix it:

First, Let's Diagnose the Root Causes

Your error usually pops up due to three main issues:

  1. Incorrect environment variable setup (you have a tiny typo that's breaking things)
  2. Mismatched image types between C# and Python (you're passing a C# Image directly to OpenCV, which doesn't understand that format)
  3. Late/duplicate Python runtime initialization (setting env vars and initializing Python inside the try block can cause conflicts)

Step 1: Fix the Environment Variable Typo

Look at your PYTHONPATH line—you have an extra space at the end of the variable name, plus you're missing the site-packages folder where cv2 and numpy live:

// Wrong: extra space + missing site-packages
Environment.SetEnvironmentVariable("PYTHONPATH ", $@"{pythonPath}\Lib");
// Correct: no space + include site-packages
Environment.SetEnvironmentVariable("PYTHONPATH", $@"{pythonPath}\Lib;{pythonPath}\Lib\site-packages");

Also add Scripts to your PATH to include Python executables in your environment.

Step 2: Fix Image Type Conversion

C# System.Drawing.Image can't be directly passed to OpenCV's functions—you need to convert it to a NumPy array first, then convert the processed NumPy array back to a C# Image.

Add these helper functions to your C# code:

private static numpy.ndarray ImageToNumpyArray(Image image)
{
    Bitmap bitmap = new Bitmap(image);
    Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    var bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);

    int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
    int byteCount = bmpData.Stride * bitmap.Height;
    byte[] pixels = new byte[byteCount];
    System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixels, 0, byteCount);
    bitmap.UnlockBits(bmpData);

    // Convert to NumPy array (adjust shape based on image channels)
    var npArray = numpy.array(pixels).reshape(new[] { bitmap.Height, bitmap.Width, bytesPerPixel });
    // Squeeze single-channel (grayscale) arrays to 2D
    return npArray.ndim == 3 && bytesPerPixel == 1 ? npArray.squeeze() : npArray;
}

private static Image NumpyArrayToImage(numpy.ndarray npArray)
{
    int height = npArray.shape[0];
    int width = npArray.shape[1];
    int channels = npArray.ndim == 2 ? 1 : npArray.shape[2];

    PixelFormat format = channels == 1 ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb;
    Bitmap bitmap = new Bitmap(width, height, format);

    Rectangle rect = new Rectangle(0, 0, width, height);
    var bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, format);

    byte[] pixels = npArray.flatten().ToArray<byte>();
    System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
    bitmap.UnlockBits(bmpData);

    // Set grayscale palette if needed
    if (channels == 1)
    {
        var palette = bitmap.Palette;
        for (int i = 0; i < 256; i++)
            palette.Entries[i] = Color.FromArgb(i, i, i);
        bitmap.Palette = palette;
    }

    return bitmap;
}

Step 3: Initialize Python Properly (Once, Up Front)

Don't set environment variables and initialize Python inside your processing method—do it once when your app starts (like in the form constructor):

public YourFormName()
{
    InitializeComponent();
    InitializePythonRuntime();
}

private void InitializePythonRuntime()
{
    var pythonPath = @"C:\Users\Admin\anaconda3";
    // Set environment variables for the current process
    Environment.SetEnvironmentVariable("PATH", $@"{pythonPath};{pythonPath}\Scripts;" + Environment.GetEnvironmentVariable("PATH"), EnvironmentVariableTarget.Process);
    Environment.SetEnvironmentVariable("PYTHONHOME", pythonPath, EnvironmentVariableTarget.Process);
    Environment.SetEnvironmentVariable("PYTHONPATH", $@"{pythonPath}\Lib;{pythonPath}\Lib\site-packages", EnvironmentVariableTarget.Process);
    
    // Initialize the Python engine once
    PythonEngine.Initialize();
}

Step 4: Update Your Processing Code

Now modify your image processing block to use the helper functions:

if (greyImage1 != null)
{
    try
    {
        this.Cursor = Cursors.WaitCursor;
        string scriptFile = "myfunction.py";
        string pythonCode = File.ReadAllText(scriptFile, Encoding.UTF8);

        using (Py.GIL())
        {
            var scope = Py.CreateScope();
            scope.Exec(pythonCode);
            var binariseFunc = scope.Get("binarise").AsCallable();

            // Convert C# Image to NumPy array
            var npInputImage = ImageToNumpyArray(greyImage1);
            // Run the Python binarization function
            var npResult = binariseFunc.Invoke(npInputImage);
            // Convert back to C# Image
            var resultImage = NumpyArrayToImage(npResult.As<numpy.ndarray>());

            pictureBox1.Image = resultImage;
        }
    }
    catch (Exception ex)
    {
        messageL.Text = $"Error: {ex.Message}\nFull Details: {ex.StackTrace}";
    }
    finally
    {
        this.Cursor = Cursors.Default;
    }
}

Extra Checks to Ensure Success

  • Match Platforms: Make sure your C# project is set to x64 (Anaconda is almost always 64-bit)—go to Project Properties → Build → Platform target → x64.
  • Verify Python.NET Version: Install a compatible version via NuGet (for Python 3.8+, use Python.NET 3.0+).
  • Test Python Script Alone: Run your myfunction.py in Anaconda first to confirm it works with a sample NumPy array (e.g., create a test array with np.random.randint(0,255,(100,100)) and call binarise).

That should resolve the Delegates initializer error and get your image processing working smoothly!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:52:34