我一直在尝试在 Opencv 中获取图像亮度,到目前为止,我使用了 calcHist 并考虑了直方图值的平均值。但是,我觉得这并不准确,因为它实际上并不能确定图像的亮度。我在图像的灰度版本上执行了 calcHist,并试图区分从明亮图像获得的平均值与中等图像的平均值。到目前为止,我还没有成功。您能否帮助我提供一种可以通过 OpenCv 实现的方法或算法来估计图像的亮度?提前致谢。
4 回答
我想,HSV 颜色模型对您的问题很有用,其中通道 V 是值:
"值是颜色的明暗度,随颜色饱和度而变化。范围从0到100%。当值为'0'时,颜色空间将是全黑的。随着值的增加,颜色空间的亮度和显示各种颜色。”
所以使用 OpenCV 方法cvCvtColor (const CvArr* src, CvArr* dst, int code),将图像从一种颜色空间转换为另一种颜色空间。在您的情况下,代码 = CV_BGR2HSV.Than 计算第三通道 V 的直方图。
我正要问同样的问题,但后来发现,类似的问题没有给出令人满意的答案。我在 SO 上找到的所有答案都涉及人类对单像素 RGB 与 HSV 的观察。
根据我的观察,图像的主观亮度也很大程度上取决于图案。在白天,黑暗天空中的星星可能看起来比多云的天空更亮,而第一张图像的平均像素值会小得多。
我使用的图像是由显微镜产生的灰度细胞图像。形式差异很大。有时它们是非常黑的背景上的小亮点,有时是不太暗的背景上不太亮的较大区域。
我的做法是:
- 使用去除热像素的阈值查找直方图最大值 (HMax)。
- 计算 HMax * 2/3 和 HMax 之间的所有像素的平均值
比率 2/3 也可以增加到 3/4(这减少了被认为是明亮的像素范围)。
该方法效果很好,因为具有相同滴定度的不同细胞图案会产生相似的亮度。
PS:我真正想问的是,在OpenCV或SimpleCV中是否有类似的计算功能。非常感谢您的任何评论!
我更喜欢Valentin 的回答,但是对于确定平均每像素亮度的“另一种”方法,您可以使用numpy
几何平均值而不是算术平均值。对我来说它有更好的结果。
from numpy.linalg import norm
def brightness(img):
if len(img.shape) == 3:
# Colored RGB or BGR (*Do Not* use HSV images with this function)
# create brightness with euclidean norm
return np.average(norm(img, axis=2)) / np.sqrt(3)
else:
# Grayscale
return np.average(img)
一些 OpenCV C++ 源代码,用于简单检查以区分明暗图像。这是受到@ann-orlova 多年前提供的上述答案的启发:
const int darkness_threshold = 128; // you need to determine what threshold to use
cv::Mat mat = get_image_from_device();
cv::Mat hsv;
cv::cvtColor(mat, hsv, CV_BGR2HSV);
const auto result = cv::mean(hsv);
// cv::mean() will return 3 numbers, one for each channel:
// 0=hue
// 1=saturation
// 2=value (brightness)
if (result[2] < darkness_threshold)
{
process_dark_image(mat);
}
else
{
process_light_image(mat);
}