C# 图像处理(一)

2023-05-16

下面是一个学习的过程,一个小的图像处理软件的C#编程过程,是我最近学习的过程。
大家可以一起共同学习。
欢迎大家加群 图像处理交流群(C#、opencv、matlab)672854897
1.打开图像
在项目中加一个button(text文本改成打开文件)
这里写图片描述


在form1中加入一个公共变量curbitmap

		private string curFilename;
        private System.Drawing.Bitmap curbitmap;

button1_Click中的代码(打开图像读取图像文件的过程)

 private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openglg = new OpenFileDialog();
            openglg.Filter = "所有图像文件|*.bmp;*.png;*.pcx;*.jpg;*.gif;*.tif;*.ico";//文件格式可以再继续添加
            openglg.Title = "打开图像文件";
            openglg.ShowHelp = true;
            if (openglg.ShowDialog() == DialogResult.OK)//打开文件窗口
            {
                curFilename = openglg.FileName;//地址
                try
                {
                    curbitmap = (Bitmap)Image.FromFile(curFilename);//将公共变量curbitmap赋值
                }
                catch (Exception exp)
                {
                    MessageBox.Show(exp.Message);//如果出错显示错误信息
                }
            }
            Invalidate();

        }

这样文件就读到了curbitmap变量中
在form_paint事件中编辑在某个控件或者form窗体中绘制图像(图像大小的调控,滚轮的使用可以自行学习)

 private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.panel1.CreateGraphics();//绑定控件
            if (curbitmap != null)
            {
                int x, y;
                x = curbitmap.Width;
                y = curbitmap.Height;
                while (x > this.Width - 160 && y > this.Height - 20)//控制图像显示大小
                {
                    x = x / 2;
                    y = y / 2;
                }
                g.DrawImage(curbitmap, 160, 20, x, y);//绘制图像
                //g.DrawImage(curbitmap, 160, 20, curbitmap.Width, curbitmap.Height);

            }
            g.Dispose();
        }

运行结果

这里写图片描述

2.清空按钮
功能:按下清空按钮,界面的图像清空。

 private void button2_Click(object sender, EventArgs e)
        {
            Graphics g = this.panel1.CreateGraphics();
            g.Clear(panel1.BackColor);
            curbitmap = null;
            g.Dispose();
        }

清空的时候一定要把公共变量curbitmap也要变为null,不然上面的paint函数会不断刷新出来图像

3.绘制直方图
绘制RGB像素的灰度直方图(特定值的出现的频率),也可以按照比例做成转化为灰度的图(我做成RGB是为了看清楚后面也写操作对我的图像是否实现)

private void button4_Click(object sender, EventArgs e)
        {
            FrmhistR f = new FrmhistR(curbitmap);
            f.Show();
            FrmhistG G = new FrmhistG(curbitmap);
            G.Show();
            FrmhistB B = new FrmhistB(curbitmap);
            B.Show();
        }

创建三个窗体,下面只对红色进行解说
在formR中建立公共变量bmphist,用于将主窗体的图像数据传到此窗体,同时重写此窗体的构造函数

private Bitmap bmphist;
        private int[] countPixel;
        private int maxPixel;
        public FrmhistR(Bitmap bmp)
        {
            InitializeComponent();
            this.bmphist = bmp;
            this.countPixel = new int[256];//构造一个数组用于计算0-255像素的数量

        }

Load函数中代码(计算传进来的图像的直方图的数据到countPixel中)

 private void Frmhist_Load(object sender, EventArgs e)
        {
            Rectangle rect = new Rectangle(0, 0, bmphist.Width, bmphist.Height);//划定区域
            BitmapData bmpData = bmphist.LockBits(rect, ImageLockMode.ReadWrite, bmphist.PixelFormat);//上锁
            IntPtr ptr = bmpData.Scan0;//读取第一行数据
            int bytes = 3*bmphist.Width * bmphist.Height;//构造灰度值数组的个数也可以是bmpdata.strike*bmpdata.height具体的大家自己去思索其中的大小关系,牵扯到图像的数据格式(可用和未用空间问题)
            byte[] grayValues = new byte[bytes];//创建灰度值函数
            System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);//将图像数据传到grayvalues数组中
            byte temp = 0;
            maxPixel = 0;

            Array.Clear(countPixel, 0, 256);

            for(int i=0;i<bytes;i+=3)
            {
                temp = grayValues[i+2];//i,i+1,i+2分别是B,G,R
                countPixel[temp]++;//计算此像素值的个数
                if(countPixel[temp]>maxPixel)
                {
                    maxPixel = countPixel[temp];

                }
            }
            System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);//将灰度值重新复制回去
            bmphist.UnlockBits(bmpData);//解锁
        }

下面是绘制过程

 private void Frmhist_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen p = new Pen(Brushes.Black, 1);
            g.DrawLine(p, 50, 240, 320, 240);//两个坐标轴
            g.DrawLine(p, 50, 240, 50, 30);


            g.DrawLine(p, 100, 240, 100, 242);//节点标度
            g.DrawLine(p, 150, 240, 150, 242);
            g.DrawLine(p, 200, 240, 200, 242);
            g.DrawLine(p, 250, 240, 250, 242);
            g.DrawLine(p, 300, 240, 300, 242);

            g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(46, 242));//节点标度值
            g.DrawString("50", new Font("New Timer", 8), Brushes.Black, new PointF(92, 242));
            g.DrawString("100", new Font("New Timer", 8), Brushes.Black, new PointF(139, 242));
            g.DrawString("150", new Font("New Timer", 8), Brushes.Black, new PointF(189, 242));
            g.DrawString("200", new Font("New Timer", 8), Brushes.Black, new PointF(239, 242));
            g.DrawString("250", new Font("New Timer", 8), Brushes.Black, new PointF(289, 242));

            g.DrawLine(p, 48, 40, 50, 40);//最大值节点标注
            g.DrawString("0", new Font("New Timer", 8), Brushes.Black, new PointF(34, 234));
            g.DrawString(maxPixel.ToString(), new Font("New Timer", 8), Brushes.Black, new PointF(18, 34));//最大值节点标注等等,自己需要尝试一下

            double temp = 0;
            for(int i=0;i<256;i++)
            {
                temp = 200.0 * countPixel[i] / maxPixel;
                g.DrawLine(p, 50+i, 240, 50+i, 240-(int)temp);绘制每个像素的数量线
            }
            p.Dispose();

        }

绘制结果

这里写图片描述

4.线性点拉伸
其实就是一个对灰度值进行拉伸的过程
直接放代码
主窗体

 private void button5_Click(object sender, EventArgs e)
        {
            if (curbitmap != null)
            {
                Frmliner finearfrom = new Frmliner();
                if (finearfrom.ShowDialog() == DialogResult.OK)
                {
                    Rectangle rect = new Rectangle(0, 0, curbitmap.Width, curbitmap.Height);
                    System.Drawing.Imaging.BitmapData bmpdata = curbitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                        curbitmap.PixelFormat);
                    IntPtr ptr = bmpdata.Scan0;
                    int bytes = 3 * curbitmap.Width * curbitmap.Height;
                    byte[] grayValues = new byte[bytes];
                    System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);


                    int temp = 0;
                    double a = Convert.ToDouble(finearfrom.Getscaling);
                    double b = Convert.ToDouble(finearfrom.Getoffset);
                    for (int i = 0; i < bytes; i++)
                    {
                        temp = (int)(a * grayValues[i] + b + 0.5);
                        if (temp > 255)
                        {
                            grayValues[i] = 255;
                        }
                        else
                            if (temp < 0)
                            grayValues[i] = 0;
                        else
                            grayValues[i] = (byte)temp;


                    }
                    System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
                    curbitmap.UnlockBits(bmpdata);

                }
                Invalidate();
            }
        }

获取参数界面

这里写图片描述
获取界面的代码

 private void startLinear_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;        }

        private void close_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        public string Getscaling
        {
            get
            {
                return scaling.Text;
            }
        }
        public string Getoffset
        {
            get
            {
                return offset.Text;
            }
        }

运行结果
这里写图片描述
这里写图片描述

做完这些理解后就可以自己尝试一下做一下其他的。下面谈谈内存法,像素法,指针法的我的理解,获取像素虽然自己在敲的过程很省事,代码很少,思考的也不多,但是速度真的很慢,我在后面实现一个东西的时候要等很久。
内存法的速度真的很快,但是有一个理解的过程,还要在理解的基础上,在实现每个东西的时候,要去思考一些很多东西和不同,比如要是用matlab来做的话可能就直接一个gray灰度值就ok了,但是在内存法的时候要思考RGB三个量的关系,尤其在图像分割的时候一开始,要思考很久。但是想一下,要是用灰度值统一的话就没有那个i+=3的过程了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 图像处理(一) 的相关文章

  • 朱有鹏老师linux核心大讲堂---ARM裸机第十一部分 NandFlash和iNand学习笔记

    目录 1 NandFlash的接口 数据手册 xff1a K9F2G08 K9F4G08 2 NandFlash结构框图 3 Nandflash的结构 4 NandFlash常见操作以及流程分析 5 S5PV210的NandFlash控制器
  • 查看KerasTensor具体值

    之前碰到过一次这个问题 xff0c 一直没解决 xff0c 这次又又碰上了 xff0c 在模型采用Sequential xff08 xff09 方式定义的情况下 xff0c 找到了一个解决办法 xff0c 在此分享一下 xff08 如果有其
  • 面向深度学习系统的对抗样本攻击与防御

    研究生涯即将开始 xff0c 现在做的是对抗样本攻击与防御 xff0c 开始每天写博客 xff0c 记录一下自己的学习历程 1 对抗样本 尽管深度学习解决某些复杂问题的能力超出了人类水平 xff0c 但也面临多种安全性威胁 2013年 xf
  • VNC启动出错的处理汇总

    1 vncserver 1尝试启动VNC vncserver 1 2 ps进程并kill掉所有的PS span class token function ps span span class token parameter variable
  • LeetCode 24 螺旋矩阵

    螺旋矩阵 LeetCode 问题描述问题分析代码 问题描述 给定一个包含 m x n 个元素的矩阵 xff08 m 行 n 列 xff09 xff0c 请按照顺时针螺旋顺序 xff0c 返回矩阵中的所有元素 示例 1 输入 1 2 3 4
  • 黑苹果安装 戴尔灵越3568 驱动篇

    本教程主要适用于安装后驱动的安装和细节问题 xff0c 安装教程基本一样 xff0c 就没有介绍 xff0c 希望谅解 最近在公司电脑上装了黑苹果之后体验不错 xff0c 自己的本本上也装了一个 安装接近完美 xff0c 除wif不能驱动
  • ubuntu1804(或1604)换清华源(含其他源地址)

    将ubuntu的源换成国内源会大大提高更新速度 笔者习惯用清华源 xff0c 故此笔记就以清华源为准绳进行介绍 xff0c 为了利于大家使用 xff0c 同时也附上国内其他几个主要的源 备份源列表 终端输入 xff1a sudo cp et
  • moby、docker-ce与docker-ee

    原文链接 xff1a https blog csdn net yk20091201 article details 80016135 1 moby docker ce与docker ee 最早的时候docker就是一个开源项目 xff0c
  • mysql之 find_in_set()、INSTR()、in

    1 find in set 函数 xff1a 查询字段 str 在 strlist 中的位置 1 1 语法 FIND IN SET str strlist str xff1a 要查询的字符串 strlist xff1a 字段名 xff0c
  • Springboot项目搭建过程报错汇总

    1 SpringbootTest总是报 XXXX that could not be found span class token operator span span class token operator span span clas
  • python实现飞行控制仿真(一)——PyFME(Python Flight Mechanics Engine)

    一 PyFME安装 目前关于PyFME的介绍比较少 xff0c 利用很长时间才摸索整理出来 xff0c 如需转载请标注来源 虚拟环境文件和测试代码下载地址 xff1a https download csdn net download wei
  • 五个无刷马达驱动电路分享!

    1 三相六臂全桥驱动电路 无刷直流电机驱动控制电路如图1 所示 该电路采用三相六臂全桥驱动方式 xff0c 采用此方式可以减少电流波动和转矩脉动 xff0c 使得电机输出较大的转矩 在电机驱动部分使用6个功率场效应管控制输出电压 xff0c
  • 胎压监测方案设计--TPMS方案

    随着国民经济发展 xff0c 群众生活水平提高 xff0c 汽车逐步走进了千家万户 近几年相关统计 xff0c 我国汽车产销量连年增长 xff0c 2014年的汽车总产量增加到2001年的十倍 达到将近2400万辆 xff0c 汽车工业已经
  • 前端数据可视化echarts.js

    一 echarts js的优势与总体情况 echarts js作为国内的IT三巨头之一的百度的推出一款相对较为成功的开源项目 xff0c 总体上来说有这样的一些优点 1 容易使用 echarts js的官方文档比较详细 xff0c 而且官网
  • 列表、数组、张量的联系与区别

    1 list和ndarray 最大区别在于在内存中存储方式不同 相同 xff1a 列表 list 与数组 xff08 ndarray xff09 类似 xff0c 是具有相同类型的多个元素构成的整体 list和array都可以根据索引 切片
  • 基于Python的ZED2教程 3.深度感知

    本教程将讲述如何用ZED SDK获取深度信息 xff0c 当获取到50张图片时程序将停止 创建摄像头 如前例 xff0c 我们需要先创建初始化摄像头 本例中 xff0c 我们设置摄像头的分辨率为720 xff0c 帧速率为60 xff0c
  • Qt类关系图

  • ubuntu安装openrave的简单方法

    openrave装了一天都没装好 xff0c 无意间找到下面这个网站 xff1a https github com crigroup openrave installation 安装成功了 xff0c 步骤还简单 下载脚本后 xff0c 按
  • vue项目 请求封装

    vue项目 xff0c 为了统一代码 xff0c 提高可维护性 xff0c 通常会涉及请求封装 在里面 xff0c 我们可以统一处理请求头 xff1a axios defaults baseURL 61 34 api 34 axios de
  • Linux 多线程编程 (典藏、含代码)

    目录 1 基础知识 2 相关函数 2 1创建线程 pthread create 2 2获取线程ID pthread self 2 3等待线程结束 pthread join 线程的分离 pthread detach 2 4线程退出 2 4 1

随机推荐

  • (0)C#开发环境构建——史上最容易理解的C#界面搭建

    本次开发使用的开发环境为 xff1a win10 64位 xff0c vs2017 64位 xff0c OpenCV341 1 vs2017的安装 安装环境的配置 xff0c 网上有很多教程 xff0c 在此仅做以引用 xff0c 唯一需要
  • 惯性传感器的寄存器配置

    一 陀螺仪 1 输入数据的处理 xff08 寄存器配置 xff09 陀螺仪是测量角速度的传感器 xff0c 量程范围可选 43 250 500 1000和2000 dps就是degree per second 度每秒 xff0c 传感器直接
  • CAN总线学习笔记(1)- CAN基础知识

    依照瑞萨公司的 CAN入门书 的组织思路来学习CAN通信的相关知识 xff0c 并结合网上相关资料以及学习过程中的领悟整理成笔记 好记性不如烂笔头 xff0c 加油 xff01 1 CAN的一些基本概念 1 1 什么是CAN总线 CAN 是
  • 分析蓝牙协议栈源码bstack

    参考 xff1a https blog csdn net lewanhah01 article details 104029135 一 bstack支持的设备类型 BTStack支持多种接口的蓝牙模块 xff0c 比如USB口 3线串口 T
  • HYG12864字符显示

    一 硬件 HYG12864A2G YF62L VD是一个128 64的lcd模块 记录几个比较重要的寄存器设置 1 有lcd模块信息可知 xff0c 有128列 xff0c 64行 xff0c 每8行为一页 2 显示时要设置页地址和列地址
  • 可以在不建立对象的情况下调用类成员吗?可以不建立对象的情况下调用类方法吗?

    可以在不建立对象的情况下调用类成员吗 xff1f 非静态成员不能 xff0c 非静态成员是随着对象存在而产生的 xff0c 没有对象也就不会存在非静态成员 xff0c 静态的可以 xff0c 类名 成员名方式访问 静态的成员变量和函数存在全
  • 解决linux指令“没有那个文件或目录”

    今天用shuf指令想打乱一个txt文件中各行的内容 xff0c 结果终端提示 没有那个文件或目录 一般这种情况肯定是路径写错了 xff0c 仔细检查之后发现 txt后面多打了一个空格 将空格删除 xff0c 问题解决 上面是正常的txt文件
  • Ubuntu配置阿里云的apt源

    root 64 zjy span class token comment cd etc apt span root 64 zjy etc apt span class token comment cp sources list source
  • hadoop自动故障转移集群搭建详解

    安装包地址 https archive apache org dist hadoop common stable 选择hadoop 3 3 2 tar gz包下载 环境 操作系统 span class token punctuation s
  • TX2 入坑总结(持续更新)

    1 新机无法使用hdmi转VGA连接显示器 xff0c 就算是换成1080p的显示器也不行 xff08 之前的树莓派可是啥都不挑各种连 xff09 更新内核后就可以连接1080p的显示器了 xff08 意外收获 xff09 xff0c 而且
  • 简单概念-BaseLine,PipeLine

    BaseLine 你训练一个模型 xff0c 获得了80 的准确率 xff0c 你觉得很高吗 xff1f 不能这么说 xff0c 因为你没有与别人的东西作对比 只有与当前的state of the art的算法比较才能有意义 xff0c 这
  • FreeRTOS中的变量,函数命名规则(u.v.x.p什么意思)

    写在前面 初学FreeRTOS时 xff0c 每次打开函数列表都一脸懵逼 xff1f 根本不知道这什么prv v ux是什么意思 xff0c 虽然平时使用也不需要知道这么多东西 xff0c 因为它不怎么影响开发 xff0c 但是理解总比疑惑
  • 水准网平差 WinForm C#软件

    水准网平差 span class token class name WinForm span C 软件 版权所有 需求源码请咨询 qq xff1a 849495327 仅供学习交流 界面UI设计 导入数据窗体 showViewdata cs
  • 基于K-d tree的Lidar点云检索C#

    版权所有 咨询请加qq 849495327 Form2 xff1a using System using System Collections Generic using System ComponentModel using System
  • C# 影像特征点提取

    版权所有 详情咨询qq 849495327 内容和要求如下 xff1a 任务 xff1a 提取一幅数字影像中的特征点 内容 xff1a 使用Moravec算子编写程序 xff0c 从一幅数字影像中自动提取出50个以上的特征点 要求 xff1
  • 解决朱有鹏开发板--主机--虚拟机不能互相PING通问题

    解决朱有鹏开发板 主机 虚拟机不能互相PING通问题 前言 xff1a 查遍整个网络 xff0c 没有人发表这个问题 xff0c 在视频中老朱得到的结论是UBOOT有问题 xff0c 结果 xff0c 经过实践发现 xff0c 是可以同时P
  • 一个简单的三层架构之用户登陆和注册在数据库中的存储

    一个简单的三层架构之用户登陆和注册在数据库中的存储 本人为一小白菜鸟 xff0c 在不断学习的过程中将自己学习所得的经验分享给大家 今天为大家介绍的是一个小实现 xff0c 一个三层架构的小实现 xff0c 关于登陆界面用户名输入与注册与数
  • 有哪些比较好的关于GIS和遥感的公众号?

    有哪些比较好的关于GIS和遥感的公众号 xff1f 作为一个正在学习的GISer和遥感学习者 xff0c 有哪些比较好的关于GIS和遥感的公众号呢 xff0c 下面来给大家分享一些我知道的 xff0c 当然又很多途径 xff0c 欢迎大家一
  • 一个简单的三层架构之仓库管理系统的入库出库

    一个简单的三层架构之仓库管理系统的入库出库 今天来讲一下一个简单的三层架构的程序 xff0c 一个仓库管理系统的简单的出库入库操作 xff0c 还有供应商的信息录入 欢迎大家添加 仓库管理系统群 xff08 matlab c java均可
  • C# 图像处理(一)

    下面是一个学习的过程 xff0c 一个小的图像处理软件的C 编程过程 xff0c 是我最近学习的过程 大家可以一起共同学习 欢迎大家加群 图像处理交流群 xff08 C opencv matlab xff09 672854897 1 打开图