C# visual programming image binarization tool

The manuscript was completed on May 19, 2020.

text











I hope that the order of the code copied and pasted from word is not disordered, I have been too lazy to check.

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 is an object used to process images defined by pixel data
        Bitmap cutImage;
        public Form1()//Constructor
        {
            InitializeComponent();
        }
        Boolean ifgray = false;/Whether to grayscale, the value will be reset when a new image is opened.
        private void openFileToolStripMenuItem_Click(object sender, EventArgs e)//Define the ToolStripMenuItem (toolstrip menu item) method to open [File]
        {                                          
            OpenFileDialog ofd = new OpenFileDialog();//An instantiation of a class, instance named ofd, which can be used to check if a file exists and open it.
            ofd.Filter = "Jpeg Files (jpg)|*.jpg; | Bitmap Files (bmp)|*.bmp; | Gif Files (gif)|*.gif; | Png Files (png)|*.png; | All Files (*.*) | *.*;"; //file type filtering
            string filename;
            if(ofd.ShowDialog()==DialogResult.OK)//If the user clicks OK in the dialog
            {
                filename = ofd.FileName; //The opened file is named as the original file name
            }
            else
            {
                return; //otherwise return
            }
            currentImage = new Bitmap(filename);
            pictureBox1.Image = currentImage;//Show selected image
            ifgray = false;
			cutImage = null;
			pictureBox2.Image = null;
            pictureBox3.Image = null;
        }
        private void openFolderToolStripMenuItem_Click(object sender, EventArgs e)//Define the ToolStripMenuItem (toolstrip menu item) method to open the [folder]
        {                                                                         //roughly the same
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            string path;
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                path = fbd.SelectedPath;//The file path is the path selected by the user
            }
            else
            {
                return;
            }
            DirectoryInfo root = new DirectoryInfo(path);//The DirectoryInfo class is part of the System.IO namespace and is used to create, delete and move directories.
            //Refers to the user-selected folder path as the root directory
            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();//Add the files in the obtained folder in the data grid display column, and create a new line for each additional file
                    dataGridView1["image", newrow].Value = new Bitmap(filename);//new Bitmap(filename)
                    dataGridView1["id", newrow].Value = newrow;//The id column value is the row value
                    dataGridView1["filename", newrow].Value = filename;//filename is the original name of the file
                }
            }
        }
        private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)//delete all added files
        {
            dataGridView1.Rows.Clear();
            pictureBox1.Image = null;
            pictureBox2.Image = null;
            pictureBox3.Image = null;
            currentImage = null;
            cutImage = null;
        }
        private void clearSelectedToolStripMenuItem_Click(object sender, EventArgs e)//delete selected files
        {
            int rowCount;
            rowCount = dataGridView1.Rows.Count;
            dataGridView1.ReadOnly = true;
            for(int i=rowCount-1;i>=0;i--)//data traversal
            {
                if(Convert.ToInt16(dataGridView1["selected",i].Value) == 1)//Delete all files marked as selected
                {
                    //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;//number of update files
            for(int i=0;i<rowCount;i++)
            {
                dataGridView1["id", i].Value = i;//renumber
            }
        }
        private void dataGridView1_Click(object sender, EventArgs e)//DataGridView class: cell //Display selected picture //Get or set the currently active cell
        {
            if (dataGridView1.Rows.Count==0)//fix bug s
            {
                MessageBox.Show("list is empty", "Warning");  
                return;
            }
            else
            {
                if (dataGridView1.CurrentCell.ColumnIndex == 3)//Clicking the list when the list is empty will appear [System.NullReferenceException: "The object reference is not set to an instance of the object."], the program does not respond  
                {
                    string filename = dataGridView1.CurrentCell.Value.ToString();
                    currentImage = new Bitmap(filename);
                    pictureBox1.Image = currentImage;//Show current photo
                    ifgray = false;
					cutImage = null;
					pictureBox2.Image = null;
                    pictureBox3.Image = null;
                }
                else;
            }
            
        }
        //Initialize key values
        int start_row = 0, start_col = 0;//start row, column 0
        int current_row = 0, current_col = 0;//current row, column 0
        int LU_row = 0, LU_col = 0;//The coordinate pair of the upper left corner of the ROI is 0
        int rcw = 0, rch = 0;//ROI width and height are 0
        Boolean if_draw = false;//This boolean is used to mark whether to draw the ROI in the image
        private void button1_Click(object sender, EventArgs e)//Set the button for storing subimage folders
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if(fbd.ShowDialog() == DialogResult.OK)
            {
                string path;
                path = fbd.SelectedPath;//Set the path to the specified path value
                textBox1.Text = path;//Display the path selected by the user
            }
        }
        private void button2_Click(object sender, EventArgs e)//save subimage
        {
            if(cutImage == null)//Button has no effect if no subimage is created
            {
                    MessageBox.Show("You have not created a subimage", "Warning");///Error message
                    return;
            }
            string path = textBox1.Text;
            if(path.Length == 0)//If no path is specified, the button has no effect
            {
                MessageBox.Show("You have not added the specified path", "Warning");///Error message
                return;
            }
            DirectoryInfo di = new DirectoryInfo(path);
            int fileCount = di.GetFiles().Length;
            string filename = path + "\\" + (fileCount + 1).ToString() + ".bmp";//Name the subimage filename
            cutImage.Save(filename);//Save the subimage to the specified path
        }
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)//The pictureBox control is used to display the picture//This method belongs to the first step of drawing ROI, which is used to configure the right click of the mouse
        {
			if (currentImage == null)//This method has no effect when no image is selected
			{
				return;
			}
			else if (ifgray == false)
			{
				MessageBox.Show("It must be grayscaled before it can be selected 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)//Determine if the mouse click position is within the photo size
			{
				if_draw = true;//Start drawing ROI
				start_row = e.Y;//Set the starting coordinate value
				start_col = e.X;
				pictureBox1.Cursor = Cursors.Cross;//Mouse changes from arrow to cross
			}
			else;
        }
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)//This method belongs to the second step of drawing ROI. After the mouse is right-clicked, it is used to configure the block diagram (ie the ROI area) to move with the mouse
        {
            if(if_draw == true)//When the ROI is already being drawn
            {
                current_row = e.Y;//Set the current coordinate value
                current_col = e.X;
            }
            pictureBox1.Invalidate();//Redraw the block diagram after releasing the mouse
        }
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)//This method belongs to the third step of drawing ROI. Release the right mouse button, the block diagram is drawn, and the program will record the ROI.
        {
			if (if_draw == true && ifgray == true)
			{
				if_draw = false;//ROI drawing completed
				pictureBox1.Cursor = Cursors.Arrow;//Release the right mouse button, the mouse arrow returns
				if (rcw > 0 && rch > 0)/repair bug
				{
					cutImage = new Bitmap(rcw, rch);
					Graphics g = Graphics.FromImage(cutImage);//Error: If the mouse only clicks on the picture without dragging, the program will be abnormal
					g.DrawImage(currentImage, 0, 0, new Rectangle(LU_col, LU_row, rcw, rch), GraphicsUnit.Pixel);//Capture ROI
					pictureBox2.Image = cutImage;//Show the ROI in the picturebox on the left
				}
			}
			else
				return;
        }
   
        private void pictureBox1_Paint(object sender, PaintEventArgs e)//block diagram for configuration
        {
            if (if_draw == true)
            {
                Pen pen = new Pen(Color.Red, 1);//Set stroke parameters
                //set dotted line
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;//draw dashed line
                //Top left corner of ROI
                if (start_row <= current_row)//record coordinate pairs
                {
                    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;//Calculate the width and height of the ROI
                rch = Math.Abs(current_row - start_row) + 1;
                e.Graphics.DrawRectangle(pen, LU_col, LU_row, rcw, rch);//draw a block diagram
            }
        }
        private void VersionToolStripMenuItem_Click(object sender, EventArgs e)///display version info
        {
        MessageBox.Show("fix the following bug: \n 1.Clicking on the blank list program will jump out\n 2.Click the picture program will jump out\n " +
			"—\n Add the following optimizations:\n 1.Prompt Assistant\n 2.Quick delete&Quick switch&Shortcut menu\n 3.Optimized file filters\n 4.full screen mode\n 5.Automatically clear the screen\n " +
   "6.add thumbnail\n 7.Add help information\n 8.Other details optimization and window beautification\n " +
            "—\n Add the following functions:\n 1.Image rotation&mirror\n 2.grayscale image\n 3.Grayscale histogram\n 4.image binarization\n" +
            "\n by Huang Yihao\n", "About");  
        }
        private void hotkey_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Currently available shortcuts:\n \n 1.Select the picture in the list, press the arrow keys to switch pictures\n 2.Double-click the checkbox to delete the picture; to delete a group of photos," +
                "You can tick the photos to be deleted, and double-click in the checkbox of the last photo to delete this group of photos;\n","Shortcuts");
        }
        ///Grayscale
        private void button5_click(object sender, EventArgs e)
        {
            if (currentImage == null)//Button has no effect if no subimage is created
            {
				MessageBox.Show("You have not selected an image yet!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n");
				return;
            }
            else
            {
                //MessageBox.Show("Grayscale takes a long time, please wait patiently\n \n Click OK to continue");
                for (int i = 0; i < currentImage.Width; i++)
                {
                    for (int j = 0; j < currentImage.Height; j++)
                    {
                        //Get the RGB color of the pixel at this point
                        Color color = currentImage.GetPixel(i, j);
                        //Calculate the gray value using the formula
                        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("Complete.");
            }
        }
        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
        }
        //Binarization
        //Based on the limitations of the binarization algorithm, only ROI can be selected first
        private void button6_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//Button has no effect if no subimage is created
            {
				MessageBox.Show("Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n");
				return;
            }
			else if (cutImage == null)//Button has no effect if no subimage is created
			{
				if (ifgray == true)
				{
					MessageBox.Show("must be selected first ROI!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n");
					return;
				}
				else
				{
					MessageBox.Show("Grayscale must be done first!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n");
					return;
				}
			}
			else            
            {
				if (ifgray == true)
                {
                    //MessageBox.Show("Binarization takes a long time, please be patient\n \n Click OK to continue");
                    int average = 0; //Take the average grayscale of the image as the threshold, all values ​​below this value are 0, and all values ​​above this value are 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;//After grayscale, just take any value in RGB
                        }
                    }
                    average = (int)average / (cutImage.Width * cutImage.Height);//adaptive threshold
                    //average = 127;//fixed threshold
                    for (int i = 0; i < cutImage.Width; i++)
                    {
                        for (int j = 0; j < cutImage.Height; j++)
                        {
                            //Get the RGB color of the pixel at this point
                            Color color = cutImage.GetPixel(i, j);
                            int value = 255 - color.B;//reverse color
                            Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255);
                            cutImage.SetPixel(i, j, newColor);//update color
                        }
                    }
                    pictureBox2.Image = cutImage;
                   // MessageBox.Show("Complete.");
                }
                else
                {
                    MessageBox.Show("Before binarization, grayscale must be performed!\n \n Image binarization operation steps:\n Open the picture - click [Grayscale] - select ROI-Click [Binarization]\n");
                }
            }
        }
        
        //keyboard shortcuts
        private void dataGridView1_Press(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
            {
                if (dataGridView1.Rows.Count == 0)//fix bug s
                {
                    return;
                }
                else                    
                {
                    if (dataGridView1.CurrentCell.ColumnIndex == 3)  
                    {
                        string filename = dataGridView1.CurrentCell.Value.ToString();
                        currentImage = new Bitmap(filename);
                        pictureBox1.Image = currentImage;
                    }
                }
            }
        }
        //Grayscale histogram
        private void pictureBox2_Click(object sender, EventArgs e)
        {
            if (ifgray == false)
            {
                MessageBox.Show("Grayscale must be performed first\n", "Do you wish to display a grayscale histogram?");
                return;
            }
            else
            {
                if (cutImage == null)
                {
                    MessageBox.Show("must be selected roi\n", "Do you wish to display a grayscale histogram?");
                }
                else
                {
                    int[] values = new int[256];//create array
                    for (int i = 0; i < 256; i++) values[i] = 0;//initialize the array
                    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;//Get the gray value of each point and store it in an array
                            values[value]++;
                        }
                    }
                    //Find the highest value of the data in the image to be drawn
                    int max = 0;
                    foreach (int i in values) max = max > i ? max : i;
                   
                    Image grayImage = null;
                    //drawing, referencing method
                    draw(ref values, max, out grayImage);
                }
            }
        }
        //draw a histogram
        private bool draw(ref int[] datas, int Height, out Image grayImage)
        {
            grayImage = new Bitmap(256, Height + 10); //The maximum value of the y-axis of the image is higher than the maximum value of the data
            Graphics g = Graphics.FromImage(grayImage);
            Pen pen = new Pen(Color.Black);//pen color
            for (int i = 0; i <= 255; i++)
            {
             g.DrawLine(pen, i, Height - datas[i] + 10, i, Height + 10);//Draw a straight line, the grayscale histogram consists of straight lines
            }
                pictureBox3.Image = grayImage;
                return true;
        }
        private void label3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("The grayscale histogram is to count all the pixels in the digital image, according to the size of the grayscale value, to count the frequency of their occurrence.\n \n" +
                "Operations to display grayscale histograms:\n [Grayscale]-[select ROI]-[click roi]\n","Grayscale histogram display teaching");
        }
        
        // Rotate the picture 90 degrees clockwise
        private void btnRotate_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//Button has no effect if no subimage is created
            {               
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                currentImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
                pictureBox1.Image = currentImage;
            }
        }
        // Rotate 90 degrees counterclockwise
        private void btncounterclockwiseRotate_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//Button has no effect if no subimage is created
            {
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                // An additional implementation of a 90 degree counterclockwise rotation
                currentImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
                pictureBox1.Image = currentImage;
               
            }
        }
        //mirror
        private void Button7_Click(object sender, EventArgs e)
        {
            if (currentImage == null)//Button has no effect if no subimage is created
            {
                return;
            }
            else
            {
                pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
                currentImage.RotateFlip(RotateFlipType.Rotate180FlipY);
                pictureBox1.Image = currentImage;
            }
        }
    }
}
 

postscript

In the past few years, I have learned C (C51), assembly, python, C# and VBS in sequence in college. It sounds amazing. In fact, the best one is C (relatively speaking); assembly can only be read but not written. I don't remember how much now; Python and VBS both use which knowledge points to learn, and there is no general concept.
C# is the last language I learned in a formal course, I learned it very seriously, and I feel very good about myself (although it's all self-taught and I haven't watched the video seriously). Because of the epidemic, before I returned to school, I had already started to work on this final project, and the addition of functions was addicting. Every day I wondered how I could make a foolish operation. I think it's too watery, can I add another one? In the end, I worked on the project for 20 days before and after, and it was considered a good level in the class (I think). Frankly speaking, after finishing this project, I never touched C# again (in fact, I made a semi-finished product for another project, and I always wondered if I could use C# to compile a small tool in other projects, and only make a semi-finished product The reason is that the amount of knowledge required to complete it is beyond my level at that time), I don't know what the level of this project is, but for a beginner, I am relatively satisfied with the knowledge I have.
One of the very important purposes of learning C# at the beginning was to understand the difference between object-oriented and process-oriented, even though I had taught myself mircoPython at that time, it was only the degree of library adjustment.

2020/8/19/20:20

Tags: C# Programming winform

Posted by thestars on Sat, 21 May 2022 23:02:25 +0300