SoFunction
Updated on 2024-10-28

How to binarize an image in opencv python

This article introduces the opencv python how to achieve the image binarization, the text through the sample code describes the details of everyone's learning or work has a certain reference learning value, you can refer to the following friends

The code is as follows

import cv2 as cv
import numpy as np
import  as plt

# A binary image is a grayscale map converted to black and white, no gray, black before a value and white after it
# There are both global and local
# When using global thresholds, we're just given a random number to threshold, so how do we know how good or bad the number we picked is? The answer is to keep trying.
# What if it's a bimodal image (in simple terms a bimodal image is one with two peaks in the image histogram)?
# Shouldn't we pick a value for the peak and valley between the two peaks to use as a threshold? That's what Otsu binarization is going to do.
# Simply put, a threshold is automatically calculated for a bimodal image based on its histogram.
# (for non-bimodal images, this method may give unsatisfactory results).


def threshold_demo(image):
  gray = (image, cv.COLOR_BGR2GRAY)

  # The first argument to this function is the original image, which should be a grayscale image.
  # The second parameter is the threshold used to categorize the pixel values.
  # The third parameter is the new pixel value that should be assigned when the pixel value is above (or sometimes below) the threshold value
  # A fourth parameter to determine the threshold method, see threshold_simple()
  # ret, binary = (gray, 127, 255, cv.THRESH_BINARY)
  ret, binary = (gray, 127, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
  print("threshold value: %s"%ret)
  ("threshold_demo", binary)


def threshold_simple(image):
  img = (image, cv.COLOR_BGR2GRAY)
  ret, thresh1 = (img, 127, 255, cv.THRESH_BINARY)
  ret, thresh2 = (img, 127, 255, cv.THRESH_BINARY_INV)
  ret, thresh3 = (img, 127, 255, cv.THRESH_TRUNC)
  ret, thresh4 = (img, 127, 255, cv.THRESH_TOZERO)
  ret, thresh5 = (img, 127, 255, cv.THRESH_TOZERO_INV)
  titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
  images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

  for i in range(6):
    (2, 3, i + 1), (images[i], 'gray') # Spread the image 2x3
    (titles[i])
    ([]), ([])

  ()


# In the previous section we used global thresholding, where the whole image is thresholded with the same number.
# At that time this method was not adapted to all cases, especially when different parts of the same image had different brightnesses.
# In this case we need to use adaptive thresholding. In this case, the threshold is calculated for each small region of the image.
# So different thresholds are used for different regions on the same image, which allows us to get better results with varying brightness.
# This method requires us to specify three parameters, and the return value is only one
# _MEAN_C: the threshold is taken from the average of the neighboring regions, _GAUSSIAN_C: the threshold is taken from the weighted sum of the neighboring regions, the weight is a Gaussian window.
# Block Size - Neighborhood size (the size of the area used to calculate the threshold).
# C - This is is a constant, and the threshold is then equal to the mean or weighted average minus this constant.

def threshold_adaptive(image):
  img = (image, cv.COLOR_BGR2GRAY)
  # Median filtering
  img = (img,5)

  ret, th1 = (img, 127, 255, cv.THRESH_BINARY)
  # 11 is the block size, 2 is the C value
  th2 = (img, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 2)
  th3 = (img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 2)

  titles = ['Original Image', 'Global Threshold (v = 127)', 'Adaptive Mean Threshold', 'Adaptive Gaussian Threshold']
  images = [img, th1, th2, th3]

  for i in range(4):
    (2, 2, i + 1), (images[i], 'gray')
    (titles[i])
    ([]), ([])

  ()


def threshold_custom(image):
  gray = (image, cv.COLOR_BGR2GRAY)
  h, w = [:2]
  m = (gray, [1, w*h])
  mean = () / (w*h) # Find the average of the entire grayscale image
  print("mean:", mean)
  ret, binary = (gray, mean, 255, cv.THRESH_BINARY)
  ("threshold_custom", binary)


# It's better to split large images into small ones before using adaptive local thresholding
def big_image_demo(image):
  print()
  cw = 200
  ch = 200
  h, w = [:2]
  gray = (image, cv.COLOR_BGR2GRAY)
  ("big_image_demo_gray", gray)

  # Split a picture every ch * cw
  for row in range(0, h, ch):
    for col in range(0, w, cw):
      roi = gray[row:row+ch, col:col+cw]
      dst = (roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 127, 2)
      gray[row:row + ch, col:col + cw] = dst
      print((dst), (dst))

  ("../images/result_big_image.png", gray)


def main():
  img = ("../images/")
  # threshold_demo(img)
  # threshold_simple(img)
  # threshold_adaptive(img)
  # threshold_custom(img)
  src = ("../images/big_image.jpg")
  big_image_demo(src)
  (0) # Wait for key input or automatically remove the window after 1000ms, 0 means end the window with key input only.
  () # Close all windows


if __name__ == '__main__':
  main()

This is the whole content of this article.