通过灰度变换对彩图使用自适应阈值

通过灰度变换对彩图使用自适应阈值

OpenCV 提供了灰度图的自适应阈值,可以在环境变化的情况下仍然保证识别结果,但是该函数只适用于灰度图,并不能直接应用于 RGB 或 HSV 图像,本文通过一种自由颜色方向的颜色灰度变换,来使某些颜色在灰度图像中更加突出,便于应用自适应阈值。

实现思路

  • 传入一张彩色图像,RGB/BGR/HSV 都可以
  • 给定要突出的颜色,或者图像各个通道的权重
  • 根据通道的权重,获取到该颜色在色盘上面的位置,将这个位置与色盘中心做向量,使这个方向上最远的颜色在灰度图中为白色,相反方向为黑色
  • 将上一步中得到的标准化权重与原图的每个像素的颜色值相乘,即可得到灰度值

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import cv2 
import numpy as np

def color2gray(img, convertor, weight=[1, 1, 1]):
assert len(weight) == 3, "Weight must be a 3-element list"
assert sum(weight) != 0, "Weight must not be all zeros"
assert len(img.shape) == 3, "Input image must be a 3D array"
assert convertor in [
"3c2gray",
"hsv2gray",
], f"Convertor {convertor} is not supported"

# 标准化权重向量,使其模为1,这样可以使在输出的灰度图像中,完全符合权重向量的颜色为白色
normalise = lambda W: W / np.sqrt(np.sum(W**2))
# 不同的转换器对应的标准颜色
std_color = (
np.array([255, 255, 255])
if convertor == "3c2gray"
else np.array([180, 255, 255])
)

normalised_weight = normalise(np.array(weight))
norm_img = img / np.sqrt(np.sum(std_color**2))
gray_img = np.dot(norm_img, normalised_weight)
gray_img = (gray_img * 255).astype(np.uint8)
return gray_img

效果

  • 当权重等于白色或灰色时,转换的灰度结果和普通转换没有差别

    image-20240510221202053

  • 当权重不等于白色或灰色时,可以把某种颜色突出

    image-20240510221323788

    image-20240510221353566

由此可见,当前环境可以通过将权值设置为 [1, 0, 0] 来将目标盒子在图像中突出出来,更方便进行阈值框定或自适应阈值。