C#可视化程序设计 图像二值化工具

原稿完成于2020年5月19日,上传以做备份。

正文

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

希望从word复制粘贴过来的代码顺序没有乱,我已经懒得核查了。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ImageCut
{
public partial class Form1 : Form 
    {
        Bitmap currentImage; // Bitmap (位图)是用于处理由像素数据定义的图像的对象
        Bitmap cutImage;
        public Form1()//构造函数
        {
            InitializeComponent();
        }
        Boolean ifgray = false;/是否灰度化,新打开图片时,该值会重置。
        private void openFileToolStripMenuItem_Click(object sender, EventArgs e)//定义打开【文件】的ToolStripMenuItem (工具条形菜单项目)方法
        {                                          
            OpenFileDialog ofd = new OpenFileDialog();//类的实例化,实例名为ofd,此类可用于检查文件是否存在并打开它。
            ofd.Filter = "Jpeg Files (jpg)|*.jpg; | Bitmap Files (bmp)|*.bmp; | Gif Files (gif)|*.gif; | Png Files (png)|*.png; | All Files (*.*) | *.*;"; //文件类型过滤
            string filename;
            if(ofd.ShowDialog()==DialogResult.OK)//如果用户在对话框中点击了确定
            {
                filename = ofd.FileName; //则打开的文件命名为原文件名
            }
            else
            {
                return; //否则返回
            }
            currentImage = new Bitmap(filename);
            pictureBox1.Image = currentImage;//显示选中的图片
            ifgray = false;
			cutImage = null;
			pictureBox2.Image = null;
            pictureBox3.Image = null;
        }
        private void openFolderToolStripMenuItem_Click(object sender, EventArgs e)//定义打开【文件夹】的ToolStripMenuItem (工具条形菜单项目)方法
        {                                                                         //整体大致相同
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            string path;
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                path = fbd.SelectedPath;//文件路径为用户选定的路径
            }
            else
            {
                return;
            }
            DirectoryInfo root = new DirectoryInfo(path);//DirectoryInfo类是System.IO命名空间的一部分,它用于创建,删除和移动目录。
            //指将用户选定文件夹路径为根目录
            foreach (FileInfo f in root.GetFiles())
            {
                string filename = f.FullName;
                if (f.Extension.ToUpper() == ".BMP" || f.Extension.ToUpper() == ".JPG" || f.Extension.ToUpper() == ".PNG" || f.Extension.ToUpper() == ".GIF" || f.Extension.ToUpper() == ".TIF")
                {
                    int newrow = dataGridView1.Rows.Add();//在数据网格显示栏中添加获取的文件夹中的文件,每多一个文件就新建一行
                    dataGridView1["image", newrow].Value = new Bitmap(filename);//new Bitmap(filename)
                    dataGridView1["id", newrow].Value = newrow;//id栏值为行值
                    dataGridView1["filename", newrow].Value = filename;//filename值为文件原名
                }
            }
        }
        private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)//删除全部已添加的文件
        {
            dataGridView1.Rows.Clear();
            pictureBox1.Image = null;
            pictureBox2.Image = null;
            pictureBox3.Image = null;
            currentImage = null;
            cutImage = null;
        }
        private void clearSelectedToolStripMenuItem_Click(object sender, EventArgs e)//删除所选的文件
        {
            int rowCount;
            rowCount = dataGridView1.Rows.Count;
            dataGridView1.ReadOnly = true;
            for(int i=rowCount-1;i>=0;i--)//数据遍历
            {
                if(Convert.ToInt16(dataGridView1["selected",i].Value) == 1)//删除所有被标记为选择的文件
                {
                    //string filename = dataGridView1.CurrentCell.Value.ToString();
                    //if (pictureBox1.Image. == filename)
                    //{
                    //    pictureBox1.Image = null;
                    //    pictureBox2.Image = null;
                    //    currentImage = null;
                    //    cutImage = null;
                    //}
                    dataGridView1.Rows.RemoveAt(i);
                }
            }
            dataGridView1.ReadOnly = false;
            rowCount = dataGridView1.Rows.Count;//更新文件数目
            for(int i=0;i<rowCount;i++)
            {
                dataGridView1["id", i].Value = i;//重新编号
            }
        }
        private void dataGridView1_Click(object sender, EventArgs e)//DataGridView 类:单元格//显示选中的图片//获取或设置当前处于活动状态的单元格
        {
            if (dataGridView1.Rows.Count==0)//修复bug
            {
                MessageBox.Show("列表为空", "Warning");  
                return;
            }
            else
            {
                if (dataGridView1.CurrentCell.ColumnIndex == 3)//在列表为空时点击列表,将出现【System.NullReferenceException:“未将对象引用设置到对象的实例。”】,程序无响应  
                {
                    string filename = dataGridView1.CurrentCell.Value.ToString();
                    currentImage = new Bitmap(filename);
                    pictureBox1.Image = currentImage;//显示当前照片
                    ifgray = false;
					cutImage = null;
					pictureBox2.Image = null;
                    pictureBox3.Image = null;
                }
                else;
            }
            
        }
        //初始化关键值
        int start_row = 0, start_col = 0;//起始行、列为0
        int current_row = 0, current_col = 0;//当前行、列为0
        int LU_row = 0, LU_col = 0;//ROI左上角坐标对为0
        int rcw = 0, rch = 0;//ROI宽度、高度为0
        Boolean if_draw = false;//该布尔量用来标记是否在图像中绘制ROI
        private void button1_Click(object sender, EventArgs e)//设置储存子图像文件夹的按钮
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if(fbd.ShowDialog() == DialogResult.OK)
            {
                string path;
                path = fbd.SelectedPath;//将路径设为指定的路径值
                textBox1.Text = path;//显示用户选择的路径
            }
        }
        private void button2_Click(object sender, EventArgs e)//保存子图像
        {
            if(cutImage == null)//如果没有创建子图像,按钮无效
            {
                    MessageBox.Show("您还未创建子图像", "Warning");///错误提示
                    return;
            }
            string path = textBox1.Text;
            if(path.Length == 0)//如果没有指定路径,按钮无效
            {
                MessageBox.Show("您还未添加指定路径", "Warning");///错误提示
                return;
            }
            DirectoryInfo di = new DirectoryInfo(path);
            int fileCount = di.GetFiles().Length;
            string filename = path + "\\" + (fileCount + 1).ToString() + ".bmp";//命名子图像文件名
            cutImage.Save(filename);//保存子图像至指定路径
        }
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)//pictureBox控件用于显示图片//此方法属于绘制ROI的第一步,用于配置鼠标右击
        {
			if (currentImage == null)//未选定图像时此方法无效
			{
				return;
			}
			else if (ifgray == false)
			{
				MessageBox.Show("必须先进行灰度化才能选取ROI!");
				return;
			}
			else;
			int w, h;
            w = currentImage.Width;
            h = pictureBox1.Height;
			if (e.Y >= 0 && e.Y <= h - 1 && e.X >= 0 && e.X <= w - 1)//判断鼠标点击的位置是否位于照片尺寸内
			{
				if_draw = true;//开始绘制ROI
				start_row = e.Y;//设置起始坐标值
				start_col = e.X;
				pictureBox1.Cursor = Cursors.Cross;//鼠标由箭头变为十字标
			}
			else;
        }
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)//此方法属于绘制ROI的第二步,鼠标右击后,用于配置框图(即ROI区域)随鼠标移动
        {
            if(if_draw == true)//当已在绘制ROI时
            {
                current_row = e.Y;//设置当前坐标值
                current_col = e.X;
            }
            pictureBox1.Invalidate();//松开鼠标后可重绘框图
        }
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)//此方法属于绘制ROI的第三步,松开鼠标右键,框图绘制完成,程序将记录ROI
        {
			if (if_draw == true && ifgray == true)
			{
				if_draw = false;//ROI绘制完成
				pictureBox1.Cursor = Cursors.Arrow;//松开鼠标右键,鼠标箭头恢复
				if (rcw > 0 && rch > 0)/修复bug
				{
					cutImage = new Bitmap(rcw, rch);
					Graphics g = Graphics.FromImage(cutImage);//错误:如果鼠标只点了一下图片而没有拖动,程序将异常
					g.DrawImage(currentImage, 0, 0, new Rectangle(LU_col, LU_row, rcw, rch), GraphicsUnit.Pixel);//截取ROI
					pictureBox2.Image = cutImage;//在左边的picturebox中显示ROI
				}
			}
			else
				return;
        }
   
        private void pictureBox1_Paint(object sender, PaintEventArgs e)//用于配置框图
        {
            if (if_draw == true)
            {
                Pen pen = new Pen(Color.Red, 1);//设定笔触参数
                //设置虚线
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;//绘制虚线
                //ROI左上角点
                if (start_row <= current_row)//记录坐标对
                {
                    LU_row = start_row;
                }
                else
                {
                    LU_row = current_row;
                }
                if (start_col <= current_col)
                {
                    LU_col = start_col;
                }
                else
                {
                    LU_col = current_col;
                }
                rcw = Math.Abs(current_col - start_col) + 1;//计算ROI的宽度和高度
                rch = Math.Abs(current_row - start_row) + 1;
                e.Graphics.DrawRectangle(pen, LU_col, LU_row, rcw, rch);//绘制框图
            }
        }
        private void VersionToolStripMenuItem_Click(object sender, EventArgs e)///显示版本信息
        {
        MessageBox.Show("修复以下bug:\n 1.点击空白列表程序会跳出\n 2.单击图片程序会跳出\n " +
			"—\n 添加以下优化:\n 1.提示助手\n 2.快捷删除&快捷切换&快捷菜单\n 3.优化文件过滤器\n 4.全屏模式\n 5.自动清屏\n " +
   "6.增添缩略图\n 7.添加帮助信息\n 8.其它细节优化及窗体美化\n " +
            "—\n 添加以下功能:\n 1.图片旋转&镜像\n 2.图片灰度化\n 3.灰度直方图\n 4.图片二值化\n" +
            "\n by Author\n", "About");  
        }
        private void hotkey_Click(object sender, EventArgs e)
        {
            MessageBox.Show("当前可用的快捷操作:\n \n 1.选中列表中的图片,按方向键可切换图片\n 2.双击复选框可删除该图片;如若要删除一组照片," +
                "可勾选待删除照片,在最后一张照片的复选框内双击即可删除这组照片;\n","快捷操作");
        }
        ///灰度化
        private void button5_click(object sender, EventArgs e)
        {
            if (currentImage == null)//如果没有创建子图像,按钮无效
            {
				MessageBox.Show("您还未选取图像!\n \n图像二值化操作步骤:\n 打开图片——点击【灰度化】——选取ROI——点击【二值化】\n");
				return;
            }
            else
            {
                //MessageBox.Show("灰度化耗时较长,请耐心等待\n \n点击确定以继续");
                for (int i = 0; i < currentImage.Width; i++)
                {
                    for (int j = 0; j < currentImage.Height; j++)
                    {
                        //获取该点的像素的RGB的颜色
                        Color color = currentImage.GetPixel(i, j);
                        //利用公式计算灰度值
                        int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
                        Color newColor = Color.FromArgb(gray, gray, gray);
                        currentImage.SetPixel(i, j, newColor);
                    }
                }
                pictureBox1.Image = currentImage;
                ifgray = true;
                //MessageBox.Show("完成。");
            }
        }
        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
        }
        //二值化
        //基于二值化算法局限性,只能先选取ROI
        private void button6_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//如果没有创建子图像,按钮无效
            {
				MessageBox.Show("图像二值化操作步骤:\n 打开图片——点击【灰度化】——选取ROI——点击【二值化】\n");
				return;
            }
			else if (cutImage == null)//如果没有创建子图像,按钮无效
			{
				if (ifgray == true)
				{
					MessageBox.Show("必须先选取ROI!\n \n 图像二值化操作步骤:\n 打开图片——点击【灰度化】——选取ROI——点击【二值化】\n");
					return;
				}
				else
				{
					MessageBox.Show("必须先进行灰度化!\n \n图像二值化操作步骤:\n 打开图片——点击【灰度化】——选取ROI——点击【二值化】\n");
					return;
				}
			}
			else            
            {
				if (ifgray == true)
                {
                    //MessageBox.Show("二值化耗时较长,请耐心等待\n \n点击确定以继续");
                    int average = 0; //取图片的平均灰度作为阈值,低于该值的全都为0,高于该值的全都为255
                    for (int i = 0; i < cutImage.Width; i++)
                    {
                        for (int j = 0; j < cutImage.Height; j++)
                        {
                            Color color = cutImage.GetPixel(i, j);
                            average += color.B;//灰度化后只需取RGB中任意一值
                        }
                    }
                    average = (int)average / (cutImage.Width * cutImage.Height);//自适应阈值
                    //average = 127;//固定阈值
                    for (int i = 0; i < cutImage.Width; i++)
                    {
                        for (int j = 0; j < cutImage.Height; j++)
                        {
                            //获取该点的像素的RGB的颜色
                            Color color = cutImage.GetPixel(i, j);
                            int value = 255 - color.B;//反色
                            Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255);
                            cutImage.SetPixel(i, j, newColor);//更新颜色
                        }
                    }
                    pictureBox2.Image = cutImage;
                   // MessageBox.Show("完成。");
                }
                else
                {
                    MessageBox.Show("在进行二值化前,必须进行灰度化!\n \n图像二值化操作步骤:\n 打开图片——点击【灰度化】——选取ROI——点击【二值化】\n");
                }
            }
        }
        
        //键盘快捷键
        private void dataGridView1_Press(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
            {
                if (dataGridView1.Rows.Count == 0)//修复bug
                {
                    return;
                }
                else                    
                {
                    if (dataGridView1.CurrentCell.ColumnIndex == 3)  
                    {
                        string filename = dataGridView1.CurrentCell.Value.ToString();
                        currentImage = new Bitmap(filename);
                        pictureBox1.Image = currentImage;
                    }
                }
            }
        }
        //灰度直方图
        private void pictureBox2_Click(object sender, EventArgs e)
        {
            if (ifgray == false)
            {
                MessageBox.Show("必须先执行灰度化\n", "您希望显示灰度直方图吗?");
                return;
            }
            else
            {
                if (cutImage == null)
                {
                    MessageBox.Show("必须选取roi\n", "您希望显示灰度直方图吗?");
                }
                else
                {
                    int[] values = new int[256];//创建数组
                    for (int i = 0; i < 256; i++) values[i] = 0;//初始化数组
                    for (int i = 0; i < cutImage.Width; i++)
                    {
                        for (int j = 0; j < cutImage.Height; j++)
                        {
                            Color color = cutImage.GetPixel(i, j);
                            int value = color.B;//获取每一个点的灰度值存到一个数组中
                            values[value]++;
                        }
                    }
                    //找出要画图像里数据的最高值
                    int max = 0;
                    foreach (int i in values) max = max > i ? max : i;
                   
                    Image grayImage = null;
                    //画图,引用方法
                    draw(ref values, max, out grayImage);
                }
            }
        }
        //画直方图
        private bool draw(ref int[] datas, int Height, out Image grayImage)
        {
            grayImage = new Bitmap(256, Height + 10); //图像y轴最大值比数据最大值高些
            Graphics g = Graphics.FromImage(grayImage);
            Pen pen = new Pen(Color.Black);//笔的颜色
            for (int i = 0; i <= 255; i++)
            {
             g.DrawLine(pen, i, Height - datas[i] + 10, i, Height + 10);//画直线,灰度直方图由直线组成
            }
                pictureBox3.Image = grayImage;
                return true;
        }
        private void label3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("灰度直方图是将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。\n \n" +
                "显示灰度直方图的操作:\n 【灰度化】-【选取ROI】-【点击roi】\n","灰度直方图显示教学");
        }
        
        // 顺时针旋转90度旋转图片
        private void btnRotate_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//如果没有创建子图像,按钮无效
            {               
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                currentImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
                pictureBox1.Image = currentImage;
            }
        }
        // 逆时针旋转90度
        private void btncounterclockwiseRotate_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//如果没有创建子图像,按钮无效
            {
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                // 逆时针旋转90度的另外实现
                currentImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
                pictureBox1.Image = currentImage;
               
            }
        }
        //镜像
        private void Button7_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//如果没有创建子图像,按钮无效
            {
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                currentImage.RotateFlip(RotateFlipType.Rotate180FlipY);
                pictureBox1.Image = currentImage;
            }
        }
    }
}
 

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值