Java-like image processing in camera

Image processing in Java-like cameras (on)

1. Introduction

2. Project process

\qquad 1. Create the form

\qquad 2. Action Listener

\qquad 3. Get the pixel value of the image file

\qquad 4. Draw the original painting

\qquad 5. Draw grayscale images

\qquad 6. Draw a black and white binary image

\qquad 7. Draw a mosaic

3. Effect picture

1. Introduction

\qquad The last article introduced the principle of images, RGB tricolor values ​​are stored in int values ​​and then split into tricolor values, displacement operators in Java and hexadecimal numbers. In this article, I will put these into practice, Make a few simple image processing functions.

2. Project process

1. Create the form

   First, we need a form to display images, so we use the JFrame we learned before, and add an action listener ImageListener for each button to implement the functions separately.

public class ImagePad {
    String[] strs = {"Open","save","original image","grayscale","Binarization","mosaic","dot mosaic",
            "nostalgic","contour","sketch","sharpen","zoom out","enlarge",
    };// This article is not fully implemented, but a complete project will be made later
    // Create a listener object
    ImageListener img1 = new ImageListener();

    public void showUI(){
        JFrame jf = new JFrame("Image Processing V1.0");
        jf.setSize(800,600);//size
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//close directly
        jf.setLocationRelativeTo(null);//Center popup
        jf.setLayout(new FlowLayout());//Flow layout

        // Create button object | set properties (text size background color font size listener)
        Font font = new Font("black body",Font.BOLD,16);
        for (int i = 0; i < strs.length; i++) {
            JButton btn = new JButton(strs[i]);
            btn.setBackground(Color.WHITE);
            btn.setFont(font);
            btn.addActionListener(img1);//Add action listener
            jf.add(btn);
        }

        jf.setVisible(true);
        // After visualization, get a Graphics
        img1.g = jf.getGraphics();//The listener gets the brush in the form
    }

    public static void main(String[] args) {
        new ImagePad().showUI();
    }
}

2. Action Listener

   Before talking about the action listener, let me list the new knowledge used in this action listener.

  1. Code block: {}:

    • In the program, use a pair of square brackets to include some code statements, which means that the object is executed when the object is created, which means initialization.

    • You can put some functions that often need the same call in the program, which can save time and avoid unnecessary overhead.

  2. switch(a) case statement:

    • The switch-case statement can easily enumerate the situation, which is much simpler than the usual if else if.... According to the value of a and case, the corresponding code is run.

    • Don't forget to break; to jump out of the loop, you can also write a default statement to facilitate execution when it is not satisfied.

   Below is the code of the action listener ImageListener

public class ImageListener implements ActionListener {
    ImageTools imgtools = new ImageTools();
    Graphics g;
    int[][] imageArr;

    {// The code block executes the initialized method call when the object is created
        String path = "D:\\OneDrive\\desktop\\xinhai.jpg";
        // Pass in the image path to get the pixel moment two-dimensional array of the image
        imageArr = imgtools.getImagePiexArray (path);//I'll talk about it later, don't worry
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // get the string on the button
        String btnStr = e.getActionCommand();
        System.out.println("Clicked:"+ btnStr);

        // Draw a picture based on the clicked string action
        switch (btnStr){
            case "original image":
                // draw pictures
                System.out.println("original image");
                imgtools.drawImage(imageArr,g);
                break;
            case "grayscale":
                imgtools.drawGrayImage(imageArr,g);
                break;
            case "Binarization":
                imgtools.drawBinaryImage(imageArr,g);
                break;
            case "mosaic":
                imgtools.drawMosaicImage(imageArr,g);
                break;
        }
    }
}

3. Get the pixel value of the image file

   This basic framework is ready, let's now learn the implementation of the drawing function.

First popularize a little knowledge, enter /** in front of the method that has been written in the idea and press Enter, a new comment will appear, called a document comment. For example

/** Documentation Notes
     * Get a two-dimensional pixel array of an image based on a path
     * @param path Parameters: image path
     * @return two-digit array of pictures
     */

  We first consider how to draw the original image

   First, we need to create a method to get the pixels in the image. Since the image is a two-dimensional matrix, our return value should also be a two-dimensional array.

  We need to get the pixels in the image file first, so naturally we need to use file operations,

/** Documentation Notes
 * Get a two-dimensional pixel array of an image based on a path
 * @param path Parameters: image path
 * @return two-digit array of pictures
 */  
public int[][] getImagePiexArray(String path){
    File file = new File(path);//path is the path to the file
}

   Then we use the BufferedImage class to create an image buffer, which is used to load the image into memory, and the image can be easily manipulated through the image buffer.

BufferedImage buffimg = null;

   Read the image file object file created above through the read method in ImageIO and load it in buffimg

buffimg = ImageIO.read(file);

   But if you write it like this, you will find an error

   prompts us to try catch around, then click and do as it says

   Now there is no error

   Now that the data of this image has been stored in buffimg, we can proceed further.

  The essence of the picture is a two-dimensional matrix of pixel values. The same is true for buffimg. We obtain the length and width of this two-dimensional matrix respectively.

//buffimg width height pixel value
int width = buffimg.getWidth();
int height = buffimg.getHeight();

   Now we create a two-dimensional array imgArr with the same length and width, in order to store the pixel value of each position of the image below.

int[][] imgArr = new int[width][height];

   Next we traverse this two-dimensional array and store the pixel RGB values ​​in bufferimg into imgArr. The getRGB(int x,int y) method in BufferedImage is used to get the pixel at a certain position

for (int i = 0; i < imgArr.length; i++) {
    for (int j = 0; j < imgArr[i].length; j++) {
        imgArr[i][j] = buffimg.getRGB(i,j);
    }
}
return imgArr;

   The method for obtaining the pixel value of the image is finished, and we can call it in other methods to quickly obtain the image pixel.

  The complete code is as follows

public int[][] getImagePiexArray(String path){
        File file = new File(path);
        BufferedImage buffimg = null;

        try {
            buffimg = ImageIO.read(file);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //buffimg width height pixel value
        int width = buffimg.getWidth();
        int height = buffimg.getHeight();
        // Create a two-dimensional array based on width and height
        int[][] imgArr = new int[width][height];

        // Traverse the loop and store all the pixel values ​​in the array
        // Traverse from the beginning to the end, take out all
        for (int i = 0; i < imgArr.length; i++) {
            for (int j = 0; j < imgArr[i].length; j++) {
                imgArr[i][j] = buffimg.getRGB(i,j);
            }
        }
        return imgArr;
}

4. Draw the original image

   Now let's draw the original image. The idea is very simple, that is to draw the obtained imgArr array intact, because our imgArr is originally the pixel of the stored image file, then directly traversing the array and drawing it is the original image.

   For drawing, we definitely need the brush object Graphics. We can draw each pixel value in the way we like, such as drawing according to rectangle, drawing according to circle and so on.

    /**
     * original image
     * @param imgArr
     * @param g
     */
    public void drawImage(int[][] imgArr, Graphics g){
        for (int i = 0; i < imgArr.length; i++) {
            for (int j = 0; j < imgArr[i].length; j++) {
                int pixnum = imgArr[i][j];//Get the current pixel color, expressed as an int value
                Color color = new Color(pixnum);
                g.setColor(color);
                X Y Set the position of the image for a predefined offset value
                g.fillRect(X + i, Y + j, 1, 1);//Drawing in a rectangle, the original image pixel is also a 1*1 rectangle, so there will be no gaps
            }
        }
    }

5. Draw grayscale images

  The drawing method of the grayscale image is similar to the original image, except that the color value cannot be directly used imgArr[i][j], but three primary colors must be split and mixed in a certain proportion.

6 ways to draw grayscale images:

1. Floating point method: Gray=R0.3+G0.59+B*0.11

2. Integer method: Gray=(R30+G59+B*11)/100

3. Shift method: Gray =(R77+G151+B*28)>>8;

4. Average method: Gray=(R+G+B)/3;

5. Only take green: Gray=G;

6.Gamma correction algorithm:

   Here I use the fourth method of averaging:

   used the int value of the previous lesson to split into RGB

    /**
     * Grayscale
     * @param imgArr
     * @param g
     */
    public void drawGrayImage(int[][] imgArr, Graphics g){
        for (int i = 0; i < imgArr.length; i++) {
            for (int j = 0; j < imgArr[i].length; j++) {
                int pixnum = imgArr[i][j];
                // Split pixel value to RGB
                int red = (pixnum >> 16) & 255;
                int green = (pixnum >> 8) & 255;
                int blue = (pixnum >> 0) & 255;
                // The principle of grayscale R=G=B
                // mean method
                int gray = (red + green + blue)/3;
                Color color = new Color(gray,gray,gray);
                g.setColor(color);
                g.fillRect(X + i, Y + j,1 ,1);
            }
        }
    }

6. Draw a black and white binary image

The principle of    is similar, that is, the gray value is divided again, and the gray value greater than or equal to 127 is set to white, and the value less than 127 is set to black, and a simple binarization is completed.

    /**
     * black and white
     * @param imgArr
     * @param g
     */
    public void drawBinaryImage(int[][] imgArr, Graphics g){
        for (int i = 0; i < imgArr.length; i++) {
            for (int j = 0; j < imgArr[i].length; j++) {
                int pixnum = imgArr[i][j];
                // Split pixel value to RGB
                int red = (pixnum >> 16) & 255;
                int green = (pixnum >> 8) & 255;
                int blue = (pixnum >> 0) & 255;
                // The principle of grayscale R=G=B
                // mean method
                int gray = (red + green + blue)/3;
                // Use gray value to do bisection
                if(gray < 127){
                    g.setColor(Color.BLACK);
                }else {
                    g.setColor(Color.WHITE);
                }
                g.fillRect(X + i, Y + j,1 ,1);
            }
        }
    }    

7. Draw a mosaic

  We used to draw the rectangular frame according to 1 * 1. If we change it to 10 * 10, and change the convenient step size of the array to 10, then a simple mosaic effect is achieved, because the pixel block becomes larger. .

    /**
     * mosaic
     * @param imgArr
     * @param g
     */
    public void drawMosaicImage(int[][] imgArr, Graphics g){
        for (int i = 0; i < imgArr.length; i+=10) {
            for (int j = 0; j < imgArr[i].length; j+=10) {
                int pixnum = imgArr[i][j];
                // interval sampling
                Color color = new Color(pixnum);
                g.setColor(color);
                g.fillRect(X+i,Y+j,10,10);
            }
        }
    }

Three, renderings (using the popular heart sea expression pack)

original image

Grayscale

Black and white binary image

mosaic map

Tags: Java image processing Front-end

Posted by dreams4000 on Tue, 11 Oct 2022 18:12:04 +0530