【问题标题】:How to get luminosity of Mat image from opencv?如何从opencv获取Mat图像的亮度?
【发布时间】:2013-03-14 20:02:41
【问题描述】:

我正在使用 C++ 中的 OpenCV 在 iOS 上进行图像处理。有时环境光不够,图像无法正确处理。我没有找到任何合适的方法来检测环境光,因此尝试检测图像的亮度。

This answer 建议使用 YUV 格式的亮度值或 Y。所以我按照this answer在将图像转换为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

【问题讨论】:

    标签: c++ ios opencv image-processing luminance


    【解决方案1】:

    以下是您可以非常简单地做到这一点的方法,对我有用!

    也发布在 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);
    

    【讨论】:

    • 这应该是公认的答案,这实际上是我能找到的使用 C++ 和 Opencv 进行光度计算的唯一明确实现。
    【解决方案2】:

    您的日志输出的原因是您的像素值是 uint8_t 类型,当您尝试将其输出到控制台时,它将被解释为 unsigned char(至少在 iOS 上)。所以日志输出就是那个像素值所代表的字符。要输出相应的数值,请将值转换为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;
    

    此外,您发布的代码三次输出相同的元素,而 bgrPixel 未定义。我也更正了这个 sn-p 中的这些错误。

    如果你只对亮度信息感兴趣,你可以调用

    cv::cvtColor(image, frame_yuv, CV_BGR2GRAY);
    

    和YUV的Y通道做同样的颜色转换,但是效率会更高。

    【讨论】:

    • 抱歉我的错误,我更正了。谢谢你的建议。还有一件事,您是否知道在行for(int i = 0; i &lt; frame_yuv.rows; i+=50) 和列for(int j = 0; j &lt; frame_yuv.cols; j += 50) 中要计算的合适像素数。
    • 恐怕我不太明白你在这里问什么。为什么每次都增加 50?
    • 我的意思是对每个像素进行计算会导致性能不佳,因此我尝试每 50 个像素仅采样 1 个像素以计算对性能影响不大但仍具有足够精度的计算。我正在寻找这个最佳数字。
    • 我认为没有规范的方法可以做到这一点。您可以尝试不同的采样步骤并将它们与真实平均值(或中位数)进行比较,然后选择导致可接受误差的最大步骤。
    • @Protocole - 如果我可以建议一种更快的计算平均亮度的方法,我有一个 GPU 加速的方法,我在这个答案中描述:stackoverflow.com/a/14612913/19679
    猜你喜欢
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2020-04-04
    • 2012-02-03
    相关资源
    最近更新 更多