如何从OpenCV的Mat图像中获取亮度?

3
我正在使用OpenCV在iOS上进行C++图像处理。有时环境光线不足,图像无法正确处理。我没有找到任何适合的方法来检测环境光,因此尝试检测图像的亮度。 这个答案建议使用YUV格式中的亮度值或Y。所以我按照这个答案的方法,在将图像转换为YUV格式后访问Mat图像中的像素信息。
- (void)processImage:(Mat&)image
{    
    Mat frame_yuv;
    cvtColor( image, frame_yuv, CV_BGR2YUV );

    uint8_t* pixelPtr = (uint8_t*)frame_yuv.data;
    int cn = frame_yuv.channels();
    for(int i = 0; i < frame_yuv.rows; i+=50)
    {
        for(int j = 0; j < frame_yuv.cols; j += 50)
        {
            Scalar_<uint8_t> yuvPixel;
            yuvPixel.val[0] = pixelPtr[i*frame_yuv.cols*cn + j*cn + 0]; // Y
            yuvPixel.val[1] = pixelPtr[i*frame_yuv.cols*cn + j*cn + 1]; // U
            yuvPixel.val[2] = pixelPtr[i*frame_yuv.cols*cn + j*cn + 2]; // V

            // do something with YUV values...
            std::cout << "Y: " << yuvPixel.val[0] << endl;
            std::cout << "U: " << yuvPixel.val[1] << endl;
            std::cout << "V: " << yuvPixel.val[2] << endl;
        }
    }
}

这里有一些日志行,其中包含一些对我来说很奇怪的结果,以我的理解,“Y”、“U”或“V”的值不应该这么多。请建议我错过了什么或做错了什么?非常感谢。

Y: P
U: \204
V: \206
Y: Q
U: \201
V: \207
Y: K
U: \205
V: \211
Y: H
U: \203
V: \210
Y: G
U: \202
V: \210
Y: H
U: \201
V: \210
Y: H
U: \202
V: \211
Y: \326
U: \200
V: \204
Y: \377
U: \200
V: \200
Y: \377
U: \200
V: \200
Y: \377
U: \200
V: \200
Y: \376
U: |
V: \201
Y: \313
U: x
V: \210
Y: \231
U: ~
V: \204
Y: \214
U: ~
V: \204
Y: \205
U: |
V: \204
Y: \221
U: 
V: \202
2个回答

4

以下是一个非常简单的方法,适用于我!

也可以在PasteBin上发布:https://pastebin.com/tA1R8Qtm

// -----------------------------------------------------
// ---------- FIND AVG LUMINENCE OF FRAME --------------
// -----------------------------------------------------

// Assuming you have a cv::Mat to start with called "input_mat"
cv::Mat grayMat; 
cv::cvtColor(input_mat, grayMat, CV_BGR2GRAY);

int Totalintensity = 0;
for (int i=0; i < grayMat.rows; ++i){
    for (int j=0; j < grayMat.cols; ++j){
        Totalintensity += (int)grayMat.at<uchar>(i, j);
    }
}

// Find avg lum of frame
float avgLum = 0;
avgLum = Totalintensity/(grayMat.rows * grayMat.cols);

1
这应该是被采纳的答案,实际上这是我能找到的唯一使用C++和Opencv清晰实现亮度计算的方法。 - Alexander Belokon

2

你的日志输出的原因是你的像素值是 uint8_t 类型,当你尝试将其输出到控制台时,在iOS上至少会被解释为 unsigned char。因此,日志输出是该像素值所表示的字符。要输出相应的数字值,请将该值转换为 int,如下所示:

std::cout << "Y: " << (int)yuvPixel.val[0] << std::endl;
std::cout << "U: " << (int)yuvPixel.val[1] << std::endl;
std::cout << "V: " << (int)yuvPixel.val[2] << std::endl;

此外,您发布的代码输出了相同的元素三次,并且未定义。我已经在这个片段中纠正了这些错误。
如果您只对亮度信息感兴趣,可以改为调用:
cv::cvtColor(image, frame_yuv, CV_BGR2GRAY);

这个功能与YUV的Y通道进行的颜色转换相同,但效率更高。


抱歉我的错误,我已经更正了。感谢您的建议。还有一件事,您有关于在行for(int i = 0; i < frame_yuv.rows; i+=50)和列for(int j = 0; j < frame_yuv.cols; j += 50)中适当计算像素数量的任何想法吗? - Protocole
很抱歉,我不太明白你在这里问什么。而且为什么每次都要增加50呢? - Aurelius
我的意思是每个像素都计算会导致性能不佳,所以我尝试每50个像素只采样1个像素进行计算,以保持足够的准确性但不会对性能产生太大影响。我正在寻找这个最佳数量。 - Protocole
我认为没有一种标准的方法来做这件事。您可以尝试不同的采样步骤,并将它们与真实平均值(或中位数)进行比较,然后选择产生可接受误差的最大步骤。 - Aurelius
1
@Protocole - 如果我可以建议一种更快计算平均亮度的方法,我有一个GPU加速的方案,我在这篇答案中进行了描述:http://stackoverflow.com/a/14612913/19679 - Brad Larson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接