如何使用opencv有效地完成RGB图像中的复杂阈值?

时间:2016-11-28 13:29:59

标签: c++ matlab opencv image-processing

我想将matlab代码翻译成c ++ opencv,它为RGB图像设置阈值:红色值> 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值。

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

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

1 个答案:

答案 0 :(得分:2)

您无法直接使用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矩阵转换为double(除非它们已经是这样):

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循环,如果你使用指针可以非常快(我假设你的im属于CV_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);
    }
}