C# PaddleInference 图片旋转角度检测

news2024/9/22 4:16:11

效果

项目

 VS2022+.net4.8+ OpenCvSharp4+Sdcb.PaddleInference

 代码

using OpenCvSharp;
using Sdcb.PaddleInference;
using Sdcb.PaddleInference.Native;
using System;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace PaddleInference_图片旋转角度检测
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Bitmap bmp;
        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string img = "";
        string startupPath = "";

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        PaddlePredictor predictor;
        float rotateThreshold = 0.50f;
        InputShape defaultShape = new InputShape(3, 224, 224);

        private unsafe void Form1_Load(object sender, EventArgs e)
        {
            startupPath = Application.StartupPath;

            IntPtr _ptr = PaddleNative.PD_ConfigCreate();

            Encoding PaddleEncoding = Environment.OSVersion.Platform == PlatformID.Win32NT ? Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.ANSICodePage) : Encoding.UTF8;

            //设置推理模型路径
            String programPath = Application.StartupPath + "\\models\\inference.pdmodel";
            String paramsPath = Application.StartupPath + "\\models\\inference.pdiparams";

            byte[] programBytes = PaddleEncoding.GetBytes(programPath);
            byte[] paramsBytes = PaddleEncoding.GetBytes(paramsPath);
            fixed (byte* programPtr = programBytes)
            fixed (byte* paramsPtr = paramsBytes)

            PaddleNative.PD_ConfigSetModel(_ptr, (IntPtr)programPtr, (IntPtr)paramsPtr);
            PaddleNative.PD_ConfigEnableMKLDNN(_ptr);

            predictor = new PaddlePredictor(PaddleNative.PD_PredictorCreate(_ptr));
        }


        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;

            img = ofd.FileName;
            bmp = new Bitmap(img);
            pictureBox1.Image = new Bitmap(img);
            textBox1.Text = "";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (img == "") { return; }
            Mat src = OpenCvSharp.Extensions.BitmapConverter.ToMat(new Bitmap(pictureBox1.Image));
            Cv2.CvtColor(src, src, ColorConversionCodes.RGBA2RGB);//mat转三通道mat
            dt1 = DateTime.Now;

            Mat resized = ResizePadding(src, defaultShape);
            Mat normalized = Normalize(resized);

            using (PaddleTensor input = predictor.GetInputTensor(predictor.InputNames[0]))
            {
                input.Shape = new[] { 1, 3, normalized.Rows, normalized.Cols };
                float[] data = ExtractMat(normalized);
                input.SetData(data);
            }

            normalized.Dispose();
            resized.Dispose();

            if (!predictor.Run())
            {
                throw new Exception("PaddlePredictor(Classifier) run failed.");
            }

            RotationDegree r = RotationDegree._0;

            using (PaddleTensor output = predictor.GetOutputTensor(predictor.OutputNames[0]))
            {
                float[] softmax = output.GetData<float>();
                float max = softmax.Max();
                int maxIndex = Array.IndexOf(softmax, max);
                if (max > rotateThreshold)
                {
                    r = (RotationDegree)maxIndex;
                }
            }

            dt2 = DateTime.Now;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("图片旋转角度:" + r.ToString());
            sb.AppendLine("--------------------");
            sb.AppendLine("耗时:" + (dt2 - dt1).TotalMilliseconds + "ms");
            textBox1.Text = sb.ToString();
        }

        private float[] ExtractMat(Mat src)
        {
            int rows = src.Rows;
            int cols = src.Cols;
            float[] result = new float[rows * cols * 3];
            GCHandle resultHandle = default;
            try
            {
                resultHandle = GCHandle.Alloc(result, GCHandleType.Pinned);
                IntPtr resultPtr = resultHandle.AddrOfPinnedObject();
                for (int i = 0; i < src.Channels(); ++i)
                {
                    Mat dest = new Mat(rows, cols, MatType.CV_32FC1, resultPtr + i * rows * cols * sizeof(float));
                    Cv2.ExtractChannel(src, dest, i);
                    dest.Dispose();
                }
            }
            finally
            {
                resultHandle.Free();
            }
            return result;
        }

        private Mat ResizePadding(Mat src, InputShape shape)
        {
            OpenCvSharp.Size srcSize = src.Size();
            Mat roi = srcSize.Width / srcSize.Height > shape.Width / shape.Height ?
                src[0, srcSize.Height, 0, (int)Math.Floor(1.0 * srcSize.Height * shape.Width / shape.Height)] :
                src.Clone();
            double scaleRate = 1.0 * shape.Height / srcSize.Height;
            Mat resized = roi.Resize(new OpenCvSharp.Size(Math.Floor(roi.Width * scaleRate), shape.Height));
            if (resized.Width < shape.Width)
            {
                Cv2.CopyMakeBorder(resized, resized, 0, 0, 0, shape.Width - resized.Width, BorderTypes.Constant, Scalar.Black);
            }
            roi.Dispose();
            return resized;
        }

        private Mat Normalize(Mat src)
        {
            Mat normalized = new Mat();
            src.ConvertTo(normalized, MatType.CV_32FC3, 1.0 / 255);
            Mat[] bgr = normalized.Split();
            float[] scales = new[] { 2.0f, 2.0f, 2.0f };
            float[] means = new[] { 0.5f, 0.5f, 0.5f };
            for (int i = 0; i < bgr.Length; ++i)
            {
                bgr[i].ConvertTo(bgr[i], MatType.CV_32FC1, 1.0 * scales[i], (0.0 - means[i]) * scales[i]);
            }

            normalized.Dispose();

            Mat dest = new Mat();
            Cv2.Merge(bgr, dest);

            foreach (Mat channel in bgr)
            {
                channel.Dispose();
            }

            return dest;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (bmp == null)
            {
                return;
            }

            var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
            Cv2.CvtColor(mat, mat, ColorConversionCodes.RGBA2RGB);
            Cv2.Rotate(mat, mat, RotateFlags.Rotate90Clockwise);
            var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
            pictureBox1.Image = bitmap;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (bmp == null)
            {
                return;
            }

            var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
            Cv2.CvtColor(mat, mat, ColorConversionCodes.RGBA2RGB);
            Cv2.Rotate(mat, mat, RotateFlags.Rotate180);
            var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
            pictureBox1.Image = bitmap;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (bmp == null)
            {
                return;
            }

            var mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp);
            Cv2.CvtColor(mat, mat, ColorConversionCodes.RGBA2RGB);
            Cv2.Rotate(mat, mat, RotateFlags.Rotate90Counterclockwise);
            var bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
            pictureBox1.Image = bitmap;
        }

    }

    /// <summary>
    /// Represents the shape of input data for a rotation detection model.
    /// </summary>
    public readonly struct InputShape
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="InputShape"/> struct.
        /// </summary>
        /// <param name="channel">The number of color channels in the input image.</param>
        /// <param name="width">The width of the input image in pixels.</param>
        /// <param name="height">The height of the input image in pixels.</param>
        public InputShape(int channel, int width, int height)
        {
            Channel = channel;
            Height = height;
            Width = width;
        }

        /// <summary>
        /// Gets the number of color channels in the input image.
        /// </summary>
        public int Channel { get; }

        /// <summary>
        /// Gets the height of the input image in pixels.
        /// </summary>
        public int Height { get; }

        /// <summary>
        /// Gets the width of the input image in pixels.
        /// </summary>
        public int Width { get; }
    }

    /// <summary>
    /// Enum representing the degrees of rotation.
    /// </summary>
    public enum RotationDegree
    {
        /// <summary>
        /// Represents the 0-degree rotation angle.
        /// </summary>
        _0,
        /// <summary>
        /// Represents the 90-degree rotation angle.
        /// </summary>
        _90,
        /// <summary>
        /// Represents the 180-degree rotation angle.
        /// </summary>
        _180,
        /// <summary>
        /// Represents the 270-degree rotation angle.
        /// </summary>
        _270,
    }

}

Demo下载 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

14天学会:基于J2EE的JAVA WEB基础

系列文章 手把手教你&#xff1a;基于Django的新闻文本分类可视化系统&#xff08;文本分类由bert实现&#xff09; 手把手教你&#xff1a;基于python的文本分类&#xff08;sklearn-决策树和随机森林实现&#xff09; 手把手教你&#xff1a;岩石样本智能识别系统 一、学习…

港联证券|股票长线投资技巧?

股票长线出资主要是看股票长时间的开展&#xff0c;所以主张从以下几个方面来剖析&#xff1a; 1、经济环境 把握宏观经济大势。股市是宏观经济的风向标&#xff0c;它在宏观经济的大环境中开展&#xff0c;而且经济的变动趋势也会影响长时间出资的收益。假如出资者能够把握住…

【java】修改JsonObject中的属性值

Java修改JsonObject中的属性值 <!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.16</version></dependency>例子 public static void m…

设计师都在找的在线SVG编辑工具!赶快收藏

为了方便设计师编辑和修改SVG图形&#xff0c;本文将介绍5款易于使用的在线SVG编辑工具&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时设计是一款强大的在线SVG编辑工具&#xff0c;它可以支持路径编辑、形状编辑、填充和边框编辑、文本编辑等多种编辑需求&#xff…

人工智能套装 Ai Kit 横向测评

本文涉及到的产品 1 mechArm 270 2 mycobot 280 3 mypalletizer 260 4 AI kit 主题内容 今天的文章的主题主要介绍一下跟aikit 套件搭配的三款机械臂&#xff0c;它们之间分别有什么不一样的地方。 前言 假如说你有一台机械臂的话&#xff0c;你会用它来干什么呢&#…

【Django学习】(十一)APIView_请求与响应_GenericAPIView

继承DRF中APIView之后&#xff0c;那么当前视图就具备了认证、授权、限流等功能 继承DRF中APIView之后&#xff0c;每一个实例方法中的request为Request对象 Request类拓展了Django中的HttpRequest类&#xff0c;具备很多额外优秀的功能Request类与HttpRequest类中的所有功能兼…

2022年06月份青少年软件编程Scratch图形化等级考试试卷二级真题(含答案)

2022-06 Scratch真题二级 分数&#xff1a;100 题数&#xff1a;37 一、单选题(共25题&#xff0c;共50分) 1.角色初始位置如图所示&#xff0c;下面哪个选项能让角色移到舞台的左下角&#xff1f;&#xff08; &#xff09;(2分) A. B. C. D. 2.点击绿旗&#xff0c;执…

【面试题27】Redis中的connect和pconnect如何使用,有什么区别

文章目录 一、背景二、connect函数三、pconnect函数四、区别和使用场景五、总结 一、背景 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖PHP开发领域所有的面试题&#xff0c;对标资深工程师/架构师序列&#xff0c;欢迎大家提前关注锁定。 Redis是一个开…

六、HAL_Timer的PWM功能

1、开发环境 (1)Keil MDK: V5.38.0.0 (2)STM32CubeMX: V6.8.1 (3)MCU: STM32F407XGT6 2、PWM简介 2.1、什么是PWM (1)PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用&#xff0c;方波的占空比被调制用来对一个具体模拟信号的电平进行编码。 (2)P…

Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling

感想&#xff1a;由于看不懂官方代码的原因&#xff0c;自己这方面耽误了一段时间&#xff0c;一方面&#xff0c;在AI与经济学之间犹豫了许久&#xff0c;另一方面&#xff0c;工作 了半年&#xff0c;也没发工资&#xff0c;没空找培训代码的课程&#xff0c;所以停止更新了三…

Nginx-代理服务器详解

本文已收录于专栏 《中间件合集》 目录 概念说明Nginx代理 提供服务总结提升 概念说明 Nginx Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。它具有很多非常优越的特性&#xff1a;在连接高并发的情况下&#xff0c;Nginx是Aoache服…

机器学习算法之决策树(decision tree)

1 决策树算法介绍 决策树(Decision Tree,又称为判定树)算法是机器学习中常见的一类算法&#xff0c;是一种以树结构形式表达的预测分析模型。决策树属于监督学习&#xff08;Supervised learning&#xff09;&#xff0c;根据处理数据类型的不同&#xff0c;决策树又为分类决策…

html 模板

模板王 - 10000免费网页模板&#xff0c;网站模板下载大全 (mobanwang.com)http://www.mobanwang.com/

C++ string中内置的字符串操作和标准库中常用字符处理函数

&#x1f4af; 博客内容&#xff1a;C读取一行内个数不定的整数的方式 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&…

Qt之QDialog 自定义标题栏

简述 Qt自带标题栏功能还是很强大的&#xff0c;但是确实不能百分百满足需求&#xff0c;除了丑以外还不能随意更改标题栏字体&#xff0c;也不能更改样式&#xff1b;所以为了满足自己的虚荣心让标题栏变得更加好用看好看&#xff0c;特地花时间做了以下测试&#xff1b; 支持…

SpringBoot通过获取请求参数或者Headers上的特殊标识实现i18n国际化

实现效果 我们大部分都是把i18n的标识放在Headers上面&#xff1b;而把标识放在参数上的话比较少&#xff0c;放参数上的话一般是在使用a标签下载某些文件不好配置请求头的时候才使用上 配置在Headers上面&#xff1a; 配置在params上面&#xff1a; 配置代码&#xff1a; /**…

Django_类视图(五)

目录 类视图优点 使用方法 定义类视图 添加类视图路由 类视图原理 类视图的二次封装 类视图二次封装代码如下 编写视图 配置路由 访问url结果 源码等资料获取方法 类视图优点 使用django的函数视图&#xff0c;如果要让同一个视图实现不同的请求方式实现不同的逻辑…

Android Studio实现内容丰富的安卓社交论坛平台

如需源码可以添加q-------3290510686&#xff0c;也有演示视频演示具体功能&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号085 1.开发环境 android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看公告 3.视…

静态路由介绍

目录 静态路由配置方法&#xff08;基本配置&#xff09;&#xff1a; 静态路由的拓展配置 负载均衡 1.环回接口——测试 2.手工汇总——子网汇总 3.路由黑洞&#xff08;黑洞路由) 4.缺省路由 5.空接口——NULL 0 静态路由配置方法&#xff08;基本配置&#xff09;&#xff1…

【Linux】Linux下的项目自动化构建工具——make和makefile

❤️前言 大家好&#xff0c;好久不见&#xff01;今天小狮子为大家带来的文章是一篇关于Linux下的项目自动化构建工具——make和makefile的博客&#xff0c;希望能帮助到大家。 正文 当我们进行涉及多文件的工程开发时&#xff0c;我们需要对很多不同类型、不同功能&#xff…