【图像处理】灰度图像与二值化

参考文章:

OpenCV------灰度图像与图像二值化处理

一、灰度图

1.1 灰度图是什么

灰度图(Gray Scale Image) 仅用灰度色阶表示图像亮度的非色彩图像,像素值范围通常为0(纯黑)到255(纯白)之间的256个等级。

  • 灰度图与彩色图的核心区别:彩色图由R、G、B三通道组成,而灰度图仅单通道。彩色图转灰度图的本质是将三通道合并为单通道。
  • 灰度图像每个像素只有一个采样颜色,显示为从黑到白的灰度渐变(256级,8位存储),不同于只有黑白两色的黑白图像。

一副灰度图像示例:

二、图像二值化

2.1 图像二值化是什么

图像二值化:通过设定阈值将灰度图像转换为仅含两个值(通常为0和255)的图像,是图像处理的基础技术

2.2 常见的二值化方法

2.2.1 最大值法

对彩色图像的每个像素,从R、G、B三通道值中选取最大值作为灰度图对应位置的像素值。

例如,某像素RGB值为(91,121,46),最大值为121,故灰度值为121。

代码示例:

python 复制代码
import cv2 as cv
import numpy as np
#读图
cat=cv.imread("../images/cat1.png")
h,w=cat.shape[:2]
black=np.zeros((h,w),dtype=np.uint8)

#遍历行
for i in range(h):
    #遍历列
    for j in range(w):
        black[i,j]=max(cat[i,j][0],cat[i,j][1],cat[i,j][2])
#显示
cv.imshow("black",black)
cv.waitKey(0)
cv.destroyAllWindows()

2.2.2 平均值法

对彩色图像的每个像素,计算R、G、B三通道值的平均值(求和后除以3,取整)作为灰度值。

示例:某像素RGB值为(91,121,46),平均值为(91+121+46)/3=86,故灰度值为86。

代码示例:

python 复制代码
#读图
cat=cv.imread("../images/cat1.png")
h,w=cat.shape[:2]
black=np.zeros((h,w),dtype=np.uint8)

#遍历行
for i in range(h):
    #遍历列
    for j in range(w):#防止溢出
        black[i,j]=np.uint8((int(cat[i,j,0])+int(cat[i,j,1])+int(cat[i,j,2]))//3)
#显示
cv.imshow("black",black)
cv.waitKey(0)
cv.destroyAllWindows()

2.2.3 加权平均值法

按固定权重计算R、G、B三通道的加权和作为灰度值,常用权重为:R×0.299、G×0.587、B×0.114(权重和为1)。

示例:某像素RGB值为(10,121,46),加权和为10×0.299+121×0.587+46×0.114=79,故灰度值为79。

代码示例:

python 复制代码
import cv2 as cv
import numpy as np
#读图
cat=cv.imread("../images/cat1.png")
h,w=cat.shape[:2]
black=np.zeros((h,w),dtype=np.uint8)
#定义每个通道上的权重
wb,wg,wr=0.114,0.587,0.299
#遍历行
for i in range(h):
    #遍历列
    for j in range(w):
        black[i,j]=round(wb*cat[i,j][0]+wg*cat[i,j][1]+wr*cat[i,j][2])
#显示
cv.imshow("black",black)
cv.waitKey(0)
cv.destroyAllWindows()

最常见的加权均值代码可直接使用OpenCV内置函数实现。

2.2.4 两个极端的灰度值

灰度图像中亮度的两个极端:

  • 最暗的灰度值:0(纯黑,无任何亮度)
  • 最亮的灰度值:255(纯白,最大亮度)


(上:灰度值0(纯黑);下:灰度值255(纯白))

2.3 图像二值化处理

二值图像的二维矩阵仅含0(黑)和1(或255,白),数据类型通常为1个二进制位,适用于文字识别、掩膜存储等场景。

一副二值化后的图像示例:

注意:二值化处理的输入必须是灰度图,过程是将灰度图像素按规则修改为0和maxval(通常255),以简化图像、节约资源、辅助边缘检测。

2.3.1全局阈值法:

binary = cv.threshold(img,thresh,maxval,type)

  • 参数说明

    • img:输入的灰度图
    • thresh:设定的阈值
    • maxval:最大值(通常为255)
    • type:阈值处理类型
  • 返回值

    • 第一个值(常用_表示):计算出的阈值(自适应阈值时自动生成)
    • 第二个值(binary):二值化后的图像矩阵
1. 阈值法(THRESH_BINARY)

像素值≤阈值时设为0,>阈值时设为maxval(前景)。

示例:

效果对比:


(上:灰度图;下:二值化图)

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
#二值化:阈值法
_,binary=cv.threshold(gray,127,255,cv.THRESH_BINARY)
print()#返回的是一个浮点数

cv.imshow("gray",gray)
cv.imshow("binary",binary)
cv.waitKey(0)
cv.destroyAllWindows()

代码结果:

灰度化也可直接用cv.IMREAD_GRAYSCALE标志:cv.imread()以灰度格式读取图像。

2. 反阈值法(THRESH_BINARY_INV)

与阈值法相反:像素值>阈值时设为0,≤阈值时设为maxval。

示例:

效果对比:



(上:灰度图;下:二值化图)

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
#二值化:反阈值法
gray=cv.resize(gray, (480,480))
_,binary_inv=cv.threshold(gray, 127, 255,cv.THRESH_BINARY_INV)

cv.imshow("gray",gray)
cv.imshow("binary_inv",binary_inv)
cv.waitKey(0)
cv.destroyAllWindows()
3. 截断阈值法(THRESH_TRUNC)

像素值>阈值时设为阈值,≤阈值时不变(最大像素值为阈值,maxval参数无效)。

示例:

效果对比(阈值255时与原图一致):


(上:灰度图;下:二值化图)

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray=cv.resize(gray,(480,480))
#截断阈值法
thresh,truc=cv.threshold(gray,127,255,cv.THRESH_TRUNC)

cv.imshow("gray",gray)
cv.imshow("truc",truc)
cv.waitKey(0)
cv.destroyAllWindows()
4. 低阈值零处理(THRESH_TOZERO)

像素值≤阈值时设为0,>阈值时不变(生成的图像像素值可能多于2个)。

示例:

效果对比:



(上:灰度图;下:二值化图)

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray=cv.resize(gray,(480,480))
#低阈值,零处理
thresh,zeros=cv.threshold(gray,127,255,cv.THRESH_TOZERO)
cv.imshow("zero",zeros)
cv.waitKey(0)
cv.destroyAllWindows()
5. 超阈值零处理(THRESH_TOZERO_INV)

像素值>阈值时设为0,≤阈值时不变。

示例:

效果对比:



(上:灰度图; 下:二值化图)

2.3.2 非全局阈值

全局阈值法需手动设置阈值,不适用于明暗不均的图像,因此需自动计算阈值的方法。

1. OTSU阈值法

THRESH_OTSU是与二值化方法结合使用的标志(通常与THRESH_BINARYTHRESH_BINARY_INV结合),通过最大类间方差自动计算阈值,适用于双峰图像(灰度直方图有两个峰值)。

灰度图直方图基础

  • 灰度级:0(黑)到255(白)的亮度值
  • 直方图:x轴为灰度级,y轴为对应灰度级的像素数量

双峰图像直方图示例:

核心原理:遍历灰度值范围,找到使前景(<阈值)与背景(>阈值)类间方差最大的阈值(类间方差越大,前景与背景差异越明显)。

类间方差公式:
g = ω 0 ( μ 0 − μ ) 2 + ω 1 ( μ 1 − μ ) 2 g=\omega_0(\mu_0-\mu)^2+\omega_1(\mu_1-\mu)^2 g=ω0(μ0−μ)2+ω1(μ1−μ)2

其中:

  • T T T:阈值
  • N 0 / N 1 N_0/N_1 N0/N1:前景/背景像素数
  • ω 0 / ω 1 \omega_0/\omega_1 ω0/ω1:前景/背景像素占比
  • μ 0 / μ 1 \mu_0/\mu_1 μ0/μ1:前景/背景平均像素值
  • μ \mu μ:整幅图平均像素值

效果对比:

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray=cv.resize(gray,(480,480))

#OTSU阈值法,默认结合阈值法 最大类间方差 cv.THRESH_OTSU=cv.THRESH_OTSU+cv.THRESH_BINARY
thresh,otsu=cv.threshold(gray,127,255,cv.THRESH_OTSU)
cv.imshow("ostu", otsu)
#print(thresh)
#OTSU+反阈值法
thresh,otsu_inv=cv.threshold(gray,127,255,cv.THRESH_OTSU+cv.THRESH_BINARY_INV)
cv.imshow("otsu_inv", otsu_inv)
cv.waitKey(0)
cv.destroyAllWindows()
2. 自适应二值化

适用于明暗分布不均的图像,为每个像素计算局部阈值(基于周围邻域像素值)。

函数:cv.adaptiveThreshold(image_np_gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 7, 10)

参数说明

  • maxval:最大阈值(通常255)
  • adaptiveMethod:局部阈值计算方式
    • ADAPTIVE_THRESH_MEAN_C:邻域均值
    • ADAPTIVE_THRESH_GAUSSIAN_C:邻域高斯加权和
  • thresholdType:二值化类型(仅THRESH_BINARYTHRESH_BINARY_INV
  • blockSize:邻域大小(奇数,如7×7)
  • c:阈值修正值(最终阈值=邻域计算值-c)
(1)取均值

以3×3邻域为例,计算每个像素邻域内的平均值(边缘填充边界像素),减去c得到阈值,再按二值化规则处理。

计算过程示例:

(2)加权求和

基于高斯分布的权重对邻域像素加权求和,权重来自高斯核(如3×3核的默认权重)。

二维高斯函数:
g ( x , y ) = 1 2 π σ 2 e − ( x 2 + y 2 ) 2 σ 2 g(x,y)=\frac{1}{2\pi \sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma ^{2}}} g(x,y)=2πσ21e−2σ2(x2+y2)

3×3高斯核示例:

计算过程示例:

代码示例:

python 复制代码
import cv2 as cv
#读图
flower=cv.imread("../images/flower.png")
#灰度化
gray=cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
gray=cv.resize(gray,(480,480))

#自适应二值化,必须结合阈值法或者反阈值法,返回值只有一个
binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,7,10)
cv.imshow("binary", binary)
binary_gauss=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,10)
cv.imshow("adaptive_thresh", binary_gauss)
cv.waitKey(0)
cv.destroyAllWindows()

四、总结

  • 灰度图像生成

    • 最大值法:突出亮部,可能丢失暗部信息。
    • 平均值法:适用于均衡图像,可能降低对比度。
    • 加权平均值法:符合人眼感知,保留重要视觉信息。
  • 二值化处理

    • 阈值法/反阈值法:像素值与阈值比较后全量转换(0或maxval)。
    • 截断阈值法:仅高于阈值的像素被截断为阈值。
    • 低阈值零处理:低于阈值的像素置0,其余保留。
    • 超阈值零处理:高于阈值的像素置0,其余保留。

更多资料:https://www.csdn.net/

相关推荐
Mrliu__6 小时前
Opencv(一): 用Opencv了解图像
人工智能·opencv·计算机视觉
yanxing.D10 小时前
penCV轻松入门_面向python(第七章 图像平滑处理)
图像处理·人工智能·opencv·计算机视觉
Antonio91512 小时前
【图像处理】CMKY色彩空间
图像处理
宇宙浪子13 小时前
在 UOS(统信操作系统,基于 Debian/Ubuntu 体系)上编译 OpenCV 4.10.0
opencv·ubuntu·debian
柳鲲鹏16 小时前
多种方法:OpenCV中修改像素RGB值
前端·javascript·opencv·1024程序员节
不良人龍木木16 小时前
云图-地基云图
图像处理·算法·计算机视觉·1024程序员节
weixin_582985181 天前
OpenCV cv::Mat.type() 以及类型数据转换
c++·opencv·计算机视觉
小殊小殊1 天前
【论文笔记】LTX-Video极致速度的视频生成模型
图像处理·人工智能·深度学习
Antonio9151 天前
【图像处理】图像形态学操作
图像处理·人工智能·opencv