二、显示图片、提取边缘特征并保存(C# + OpenCV)

news2024/12/23 15:04:01

实现功能:
1,打开照片,并显示
2,对选择的照片进行Canny边缘检测
3,保存边缘检测之后的结果

一、布局

打开在视图下打开工具箱
在这里插入图片描述
选择一个PictureBox,仨Button
在这里插入图片描述

在这里插入图片描述
对Button改个名字
在这里插入图片描述
仨Button,分别对应三个功能的实现
最终的页面如下所示
在这里插入图片描述

二、引入命名空间

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

using OpenCvSharp;
using OpenCvSharp.Extensions;

在这里插入图片描述
要有这三个哈,没有就去浏览里面搜索下载安装就行
在这里插入图片描述

三、选择照片功能

定义全局变量picture用于存放读取的图片的位置

OpenFileDialog file = new OpenFileDialog();
new一个OpenFileDialog 类对象file,用于打开选择图片
OpenFileDialog 类官网API

if (file.FileName != string.Empty)
此时file.FileName就是图片的路径,是一个字符串数据

pictureBox1.Load(file.FileName);
pictureBox1就是布局里面的PictureBox控件名称
参数是图片的路径,这里传入用户选择的图片路径file.FileName
此时就可以将用户选择的照片显示在PictureBox控件上

string picture = ""; // 全局变量存放读取图片的路径
private void button1_Click(object sender, EventArgs e)
{
    OpenFileDialog file = new OpenFileDialog();
    file.InitialDirectory = ".";
    file.Filter = "所有文件(*.*)|*.*";
    file.ShowDialog();
    if (file.FileName != string.Empty)
    {
        try
        {
        	picture = file.FileName;
            this.pictureBox1.Load(file.FileName);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }  
}

四、Canny边缘检测功能

OpenCV处理的图片都是Mat形式
Mat img1 = new Mat(picture, ImreadModes.Color);
读取用户选择的图片
参数一:图片的路径,picture
参数二:读取图片的形式,ImreadModes.Color三颜色通道的彩色图

Mat gray = new Mat();存放处理图片之后的灰度图
Mat canny = new Mat();存放Canny边缘检测之后的结果图片

Cv2.CvtColor(img1,gray, ColorConversionCodes.RGB2GRAY);
img1转换为灰度图,输出结果为gray
参数一:输入图像,img1
参数二:输出图像,gray
参数三:转换的操作,ColorConversionCodes.BGR2GRAY,BGR转灰度图

Cv2.Canny(gray, canny, 100, 200);
gray图像进行Canny边缘检测,输出结果为canny,minVal 为100,maxVal 为200
当然Canny算子还有其他参数,读者可自行拓展学习
参数一:输入图像,gray
参数二:输出图像,canny
参数三:第一个阈值,100
参数四:第二个阈值,200

Bitmap bitmap = canny.ToBitmap();
graycanny都是Mat类型的数据,要想在PictureBox控件上展示,必须转换为Bitmap类型数据

pictureBox1.Image = bitmap;
此时bitmapBitmap类型数据,可以进行在控件上展示

private void button2_Click(object sender, EventArgs e)
{
    Mat img1 = new Mat(picture, ImreadModes.Color);
    Mat gray = new Mat();
    Mat canny = new Mat();

    Cv2.CvtColor(img1,gray, ColorConversionCodes.BGR2GRAY);
    Cv2.Canny(gray, canny, 100, 200);
    
    Bitmap bitmap = canny.ToBitmap();
    pictureBox1.Image = bitmap;
}

五、保存图片功能

SaveFileDialog save = new SaveFileDialog();
new一个SaveFileDialog 类对象save ,用于选择保存图片的位置
SaveFileDialog 类官网API

pictureBox1.Image.Save(save.FileName);
将PictureBox控件显示的通过Canny算子进行边缘检测之后的照片结果进行保存

private void button3_Click(object sender, EventArgs e)
{
    SaveFileDialog save = new SaveFileDialog();
    save.InitialDirectory = ".";
    save.Filter = "所有文件(*.*)|*.*";
    save.ShowDialog();
    if(save.FileName != string.Empty)
    {
        try
        {
            this.pictureBox1.Image.Save(save.FileName);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
     }
}

六、完整代码

复制的时候记得考虑实际的namespace
namespace opencv_test1跟你的项目名称一致哈

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

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace opencv_test1
{
   
    public partial class Form1 : Form
    {
       
        string picture = "";

        public Form1()
        {
            InitializeComponent();          
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
        }
       
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog file = new OpenFileDialog();
            file.InitialDirectory = ".";
            file.Filter = "所有文件(*.*)|*.*";
            file.ShowDialog();
            if (file.FileName != string.Empty)
            {
                try
                {
                    picture = file.FileName;
                    this.pictureBox1.Load(picture);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }  
        }


        private void button2_Click(object sender, EventArgs e)
        {
            Mat img1 = new Mat(picture, ImreadModes.Color);
            Mat gray = new Mat();
            Mat canny = new Mat();

            Cv2.CvtColor(img1,gray, ColorConversionCodes.BGR2GRAY);
            Cv2.Canny(gray, canny, 100, 200);
            
            Bitmap bitmap = canny.ToBitmap();
            pictureBox1.Image = bitmap;
        }


        private void button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog save = new SaveFileDialog();
            save.InitialDirectory = ".";
            save.Filter = "所有文件(*.*)|*.*";
            save.ShowDialog();
            if (save.FileName != string.Empty)
            {
                try
                {
                    this.pictureBox1.Image.Save(save.FileName);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
}

七、效果展示

运行效果
在这里插入图片描述
选择照片
在这里插入图片描述
在这里插入图片描述
Canny边缘检测
在这里插入图片描述
保存照片
在这里插入图片描述
保存效果
在这里插入图片描述

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

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

相关文章

Word中图表题注样式自动编号

需求 在写论文的时候,希望图表题注是下面的样子,其中图号表示为:章的编号-本章中图的序号,而且都是小写数字。 网上找的方法大多是使用 “插入题注” 来插入,此时章的编号是大写的,如“图一-1”。然后再通…

Mac的终端配置

Mac的终端配置 参考教程包管理工具 - Homebrew出现的问题用虚拟环境解决方案:直接将解释器的路径放过去错误方法:用find查找到虚拟环境安装的路径,其链接的是brew安装的python路径 编辑器没有报错,但是运行过程中仍然找不到pandas…

软件供应链安全:寻找最薄弱的环节

在当今的数字时代,软件占据主导地位,成为全球组织业务和创新的支柱。它是差异化、项目效率、成本降低和竞争力背后的驱动力。软件决定了企业如何运营、管理与客户、员工和合作伙伴的关系,以及充分利用他们的数据。 挑战在于,当今…

[react优化] 避免组件或数据多次渲染/计算

代码如下 点击视图x➕1,导致视图更新, 视图更细导致a也重新大量计算!!这很浪费时间 function App() {const [x, setX] useState(3)const y x 2console.log(重新渲染, x, y);console.time(timer)let a 0for (let index 0; index < 1000000000; index) {a}console.timeE…

Linux服务器上搭建深度学习环境(安装anaconda、创建虚拟环境、安装pytorch)

Linux服务器的搭配 Linux服务器上安装anaconda创建虚拟环境linux上安装pytorchxshell连接服务器 Linux服务器上安装anaconda 链接 创建虚拟环境 参考教程&#xff1a;此处 linux上安装pytorch 链接 xshell连接服务器 链接

2025考研数学汤家凤基础班百度网盘视频+强化班PDF讲义持续更新

如果25考研想全程跟张宇老师&#xff0c;可以参考下面这个表格来使用资料&#xff1a; 2025考研数学全程课&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1e6wA4OiH_EJpZPXPxoHYwg 提取码&#xff1a;om45 考研数学 考研数学无非就是汤家凤老师&#xff0c;张宇老师…

在Ubuntu Linux中安装boost库详细步骤

下载boost安装包 在Linux浏览器 Boost C Libraries 下载boost的最新版安装包 安装包解压缩 在安装目录中找到压缩包&#xff0c;右键点击压缩包&#xff0c;点击Extract to...解压缩至选择的目录 设置编译器 在解压缩后的目录中进入终端&#xff0c;运行命令&#xff1a; 如…

Redis分布式锁的实现和分析

关于 synchronized 项目单独部署时&#xff0c;使用 synchronized 可以实现并发安全&#xff0c;但如果项目搭建集群时&#xff0c;有多个线程同时对某项目中的数据修改时&#xff0c;可能会出现并发问题。 synchronized 关键字底层是 JVM 中的 monitor&#xff08;管程&…

【示例】Spring-IOC理解

前言 本文从常规的开发示例&#xff08;DAO、Service、Client&#xff09;入手&#xff0c;逐步体会理解IOC的原理及实现。 文中示例的代码地址&#xff1a; GitHubhttps://github.com/Web-Learn-GSF/Java_Learn_Examples父工程Java_Framework_Spring 示例 | 常规三层开发示…

stm32 之SPI通信协议

本文为大家介绍 SPI 通信协议的基础知识。 文章目录 前言一、SPI协议的概念二、SPI总线架构三、SPI通讯时序1. 起始&#xff0c;停止 信号2.CPOL&#xff08;时钟极性&#xff09;/CPHA&#xff08;时钟相位&#xff09; 四&#xff0c; I2C 总线 和SPI 总线比较相同点&#xf…

Flutter仿Boss-6.底部tab切换

效果 实现 图片资源采用boss包中的动画webp资源。Flutter采用Image加载webp动画。 遇到的问题 问题&#xff1a;Flutter加载webp再次加载无法再次播放动画问题 看如下代码&#xff1a; Image.asset(assets/images/xxx.webp,width: 40.w,height: 30.w, )运行的效果&#xf…

从二维数组到一维数组——探索01背包问题的动态规划优化

文章目录 题目前知背包问题 二维dp数组一、思路二、解题方法三、Code 一维dp数组一、思路二、解题方法三、Code 总结 本文将继续上一篇博客爬楼梯之后继续讲解同样用到了动态规划的 01背包问题 在解决动态规划问题时&#xff0c;我们经常面临着空间复杂度的挑战。01背包问题是…

前端三剑客 —— JavaScript (第二节)

目录 内容回顾 数据类型 基本数据类型&#xff1a; 引用数据类型&#xff1a; 常见运算 算术运算符 比较运算符 逻辑运算符 赋值运算符 自增/减运算符 三目运算符 位运算符 内容回顾 1.概述 2.基本数据 1.使用方式&#xff08;行内、页面、外部&#xff09; 2.对话框…

通信安全之数据加密

数据安全的需求如今越来越重要&#xff0c;本篇简单举例给日常的TCP/UDP通信加密&#xff0c;至少能让想干坏事的崽犯罪的成本更高一些&#xff08;如果会一些BPF的&#xff0c;可能难不住这些崽&#xff09;&#xff0c;能让我们的数据更安全一点。 经典TCP socket编程 下面…

佑雅的小布谷数据平台获取token如何实现

小博股数据开放平台是面向全部用户的股票数据开放平台&#xff0c;通过调用接口可以获取股票的历史数据。在调用之前需要进行下面的准备工作&#xff0c;第一步注册&#xff1a; 用户在注册之后&#xff0c;登录点击头像进入个人中心&#xff0c;在功能模块的最下方有一个创建应…

IntelliJ IDEA 2024.1安装与激活[破解]

一&#xff1a;IDEA官方下载 ①如题&#xff0c;先到IDEA官方下载&#xff0c;简简单单 ②IDEA官方&#xff1a;IntelliJ IDEA – the Leading Java and Kotlin IDE 二&#xff1a;获取脚本 &#x1f31f;网盘下载&#xff1a;jetbra (密码&#xff1a;lzh7) &#x1f31f;获取…

51单片机入门_江协科技_25~26_OB记录的笔记_蜂鸣器教程

25. 蜂鸣器 25.1. 蜂鸣器介绍 •蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号 •蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器&#xff08;开发板上用的无源蜂鸣器&#xff09; •有源蜂鸣器&#xff1a;内部自带振荡源&a…

报文 消息

报文消息域 MsgField name 域名称 length 长度 fillChar 填充字符 fillSide 填充位置 报文消息片 MsgPiece 由多个消息域按一定的顺序组成 private List<MsgField> itemList new LinkedList<~>();组装消息 报文消息包 MsgPackage 由多个消息片组成 String[]…

FreeRTOS启动任务调度器

FreeRTOS启动任务调度器 这部分内容就要去深入了解源码以及熟悉汇编语言的操作。依旧正点原子的视频。下面首先看开启任务调度器这部分源码&#xff1a; 1开启任务调度器 任务调度器用于启动任务调度器&#xff0c;任务调度器启动后&#xff0c; FreeRTOS 便会开始进行任务调…

MyBatis 应用的组成

王有志&#xff0c;一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群&#xff1a;共同富裕的Java人 大家好&#xff0c;我是王有志。在上一篇文章的最后&#xff0c;我们写了一个简单的例子&#xff0c;今天我们就通过这个例子来看一看一个标准的 MyBatis 应用程序由哪…