【问题标题】:Finding the max colour pixel based on the value in one channel in OpenCV根据OpenCV中一个通道中的值查找最大颜色像素
【发布时间】:2014-03-07 08:46:33
【问题描述】:

我最近开始使用 OpenCV 处理图像。

据我所知,cv::max(input1, input2, output) 用于查找 2 张图像的最大 BGR 值。我想在一个颜色通道内最大化,请参阅以下示例以获取 2 个 BGR 垫(垫尺寸 2x2):

input1= [110, 100, 90, 109, 99, 89; 111, 99, 89, 108, 98, 88]

inout2= [97, 141, 158, 95, 138, 157; 98, 149, 169, 97, 148, 168]

我只想最大化蓝色通道中的值,因此我会将绿色和红色通道的任何值带到我的输出垫;因此我希望结果是这样的:

output= [110, 100, 90, 109, 99, 89; 111, 99, 89, 108, 98, 88]

是的,它恰好是输出 mat 成为 input1 的副本,但请注意运行 cv::max(input1, input2, output); 给了

output= [110, 141, 158, 109, 138, 157; 111, 149, 169, 108, 148, 168]

它以某种方式混合了 2 个垫子通道。

抱歉写了这么长;我只是想清楚一点。谢谢,,,

更新:我已经使用 C++ for 循环实现了一个解决方案。老实说,它们可以工作,但我正在寻找更快、更简单的东西,如果有的话。

UPDATE2:从 2 个输入图像中,我需要来自蓝色通道的最大值,并将其与相关的绿色和红色值一起存储到输出中。

【问题讨论】:

    标签: c++ arrays opencv comparison mat


    【解决方案1】:

    您可以分割图像,计算所需通道的最大值,然后将其合并到输出数组中。并不简单,但我认为它比经典的 for 循环方法更好。这是我在有限的时间内写的,它可以按照你的意愿工作。

    int ssz[2] = {2,2};
    
    double data1[12] = {110,100,90,109,99,89,111,99,89,108,98,88}; 
    double  data2[12] = {120,141,158,95,138,157,98,149,169,97,148,168};
    
    Mat in1(2,ssz,CV_64FC3,data1);
    Mat in2(2,ssz,CV_64FC3,data2);
    
    Mat out = in1.clone();
    
    
    Mat c1[3];      //0 indexes will be blue channel
    Mat c2[3];
    Mat oc[3];
    
    split(in1,c1);
    split(in2,c2);
    split(out,oc);
    
    cv::max(c1[0],c2[0],oc[0]);
    cv::merge(oc,3,out);
    

    为了看到它有效,我将 input2 的第一个元素更改为 120。我测试和调试,它有效。

    【讨论】:

    • 感谢您的努力,但您的代码给出了不同的答案。它确实在一个通道中找到最大值,但它仅从 in1 Mat out = in1.clone() 获取关联的绿色和红色值。
    • 准确地说,输出的第一个像素是120, 100, 90,根据代码,应该是120, 141, 158。事实上,我希望指针可以完成这项工作。但不知道如何:D
    • 我认为您在这里感到困惑。如果您有彩色图像,则分别为 B、G、R。所以图像中的第一个像素将有 3 个值 BGR。而且您只想最大化蓝色通道。所以这就是你应该通过最大化你的输入值得到的,这也与你预期的输出相同。还有一件事,我将输出分配给 input1 的克隆,因为你没有说任何关于输出的内容。你可以采用另一个 3 通道输出数组从其他地方,拆分它,在第一个通道(蓝色)上使用最大值而不是再次合并它。它将再次工作并将蓝色通道最大化到输出的蓝色通道
    • 先生,很抱歉我的要求不是很清楚。我不仅在一个频道中找到最大值;我希望它在其他通道中的关联值保持不变并将这个像素存储到输出垫中。在您的代码中,让我们看看 in1 (110, 100, 90) 和 in2 (120, 141, 158) 中的 BGR 像素 (0,0)。我的要求是选择 in2 中的像素(其 BGR 值完好无损)作为最大值并将其放置在输出垫中,因为它的值,比如在蓝色通道中,大于 in1 中的蓝色值(110
    • 我运行了你的代码,它在输出垫中给了我 (120, 100, 90);我相信来自 in2 的 120 而来自 in1 的 100 和 90 因为它们之前是用 in1.clone() 复制的。我把它改成in2.clone(),像素(0,0)没问题,但其他像素不是:)
    【解决方案2】:

    我使用经典的 C++ for 循环来实现这一点,这就是我擅长的:D 但是,我仍然期待一个更好的答案,至少在避免 .at 方面。

    int imdepth=CV_32F;
    Mat outBlue (2, 2, imdepth);
    Mat outGreen (2, 2, imdepth);
    Mat outRed (2, 2, imdepth);
    for (int i=0; i<2; i++) {
        for (int j=0; j<2; j++) {
            float blue1 = in1b.at<float>(i,j);   //in1b, in2b, in1g, etc. are
            float blue2 = in2b.at<float>(i,j);   //channels from img1 and img2
            if (blue1>blue2) {
                outBlue.at<float>(i,j)  = blue1;
                outGreen.at<float>(i,j) = in1g.at<float>(i,j);
                outRed.at<float>(i,j)   = in1r.at<float>(i,j);
            } else {
                outBlue.at<float>(i,j)  = blue2;
                outGreen.at<float>(i,j) = in2g.at<float>(i,j);
                outRed.at<float>(i,j)   = in2r.at<float>(i,j);
            }
        }
    }
    vector<Mat> out(3);
    out[0]  = outBlue;
    out[1]  = outGreen;
    out[2]  = outRed;
    Mat output (2, 2, CV_32FC3);
    merge (out, output);
    

    【讨论】:

    • @yutasrobot:请看我的代码,它可能会给你一个线索。欢迎提出建议:)
    猜你喜欢
    • 1970-01-01
    • 2021-12-31
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2022-05-21
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多