今天详细介绍一下图像处理基础算法---图像处理灰度二值化。

通过阅读本文,可以了解:

  1. 图像灰度二值化是什么?
  2. 图像灰度二值化有哪些常见算法?
  3. 图像灰度二值化的Python实现?
  4. 图像灰度二值化的FPGA实现?

一、什么是图像处理二值化?

图像处理的灰度二值化是图像处理中一种重要的技术,它可以将灰度图像转换为二值图像,以便于后续的处理和分析,比如分割图像主体和背景,提取自己感兴趣的部分。

灰度图像是一种每个像素只有一个灰度值的图像,其灰度值通常表示像素的亮度或暗度。在灰度图像中,像素值越高表示越亮,越低表示越暗。而二值图像则是一种每个像素只有两个可能的值(通常是0和255)的图像,其中0表示黑色,255表示白色。因此,二值图像通常呈现出明显的黑白效果。

在灰度二值化的过程中,需要选择一个阈值,将灰度图像中的像素值与阈值进行比较,如果像素值大于阈值,则将该像素设置为白色(255),否则设置为黑色(0)。这样,就可以将灰度图像转换为二值图像。

在选择阈值时,需要考虑图像的具体情况和处理需求。如果阈值选择得过高,可能会导致目标区域的一部分被误判为背景;而如果阈值选择得过低,则可能会导致背景区域的一部分被误判为目标。因此,需要根据实际情况进行调整和优化。

灰度二值化在图像处理中有许多应用,例如文字识别、条形码识别、图像分割等。通过灰度二值化,可以将图像中的目标区域与背景区域分离开来,从而方便后续的处理和分析。同时,由于二值图像的存储空间较小,因此也可以减少图像处理过程中的计算量和存储成本。

二、图像二值化的常用算法

1、全局二值化

全局二值化是设定一个全局阈值T,将图像中的像素数据分为两部分:大于T的像素群和小于等于T的像素群。大于T的像素群的像素值设定为白色(或黑色),小于等于T的像素群的像素值设定为黑色(或白色)。这种方法在表现图像细节方面存在较大缺陷。

(1)固定阈值

选择127(灰度值范围的一半)作为阈值T。

(2)平均值阈值

将整幅图像的灰度平均值作为二值化的阈值T

(3)双峰法

图像灰度二值化的双峰法是一种基于图像灰度直方图的二值化方法。在图像的灰度直方图中,如果物体的灰度分布比较有规律,背景与目标在图像的直方图各自形成一个波峰,那么,选择双峰之间的波谷所代表的灰度值作为阈值。

FPGA Image Processing

双峰法只适用于目标和背景的灰度值在直方图中形成两个明显的波峰的情况。如果直方图中的波峰不明显或者存在多个波峰,则双峰法可能无法取得理想的二值化效果。

(4)OTSU法(大律法)

图像灰度二值化的大律法(Otsu's method)是一种通过计算类间方差来确定图像二值化分割阈值的方法。

该方法是由日本学者大津于1979年提出的,所以又称为大津法。其原理是:对于一副灰度图像,通过选择一个合适的阈值将其分为前景和背景两部分,使得前景和背景之间的类间方差最大。

当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。具体步骤如下

  1. 对于每个灰度级T(T=0~255),计算前景像素点数占图像比例和平均灰度,背景像素点数占图像比例和平均灰度,进而计算出整幅图像的平均灰度。
  2. 使用公式计算出类间方差g。
  3. 遍历所有灰度级,找到使得类间方差g最大的灰度级T,即为最佳阈值。
  4. 利用得到的最佳阈值T将原图像进行二值化处理。

2、局部二值化

局部二值化方法是针对全局二值化方法的缺陷而提出的。它将整幅图像划分为多个窗口,对每个窗口设定一个局部阈值T,然后对每个窗口进行二值化处理。

在处理每个窗口时,可以选择一个固定的阈值,也可以使用一些自适应的阈值选择方法,如基于窗口内像素灰度值的平均值或中值等。

它用一个滑窗扫描图像,并取滑窗中心点亮度与滑窗内其他区域(称为邻域, neighborhood area)的亮度进行比较。如果中心点亮度高于邻域亮度,则将中心点标记为白色,否则标记为黑色。

三、python实现

1、简单阈值分割(Simple Thresholding)


import cv2
import numpy as np
import matplotlib.pyplot as plt

# 1. 读取图像
img_s = cv2.imread('1280_720.bmp')

height = img_s.shape[0]
width = img_s.shape[1]

# 创建一幅图像
grayimg = np.zeros((height, width, 3), np.uint8)

for i in range(height):
    for j in range(width):
        # 灰度加权平均法
        gray = 0.30 * img_s[i, j][0] + 0.59 * \
            img_s[i, j][1] + 0.11 * img_s[i, j][2]
        grayimg[i, j] = np.uint8(gray)

img = grayimg[:, :, ::-1]

# 应用5种不同的阈值方法
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, th2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, th3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, th4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, th5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, th1, th2, th3, th4, th5]

# 使用Matplotlib显示
for i in range(6):
    plt.subplot(2, 3, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i], fontsize=8)
    plt.xticks([]), plt.yticks([])  # 隐藏坐标轴

plt.show()

FPGA Image Processing

2、自适应阈值分割(Adaptive Thresholding)


import cv2
import matplotlib.pyplot as plt

# 读取图像
img_s = cv2.imread('1280_720.bmp')

# 图像灰度化处理
img = cv2.cvtColor(img_s, cv2.COLOR_BGR2GRAY)

# 固定阈值
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)


# 自适应阈值
th2 = cv2.adaptiveThreshold(
    img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, 4)
th3 = cv2.adaptiveThreshold(
    img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, 8)

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

for i in range(4):
    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i], fontsize=8)
    plt.xticks([]), plt.yticks([])
plt.show()

FPGA Image Processing

四、FPGA实现

​图像灰度二值化,需要在灰度图像的基础上再做二值化处理,如果对【彩色图像灰度化】不了解,可以先阅读这个文章。

FPGA图像处理实战- 彩色图像灰度化

FPGA实现思路:

灰度二值化处理的关键是这个阈值的计算,除了简单阈值法外,其它算法都需要统计分析一整副画面的数据,这里就需要DDR来做帧缓存,在进入DDR之前做数据统计分析出最佳阈值,然后从DDR中读取出来时做二值化处理。

FPGA实现代码:

这里就不写了,简单阈值算法,直接判断每个像素点的灰度值与阈值大小比较,大于阈值则RGB都赋值为255,小于等于阈值则RGB都赋值为0