Binarization of images

Image binarization is to set the gray value of pixels on the image to 0 or 255, that is, the whole image presents an obvious black and white effect. The binarization images with 256 luminance levels can be obtained by selecting appropriate thresholds which can still reflect the whole and local features of the image. In digital image processing, binary image plays a very important role. First of all, the binary image is conducive to further image processing, making the image simple, and the amount of data is reduced, which can highlight the outline of the target of interest. Secondly, to carry on the binary image processing and analysis, first of all to the gray image binarization, binarization image.

In practical application, a lot of image analysis is eventually transformed into binary image analysis, such as medical image analysis, foreground detection, character recognition, shape recognition. Binarization + mathematical morphology can solve many problems of object extraction in computer recognition engineering.

Open operation demonstration — text separation and cutting

The opening operation is the process of corrosion and expansion. Used to eliminate small objects, separate objects at slender points, and smooth the boundaries of larger objects without significantly changing their area.

The counterpart of the open operation is the closed operation. In addition, corrosion and expansion are described below.

In CV4J, we encapsulate the common operations of morphology, such as open and close operations, corrosion, and bloat.

Where, the code of open operation is as follows:

public class MorphOpen {
    /**
     * in order to remove litter noise block, erode + dilate operator
     *
     * @param binary
     * @param structureElement
     */
    public void process(ByteProcessor binary, Size structureElement) {
        Erode erode = new Erode();
        Dilate dilate = newDilate(); erode.process(binary, structureElement); dilate.process(binary, structureElement); }}Copy the code

Let’s start with a full demo

PNG full demo effect

Step 3 If you can’t see clearly, let’s take a look at the enlarged renderings

Zoom in on the third step. PNG

As you can see in the image above, the demo has finished cutting the text. Let’s see how the code works.

Preparation show the original picture

        Resources res = getResources();
        final Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.test_binary1);
        image0.setImageBitmap(bitmap);Copy the code

The first step is binarization

        CV4JImage cv4JImage = new CV4JImage(bitmap);
        Threshold threshold = newThreshold(); threshold.process((ByteProcessor)(cv4JImage.convert2Gray().getProcessor()),Threshold.THRESH_TRIANGLE,Threshold.METHOD_TH RESH_BINARY_INV,255);
        image1.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());Copy the code

The second step is to start operation

MorphOpen morphOpen = new MorphOpen();
cv4JImage.resetBitmap();
morphOpen.process((ByteProcessor)cv4JImage.getProcessor(),new Size(5));

image2.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());Copy the code

The third step connects the component tag

        ConnectedAreaLabel connectedAreaLabel = new ConnectedAreaLabel();
        byte[] mask = new byte[cv4JImage.getProcessor().getWidth() * cv4JImage.getProcessor().getHeight()];
        List<Rect> rectangles = new ArrayList<>();
        connectedAreaLabel.process((ByteProcessor)cv4JImage.getProcessor(),mask,rectangles,true);
        cv4JImage.resetBitmap();
        Bitmap newBitmap = cv4JImage.getProcessor().getImage().toBitmap();

        if (Preconditions.isNotBlank(rectangles)) {
            Tools.drawRects(newBitmap,rectangles);
        }

        image3.setImageBitmap(newBitmap);Copy the code

In fact, after the third step and the COMBINATION of OCR can recognize the specific text. If combined with the web crawler, the meaning is even greater.

Although CV4J is currently only a mobile library, it was developed in Java and can be easily adapted for desktop.

Corrosion operation demonstration — coin counting

Corrosion operation is a process of eliminating boundary points and making the boundary shrink inward. Can be used to eliminate small and meaningless objects. The corrosion operation scans each pixel of the image and does an “and” operation with the structural element and its overlaid binary image: if both are 1, the pixel of the resulting image is 1, otherwise it is 0.

The opposite of the corrosion operation is the expansion operation. Etch is used to divide individual image elements, while bloat is used to join adjacent elements.

Corrosion algorithm:

PNG for corrosion operation


It can be simplified as:

Simplified corrosion operation. PNG

So let’s take an example, where we have a bunch of coins in the original drawing, and we do a step-by-step analysis to figure out how many coins there are.

Coin count 1.png

Coin count 2.png

Preparation show the original picture

        Resources res = getResources();
        final Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.test_coins);
        image0.setImageBitmap(bitmap);Copy the code

The first step is binarization

        CV4JImage cv4JImage = new CV4JImage(bitmap);
        Threshold threshold = newThreshold(); threshold.process((ByteProcessor)(cv4JImage.convert2Gray().getProcessor()),Threshold.THRESH_OTSU,Threshold.METHOD_THRESH _BINARY_INV,255);
        image1.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());Copy the code

The second step is corrosion operation

        Erode erode = new Erode();
        cv4JImage.resetBitmap();
        erode.process((ByteProcessor)cv4JImage.getProcessor(),new Size(3),10);
        image2.setImageBitmap(cv4JImage.getProcessor().getImage().toBitmap());Copy the code

The third step connects the component tag

        ConnectedAreaLabel connectedAreaLabel = new ConnectedAreaLabel();
        byte[] mask = new byte[cv4JImage.getProcessor().getWidth() * cv4JImage.getProcessor().getHeight()];

        int num = connectedAreaLabel.process((ByteProcessor)cv4JImage.getProcessor(),mask,null.false); // Get the number of connected components

        SparseIntArray colors = new SparseIntArray();
        Random random = new Random();

        int height = cv4JImage.getProcessor().getHeight();
        int width = cv4JImage.getProcessor().getWidth();
        int size = height * width;
        for (int i = 0; i<size; i++) {int c = mask[i] & 0xff;
            colors.put(c,Color.argb(255, random.nextInt(255),random.nextInt(255),random.nextInt(255)));
        }

        cv4JImage.resetBitmap();
        Bitmap newBitmap = cv4JImage.getProcessor().getImage().toBitmap();

        for(int row=0; row<height; row++) {
            for (int col = 0; col < width; col++) {

                int c = mask[row*width+col] & 0xff;
                if (c>0) {
                    newBitmap.setPixel(col,row,colors.get(c));
                }
            }
        }

        image3.setImageBitmap(newBitmap);

        if (num>0)
            numTextView.setText(String.format("A total of % D coins were identified.",num));Copy the code

Finally, the number of connected components is obtained, that is, the number of coins, and the identified coins are randomly colored.

Cv4j is an image processing library hyperyfish and I developed together, with a pure Java implementation, which is still in its early version. This week, we started to do analysis of binary images (corrosion, expansion, open and close operation, contour extraction, etc.). This module has not completed all functions, and it is expected to be completed next week.

Previous article: Java implements Gaussian blur and spatial convolution of images Java implements advanced gameplay of image filters Java implements image filter effects