欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

第一:C# 嵌入 Python 脚本进行图像处理并返回 C# 的构思和实现。

最编程 2024-10-14 06:57:20
...

人生苦短python续命,听闻各大国产图像处理程序支持python ;而我用的海康VM是支持C#脚本的;但是原生并不支持python做图像处理;

于是心生一计; C#通过pythonnet嵌入并调用python不就可以???  只需要实现对应图像类型转换;

而前面已经讲过 python 里面 使用.net 的图像处理方法; 函数前面已经用python写好了可以直接由C#调用并直接返回 C#支持的 Bitmap 图像 (双向的) ;当然这个py写的可以直接在py里面使用;由于pythonnet是C#和python的桥梁 那么 Bitmap 和 numpy格式的图像是 两者都支持的;

但是这样有个缺点就是python和C#都要安装pythonnet 而只安装C#端pythonnet是不行的;

假设在C#端导入并调用py的模块 bitmap_to_mat; mat_to_bitmap;这两个函数 那么他是依赖C#端和py端的pythonnet的;我并不想说的太绕口 ;总之 C# py 都要装pythonnet

直接先python模块:这个模块完全是为了给C#调用:

import os,sys,time,copy,socket,_thread,threading
import cv2,qrcode
import numpy as np
from PIL import Image
#region 初始化CLR环境
import clr,System
from System.IO import MemoryStream
clr.AddReference("System.Drawing")
clr.AddReference("System.Windows.Forms")
import System.Drawing
from System.Drawing import Bitmap, Imaging
import System.Drawing.Imaging
import System.Windows.Forms as Forms
# 这部分是 .NET的东西  #region# 初始化CLR环境
def getnowtime(): return f"{time.strftime('%Y-%m-%d_%H_%M_%S')}"
def bitmap_to_mat(bitmap,flag=False):
    r"""   
    System.Drawing.Bitmap对象
    转换为
    opencv 图像
    """
    stream = MemoryStream()
    bitmap.Save(stream, bitmap.RawFormat)
    stream.Position = 0
    bitmap_data = np.frombuffer(stream.ToArray(), dtype=np.uint8)
    stream.Close() #一定要
    mat = cv2.imdecode(bitmap_data, cv2.IMREAD_COLOR)
    if  flag :
        gray_mat = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY)
        return gray_mat
    bgr_mat = mat #imdecode #已经是BGR 所以 不需要#bgr_mat = cv2.cvtColor(mat, cv2.COLOR_RGB2BGR)  
    return bgr_mat
def mat_to_bitmap(cv_image):
    r"""
    opencv 图像   
    转换为
    System.Drawing.Bitmap对象
    """
    cv_image_rgb = cv_image#imencode  imdecode 已经是BGR 所以 不需要cv2.COLOR_BGR2RGB
    h, w, c = cv_image_rgb.shape# 创建一个与图像数据相匹配的numpy数组
    numpy_array = np.array(cv_image_rgb, dtype=np.uint8).reshape((h, w, c))
    stream = MemoryStream()# 创建一个MemoryStream对象并将numpy数组写入
    cv2.imencode('.png', numpy_array)[1].tobytes()
    stream.Write(cv2.imencode('.png', numpy_array)[1].tobytes(), 0, len(cv2.imencode('.png', numpy_array)[1].tobytes()))
    stream.Position = 0
    bitmap = Bitmap.FromStream(stream)# 使用.NET的System.Drawing命名空间中的Bitmap类从MemoryStream创建Bitmap对象
    stream.Close()# 清理资源
    return bitmap # 现在有一个System.Drawing.Bitmap对象,可以在.NET环境中使用
def imageprocess(mat):
    r"""
    1	水平翻转
    0	垂直翻转
    -1	水平垂直翻转
    """
    h_flip = cv2.flip(mat, 1)
    v_flip = cv2.flip(mat, 0)
    hv_flip = cv2.flip(mat, -1) 
    return h_flip #

好了 现在当他是一个DLL 或者包吧;

然后:调用它:

using System.Net;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System;
using System.IO;
using Python.Runtime; // 这个是 nuget下载的,并不是python安装目录里那个dll
using SC = System.Console;
using System.Drawing;
using System.Drawing.Imaging;
using System.Diagnostics;


namespace cspy
{
    internal  class Program
    {
        static string pythonHomePath = @"C:\Users\Administrator\AppData\Local\Programs\Python\Python38";
        // 这是我的python安装路径; 
        // 如果不想安装python 理论上可以将 python解释器连同依赖文件复制在C#工程文件跟目录
    
        /**/
       

        static string dllPath = pythonHomePath + @"\python38.dll";
        static string[] py_paths =
        {
            "DLLs",
            "Lib",
            "Lib/site-packages",
            "Lib/site-packages/win32" ,
            "Lib/site-packages/win32/lib",
            "Lib/site-packages/Pythonwin"
            };
        public static readonly string Semicolon = ";";
        static string pySearchPath = pythonHomePath + Semicolon;

        static void Main(string[] args)
        {
            foreach (string p in py_paths)
            {
                pySearchPath += pythonHomePath + "//" + p + Semicolon;
            }
            System.Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", dllPath);
            PythonEngine.PythonHome = pythonHomePath;
            PythonEngine.PythonPath = pySearchPath;
            PythonEngine.Initialize();

            //Python.Runtime.dll
            //netstandard.dll
            //Microsoft.CSharp.dll
            /*  //"Python.Runtime.dll","netstandard.dll"","Microsoft.CSharp.dll"*/

            // 初始化Python引擎


            // 导入Python中的numpy和cv2库
            dynamic np = Py.Import("numpy");
            dynamic cv2 = Py.Import("cv2");
            dynamic sys = Py.Import("sys");
            sys.path.append("C:\\Users\\Administrator\\Desktop\\VM_00\\VM_脚本嵌入python处理图像");// 模块路径
            
            dynamic pynModule = Py.Import("pyn"); //
            dynamic CreateQR = pynModule.CreateQR();// 

            dynamic vision = Py.Import("vision_converte"); // 导入模块 

            // 图像处理在英文中通常被称为 "image processing"。

            Bitmap bitmap = new Bitmap("lena.jpg");// 创建一个C#中的Bitmap对象

            // 调用Python函数
            dynamic mat = vision.bitmap_to_mat(bitmap, false); // 第二个参数根据需要设置

            // 可以在这里进行进一步的图像处理 我脑子一片空白 演示一个翻转

            dynamic matprocess = vision.imageprocess(mat); // python 里面进行翻转

            Bitmap convertedBitmap = vision.mat_to_bitmap(matprocess);// 将py Mat对象转换回Bitmap

            dynamic getnowtime = vision.getnowtime();
            string strgetnowtime = getnowtime;

            convertedBitmap.Save("converted_image"+ strgetnowtime + ".png", ImageFormat.Png); //图像返回给C# 我这里只保存 保存的是翻转的图; 
          
            
            convertedBitmap.Dispose(); // 释放Bitmap资源
            PythonEngine.Shutdown();// 关闭Python引擎
           // SC.WriteLine("____结束");SC.ReadKey();

            
            //########### wait #############    //##################################################################################################
        }//Main

    }
}

注释已经很清楚了; 

当然还有一些问题 看一眼就能发现

推荐阅读