C# OpenvinoSharp使用Anomalib的PatchCore算法进行缺陷检测

C# OpenvinoSharp使用Anomalib的PatchCore算法进行缺陷检测

检测效果如下(模型数据集为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 };   // 示例维度
    }
}

Read more

HDFS数据块机制深度解析:块大小设计与存储哲学

HDFS数据块机制深度解析:块大小设计与存储哲学

HDFS数据块机制深度解析:块大小设计与存储哲学 * 引言:块——HDFS存储的核心抽象 * 一、HDFS默认块大小 * 1.1 版本演进与默认值 * 1.2 查看和验证块大小 * 1.3 配置文件中的设置 * 二、为什么HDFS采用块存储? * 2.1 核心设计思想 * 2.2 详细解析:为什么块存储如此重要? * **2.2.1 减少寻址开销,提升I/O效率** * **2.2.2 支持超大文件,超越单机限制** * **2.2.3 简化存储设计,降低元数据复杂度** * **2.2.4 便于数据复制,增强容错性** * **2.2.5 支持数据本地性,

By Ne0inhk
算法王冠上的明珠——动态规划之斐波那契数列问题

算法王冠上的明珠——动态规划之斐波那契数列问题

目录 1. 什么是动态规划 2. 动态规划步骤 状态表示 状态转移方程 初始化 填表顺序 返回值 3. 例题讲解及具体代码 3.1 LeetCode1137. 第 N 个泰波那契数 这篇文章是我第一篇关于动态规划的,所以我会先从什么是动态规划说起。 1. 什么是动态规划 动态规划是一种通过将复杂问题分解为重叠子问题,并利用子问题的解来高效求解原问题的算法思想。它的核心是避免重复计算,通过存储中间结果(即 “记忆化”)来优化时间复杂度。 其实简单来说就是通过前面的状态来定义后面的状态,比如说我们前面关于前缀和的文章其实就可以被归为动态规划的一种,只不过它比较简单,所以我把它放在了基础算法里面。 2. 动态规划步骤 做动态规划类题目的步骤就是下面这几步。 状态表示 状态表示就是我们数组对应的那个位置的值的含义,简单来说就是那个值代表着什么。比如说我们前面说的前缀和,那他的状态表示就是代表着原数组前面这些数的累加。 状态转移方程 状态转移方程就是根据上面的状态表示来得到的一个公式,比如说我们前面说的前缀和,它的状态转移方程就是dp[i]=dp[i

By Ne0inhk

优选算法——二分查找

👇作者其它专栏 《数据结构与算法》《算法》《C++起始之路》 二分查找相关题解 1.二分查找 算法思路: a.定义left,right指针,分别指向数组的左右区间。 b.找到待查找区间的中间点mid,找到后分三种情况讨论:         i.arr[mid]==target说明正好找到,返回mid的值;         ii.arr[mid]>target说明[mid,right]这段区间都是大于target的,因此舍去右边区间,在左边[left,mid-1]的区间继续查找,即让right=mid-1,然后重复b过程;         iii.arr[mid]<target说明[left,mid]这段区间的值都是小于target的,因此舍去左边区间,在右边区间[mid+1,right]

By Ne0inhk
【2025 最新】 Python 安装教程 以及 Pycharm 安装教程(超详细图文指南,附常见问题解决)

【2025 最新】 Python 安装教程 以及 Pycharm 安装教程(超详细图文指南,附常见问题解决)

前言         Python 作为目前最热门的编程语言之一,在数据分析、人工智能、Web 开发等领域应用广泛。而 PyCharm 作为 JetBrains 推出的 Python 集成开发环境(IDE),以其强大的功能和友好的界面成为开发者的首选工具。         本文针对 2025 年最新版 Python(3.13.x)和 PyCharm(202x.x.x),提供Windows 10或11和macOS Sonoma双系统安装教程,从官网下载到环境配置一步到位,同时整理了安装过程中最常见的 10 类问题及解决方案,确保新手也能顺利完成环境搭建。 一、Python 安装教程(2025 最新版) 1. 下载 Python 安装包 步骤 1:访问 Python 官网

By Ne0inhk