检测效果如下(模型数据集为MVTecDataset的bottle类):

模型信息如下:

///Form2.Designer.cs

using System.Drawing;
using System.Windows.Forms;
using System;

namespace yolo_world_opencvsharp_net4._8
{
    partial class Form2
    {
        private System.ComponentModel.IContainer components = null;
        private PictureBox originalImageBox;
        private PictureBox anomalyMapBox;
        private PictureBox predMaskBox;
        private Button loadImageButton;
        private Button inferenceButton;
        private Label scoreLabel;
        private Label labelLabel;
        private ProgressBar progressBar;

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.originalImageBox = new System.Windows.Forms.PictureBox();
            this.anomalyMapBox = new System.Windows.Forms.PictureBox();
            this.predMaskBox = new System.Windows.Forms.PictureBox();
            this.loadImageButton = new System.Windows.Forms.Button();
            this.inferenceButton = new System.Windows.Forms.Button();
            this.scoreLabel = new System.Windows.Forms.Label();
            this.labelLabel = new System.Windows.Forms.Label();
            this.progressBar = new System.Windows.Forms.ProgressBar();
            this.elapsedTimeLabel = new System.Windows.Forms.Label();
            ((System.ComponentModel.ISupportInitialize)(this.originalImageBox)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.anomalyMapBox)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.predMaskBox)).BeginInit();
            this.SuspendLayout();
            // 
            // originalImageBox
            // 
            this.originalImageBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.originalImageBox.Location = new System.Drawing.Point(20, 18);
            this.originalImageBox.Name = "originalImageBox";
            this.originalImageBox.Size = new System.Drawing.Size(256, 236);
            this.originalImageBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.originalImageBox.TabIndex = 0;
            this.originalImageBox.TabStop = false;
            // 
            // anomalyMapBox
            // 
            this.anomalyMapBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.anomalyMapBox.Location = new System.Drawing.Point(300, 18);
            this.anomalyMapBox.Name = "anomalyMapBox";
            this.anomalyMapBox.Size = new System.Drawing.Size(256, 236);
            this.anomalyMapBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.anomalyMapBox.TabIndex = 1;
            this.anomalyMapBox.TabStop = false;
            // 
            // predMaskBox
            // 
            this.predMaskBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.predMaskBox.Location = new System.Drawing.Point(580, 18);
            this.predMaskBox.Name = "predMaskBox";
            this.predMaskBox.Size = new System.Drawing.Size(256, 236);
            this.predMaskBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.predMaskBox.TabIndex = 2;
            this.predMaskBox.TabStop = false;
            // 
            // loadImageButton
            // 
            this.loadImageButton.Location = new System.Drawing.Point(20, 277);
            this.loadImageButton.Name = "loadImageButton";
            this.loadImageButton.Size = new System.Drawing.Size(100, 28);
            this.loadImageButton.TabIndex = 3;
            this.loadImageButton.Text = "加载图像";
            this.loadImageButton.Click += new System.EventHandler(this.LoadImageButton_Click);
            // 
            // inferenceButton
            // 
            this.inferenceButton.Enabled = false;
            this.inferenceButton.Location = new System.Drawing.Point(140, 277);
            this.inferenceButton.Name = "inferenceButton";
            this.inferenceButton.Size = new System.Drawing.Size(100, 28);
            this.inferenceButton.TabIndex = 4;
            this.inferenceButton.Text = "开始推理";
            this.inferenceButton.Click += new System.EventHandler(this.InferenceButton_Click);
            // 
            // scoreLabel
            // 
            this.scoreLabel.Location = new System.Drawing.Point(20, 323);
            this.scoreLabel.Name = "scoreLabel";
            this.scoreLabel.Size = new System.Drawing.Size(300, 18);
            this.scoreLabel.TabIndex = 5;
            this.scoreLabel.Text = "异常分数: ";
            // 
            // labelLabel
            // 
            this.labelLabel.Location = new System.Drawing.Point(20, 351);
            this.labelLabel.Name = "labelLabel";
            this.labelLabel.Size = new System.Drawing.Size(300, 18);
            this.labelLabel.TabIndex = 6;
            this.labelLabel.Text = "预测标签: ";
            // 
            // progressBar
            // 
            this.progressBar.Location = new System.Drawing.Point(20, 388);
            this.progressBar.Name = "progressBar";
            this.progressBar.Size = new System.Drawing.Size(800, 18);
            this.progressBar.TabIndex = 7;
            this.progressBar.Visible = false;
            // 
            // elapsedTimeLabel
            // 
            this.elapsedTimeLabel.AutoSize = true;
            this.elapsedTimeLabel.Location = new System.Drawing.Point(580, 292);
            this.elapsedTimeLabel.Name = "elapsedTimeLabel";
            this.elapsedTimeLabel.Size = new System.Drawing.Size(41, 12);
            this.elapsedTimeLabel.TabIndex = 8;
            this.elapsedTimeLabel.Text = "耗时:";
            // 
            // Form2
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(864, 426);
            this.Controls.Add(this.elapsedTimeLabel);
            this.Controls.Add(this.originalImageBox);
            this.Controls.Add(this.anomalyMapBox);
            this.Controls.Add(this.predMaskBox);
            this.Controls.Add(this.loadImageButton);
            this.Controls.Add(this.inferenceButton);
            this.Controls.Add(this.scoreLabel);
            this.Controls.Add(this.labelLabel);
            this.Controls.Add(this.progressBar);
            this.Name = "Form2";
            this.Text = "AnomalibSeg 异常检测";
            ((System.ComponentModel.ISupportInitialize)(this.originalImageBox)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.anomalyMapBox)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.predMaskBox)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        private Label elapsedTimeLabel;
    }
}

///Form2.cs

using OpenCvSharp;
using OpenCvSharp.Extensions;
using OpenVinoSharp;
using OpenVinoSharp.Extensions.process;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Size = OpenCvSharp.Size;

namespace yolo_world_opencvsharp_net4._8
{
    public partial class Form2 : Form
    {
        private Core core;
        private Model model;
        private CompiledModel compiledModel;
        private InferRequest inferRequest;

        private string imagePath;
        private Mat originalImage;
        private Mat processedImage;

        private const int INPUT_WIDTH = 256;
        private const int INPUT_HEIGHT = 256;
        private const string MODEL_PATH = @"D:\3D\patchcore.onnx";

        public Form2()
        {
            InitializeComponent();
            InitializeModel();
        }

        private void InitializeModel()
        {
            try
            {
                progressBar.Visible = true;
                progressBar.Style = ProgressBarStyle.Marquee;

                // 初始化OpenVINO运行时
                core = new Core();

                // 加载模型
                model = core.read_model(MODEL_PATH);

                // 编译模型
                compiledModel = core.compile_model(model, "CPU");

                // 创建推理请求
                inferRequest = compiledModel.create_infer_request();

                progressBar.Visible = false;
                MessageBox.Show("模型加载成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                progressBar.Visible = false;
                MessageBox.Show($"模型加载失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void LoadImageButton_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "图像文件|*.jpg;*.jpeg;*.png;*.bmp";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    imagePath = openFileDialog.FileName;
                    originalImage = new Mat(imagePath);

                    // 显示原图
                    originalImageBox.Image = MatToBitmap(originalImage);
                    inferenceButton.Enabled = true;
                }
            }
        }

        private void InferenceButton_Click(object sender, EventArgs e)
        {
            if (originalImage == null)
            {
                MessageBox.Show("请先加载图像!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            try
            {
                progressBar.Visible = true;
                progressBar.Style = ProgressBarStyle.Marquee;
                Stopwatch sw = Stopwatch.StartNew();
                // 预处理图像
                processedImage = PreprocessImage(originalImage);

                // 执行推理
                var results = PerformInference(processedImage);

                sw.Stop();
                elapsedTimeLabel.Text = sw.ElapsedMilliseconds.ToString() + "ms";
                // 显示结果
                DisplayResults(results);

                progressBar.Visible = false;
            }
            catch (Exception ex)
            {
                progressBar.Visible = false;
                MessageBox.Show($"推理失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private Mat PreprocessImage(Mat image)
        {
            // 调整大小
            Mat resized = new Mat();
            Cv2.Resize(image, resized, new Size(INPUT_WIDTH, INPUT_HEIGHT));

            // 转换颜色空间 BGR -> RGB
            Mat rgb = new Mat();
            Cv2.CvtColor(resized, rgb, ColorConversionCodes.BGR2RGB);

            // 归一化 [0,255] -> [0,1]
            Mat normalized = new Mat();
            rgb.ConvertTo(normalized, MatType.CV_32FC3, 1.0 / 255.0);

            rgb.Dispose();
            resized.Dispose();

            return normalized;
        }

        private InferenceResults PerformInference(Mat input)
        {
            // 获取输入张量
            using (Tensor inputTensor = inferRequest.get_input_tensor(0))
            {
                // 准备输入数据
                float[] inputData = Permute.run(input);

                // 设置输入数据
                inputTensor.set_shape(new Shape(1, 3, 256, 256));
                inputTensor.set_data(inputData);

                // 执行推理
                inferRequest.infer();
            }

            // 获取输出结果
            using (Tensor predScoreTensor = inferRequest.get_tensor("pred_score"))
            using (Tensor predLabelTensor = inferRequest.get_tensor("pred_label"))
            using (Tensor anomalyMapTensor = inferRequest.get_tensor("anomaly_map"))
            using (Tensor predMaskTensor = inferRequest.get_tensor("pred_mask"))
            {
                //var PredScore = predScoreTensor.get_data<float>((int)predScoreTensor.get_size());
                //var PredLabel = predLabelTensor.get_data<byte>((int)predLabelTensor.get_size());
                //var AnomalyMap = anomalyMapTensor.get_data<float>((int)anomalyMapTensor.get_size());
                //var PredMask = predMaskTensor.get_data<byte>((int)predMaskTensor.get_size());

                return new InferenceResults
                {
                    PredScore = predScoreTensor.get_data<float>((int)predScoreTensor.get_size()),
                    PredLabel = predLabelTensor.get_data<byte>((int)predLabelTensor.get_size()),
                    AnomalyMap = anomalyMapTensor.get_data<float>((int)anomalyMapTensor.get_size()),
                    PredMask = predMaskTensor.get_data<byte>((int)predMaskTensor.get_size())
                };
                
            }
        }

        private void DisplayResults(InferenceResults results)
        {
            // 显示异常分数和预测标签
            scoreLabel.Text = $"异常分数: {results.PredScore[0]:F4}";
            labelLabel.Text = $"预测标签: {(results.PredLabel[0]>0 ? "异常" : "正常")}";

            // 处理异常图
            if (results.AnomalyMapDims != null && results.AnomalyMapDims.Length >= 2)
            {
                int height = (int)results.AnomalyMapDims[1];
                int width = (int)results.AnomalyMapDims[2];

                Mat anomalyMap = new Mat(height, width, MatType.CV_32FC1, results.AnomalyMap);
                Mat anomalyMapColored = ApplyColorMap(anomalyMap);
                anomalyMapBox.Image = MatToBitmap(anomalyMapColored);

                anomalyMap.Dispose();
                anomalyMapColored.Dispose();
            }

            // 处理预测掩码
            if (results.PredMaskDims != null && results.PredMaskDims.Length >= 2)
            {
                int height = (int)results.PredMaskDims[1];
                int width = (int)results.PredMaskDims[2];

                Mat predMask = new Mat(height, width, MatType.CV_8UC1);
                byte[] maskData = new byte[results.PredMask.Length];
                for (int i = 0; i < results.PredMask.Length; i++)
                {
                    maskData[i] = results.PredMask[i];
                }
                predMask.SetArray(maskData);

                predMaskBox.Image = MatToBitmap(predMask*255);
                predMask.Dispose();
            }
        }

        private Mat ApplyColorMap(Mat anomalyMap)
        {
            // 归一化到[0,1]
            Mat normalized = new Mat();
            Cv2.Normalize(anomalyMap, normalized, 0, 1, NormTypes.MinMax);

            // 转换为8位
            Mat u8 = new Mat();
            normalized.ConvertTo(u8, MatType.CV_8UC1, 255);

            // 应用Jet色彩映射
            Mat colored = new Mat();
            Cv2.ApplyColorMap(u8, colored, ColormapTypes.Jet);

            normalized.Dispose();
            u8.Dispose();

            return colored;
        }

        private Bitmap MatToBitmap(Mat mat)
        {
            if (mat.Channels() == 1)
            {
                return mat.ToBitmap();
            }
            else
            {
                // 确保颜色顺序正确 (OpenCV使用BGR,.NET使用RGB)
                Mat rgb = new Mat();
                Cv2.CvtColor(mat, rgb, ColorConversionCodes.BGR2RGB);
                Bitmap bitmap = rgb.ToBitmap();
                rgb.Dispose();
                return bitmap;
            }
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            // 清理资源
            originalImage?.Dispose();
            processedImage?.Dispose();
            inferRequest?.Dispose();
            compiledModel?.Dispose();
            model?.Dispose();
            core?.Dispose();

            base.OnFormClosing(e);
        }
    }

    // 推理结果数据结构
    public class InferenceResults
    {
        public float[] PredScore { get; set; }
        public byte[] PredLabel { get; set; }
        public float[] AnomalyMap { get; set; }
        public byte[] PredMask { get; set; }

        // 维度信息(根据实际模型输出调整)
        public long[] AnomalyMapDims => new long[] { 1, 256, 256, 1 }; // 示例维度
        public long[] PredMaskDims => new long[] { 1, 256, 256, 1 };   // 示例维度
    }
}

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐