【问题标题】:How to efficiently do complex threshold in RGB image using opencv?如何使用opencv有效地在RGB图像中做复杂的阈值?
【发布时间】:2017-04-12 05:57:01
【问题描述】:

我想将 matlab 代码翻译成 c++ opencv,它对 RGB 图像进行阈值处理:red value>threshold1 AND red/green>threshold2 AND red/blue>threshold3

matlab代码为:

bw=(im(:,:,1)>=red_th&(im(:,:,1)./im(:,:,2))>=red_green_th&(im(:,:,1)./im(:,:,3))>=red_blue_th);

其中im(:,:,1), im(:,:,2)im(:,:,3)分别是r、g、b值。

与使用“for cols and for rows”循环所有像素相比,我发现 matlab 代码非常有效。因此,我想在 opencv 中找到类似的有效方法,而不是循环 cols 和 rows。

我阅读了一些关于cv::threshold and inRange 的信息,但是,它们似乎无法满足我的要求。

【问题讨论】:

    标签: c++ matlab opencv image-processing


    【解决方案1】:

    您不能直接使用 thresholdinRange 执行此操作,但您可以轻松地将其转换为 OpenCV,首先拆分 3 个通道,然后使用矩阵表达式:

    Mat im = ...
    vector<Mat> planes;
    split(im, planes); // B, G, R planes
    
    Mat bw = (planes[2] >= red_th) & 
             (planes[2] / planes[1] >= red_green_th) &
             (planes[2] / planes[0] >= red_blue_th);
    

    由于 Matlab 通常适用于双精度,因此您最好将 OpenCV 矩阵转换为双精度(除非它们已经如此):

    Mat im = ...
    vector<Mat> planes;
    split(im, planes); // B, G, R planes
    
    for(size_t i=0; i<planes.size(); ++i) {
        planes[i].convertTo(planes[i], CV_64F);
    }
    
    Mat bw = (planes[2] >= red_th) & 
             (planes[2] / planes[1] >= red_green_th) &
             (planes[2] / planes[0] >= red_blue_th);
    

    或者您可以使用 for 循环,如果您使用指针,这会非常快(我假设您的 imCV_8UC3 类型):

    Mat3b im = ...
    Mat1b bw(im.rows, im.cols, uchar(0));
    
    int rows = im.rows;
    int cols = im.cols;
    if(im.isContinuous()) {
        cols = rows * cols;
        rows = 1;
    }
    
    for(int r=0; r<rows; ++r) {
        Vec3b* ptr_im = im.ptr<Vec3b>(r);
        uchar* ptr_bw = bw.ptr<uchar>(r)
        for(int c=0; c<cols; ++c) { 
            const Vec3b& bgr = ptr_im[c];
    
            // Take care of division by 0  
    
            ptr_bw[c] = (bgr[2] >= red_th) &&
                        (bgr[2] / bgr[1] >= red_green_th) &&
                        (bgr[2] / bgr[0] >= red_blue_th);
        }
    }
    

    【讨论】:

    • 很高兴它有帮助;D
    • 可能你的类型有问题。 Matlab 中的矩阵通常是 double 类型,而在 OpenCV 中它们可能是 uchar 类型。如果是整数除法问题,则需要在此之前将 OpenCV 矩阵转换为 double
    • 只是一个更新。第二点解决方案的工作原理是避免除以 0。 ptr_bw[c] = (bgr[2]>=red_th)&&(bgr[1]==0||(bgr[2]/bgr[1]>=red_green_th) )&&(bgr[0]==0||(bgr[2]/bgr[0]>=red_blue_th));体重=体重*255;但是,第一个拆分方案效果不佳,结果是错误的(与matlab代码的结果相差很大)。似乎 (planes[2]/planes[0]) 有一些问题。我不确定这是否是数据类型问题。你知道为什么吗?
    • 我尝试了新的拆分代码,它仍然有一些问题。无论如何,第二点解决方案效果很好,速度很快。
    猜你喜欢
    • 2014-11-30
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2021-09-12
    相关资源
    最近更新 更多