两个图像的乘积,其中图像在OPEN CV中具有不同的模型

Multiplication of 2 images where the images have different models in OPEN CV

本文关键字:图像 CV OPEN 模型 两个      更新时间:2023-10-16

我正在尝试将不同模型的两个图像相乘,在我的例子中是HSV和YCRCB
我每次都会得到"向量越界错误"。我已经检查了要相乘的输入图像的大小、行和列的数量。我知道这个值超过了255。
我试图实现这种方法opencv-image乘法,但代码有很多MAT必须初始化。这也让我提出了一个问题,即具有1个以上通道的图像是否可以相乘。也尝试了直接乘法,但它不起作用,所以尝试了按通道相乘。为了让事情变得更容易,我使用了循环方法,但随后出现了错误。

关于代码和原因的简短总结:我将其用于皮肤检测,但希望进一步减少噪音。我认为这可以通过将阈值运算生成的2个输出图像相乘来实现(对于HSV&YCRCB)。由于这些图像在图像中具有不同的噪声,因此乘法的输出将具有更少的噪声(我在不同的屏幕上看到了输出,重叠区域非常小),因此这几乎可以随时检测皮肤颜色,并且噪声将是最小的,因此将有助于更好地跟踪皮肤。

下面给出的代码并不完整,因为它永远不会执行到最后。之后进行形态学和扩张操作,仅此而已。
这是我第一次在Stack Overflow上提问,我还在学习Open CV。对不起,如果我描述得太多了,欢迎所有建议。非常感谢。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencvcv.h>
#include <opencvhighgui.h>
#include <iostream>
#include <opencv2imgprocimgproc.hpp>
    using namespace cv;
    using namespace std;
    char key;
    Mat image,hsv,ycr;
    vector<Mat> channels,ycrs,threshold_output;   
     int main()
        {       
        VideoCapture cap(0); // open the default camera
            if(!cap.isOpened())  // check if we succeeded
                {
                 cout << "Cannot open the web cam" << endl;
                 return -1;
            }
        while(1)
        {
            cap>>image;
              cvtColor( image, ycr, CV_BGR2YCrCb ); //Converts into YCRCB 
              cvtColor( image, hsv, CV_BGR2HSV ); //Converts into HSV 
              Mat imgThresholded;
              Mat imgThresholded1;
              inRange(ycr, Scalar(0, 140,105 ), Scalar(255, 165,135), imgThresholded1); //for yrcrcb range
              inRange(hsv, Scalar(0, 48,150 ), Scalar(20, 150,255), imgThresholded); //for hsv range
    split(imgThresholded1, channels);
    split(imgThresholded, ycrs);
    for( int i = 0; i <3 ; i++ )
    {
        multiply(channels[i],ycrs[i], threshold_output[i], 1,-1 );
    }//code breaks here 

即使inRange的输入是多通道的,inRange的输出也将是单通道CV_8UC1

原因是inRange计算了一个笛卡尔交点:

  • 如果ALL为true,则结果(x,y)为true(uchar为255):
    • 对于第一个通道,lower[0] <= img(x, y)[0] <= upper[0]AND
    • 对于第二个通道lower[1] <= img(x, y)[1] <= upper[1]AND
    • 等等

换句话说,在根据下限和上限检查每个通道的像素值后,逻辑结果是图像通道上的逻辑与运算。

"Boiled down"是我的口语化方式,指的是归约或折叠,其中函数可以接受任意数量的参数,并且可以"归约"为单个值。求和、乘法、字符串串联等

因此,没有必要在cv::inRange的输出上使用cv::split。事实上,因为输出只有一个通道,所以调用channels[1]ycrs[1]将是一种未定义的行为,这将导致调试构建异常和未定义行为,或者导致发布构建崩溃或内存损坏。