Jun Fang - 1 year ago 87
C++ Question

# How to efficiently do complex threshold in RGB image using opencv?

I want to translate a matlab code into c++ opencv, it threshold a RGB image: red value>threshold1 AND red/green>threshold2 AND red/blue>threshold3

The matlab code is:

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

Where
`im(:,:,1), im(:,:,2)`
and
`im(:,:,3)`
is the r, g, b value respectively.

I found the matlab code is very efficient comparing with looping all pixels using "for cols and for rows". Hence, I want to find similar efficient method in opencv instead of looping cols and rows.

`cv::threshold and inRange`
, however, it seems that they cannot satisfy my requirement.

You can't do this directly with `threshold` or `inRange`, but you can easily convert this to OpenCV first splitting the 3 channels, and then using Matrix Expressions:

``````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);
``````

Since Matlab usually works on doubles, you'd better convert the OpenCV matrices to double (unless they are already so):

``````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);
``````

Or you can for loops, which can be very fast if you work on pointers (I'm assuming your `im` is of type `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);
}
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download